summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/glslang/src/glslang/MachineIndependent
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/glslang/src/glslang/MachineIndependent')
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Constant.cpp965
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/InfoSink.cpp109
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp4312
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.h113
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/IntermTraverse.cpp302
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp1980
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp6164
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h388
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/PoolAlloc.cpp347
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.cpp118
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.h39
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp1331
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.h265
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/ScanContext.h86
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp1623
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp351
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.h694
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp677
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.h185
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/gl_types.h160
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/glslang.y2703
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp7685
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h369
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp864
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/limits.cpp198
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp1050
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h396
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp210
-rwxr-xr-xchromium/third_party/glslang/src/glslang/MachineIndependent/parseVersions.h135
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp1151
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp192
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp122
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h570
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp162
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp778
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp135
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp278
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h171
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp859
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.h53
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp761
-rw-r--r--chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.h134
42 files changed, 39185 insertions, 0 deletions
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Constant.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/Constant.cpp
new file mode 100644
index 00000000000..03033bce821
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Constant.cpp
@@ -0,0 +1,965 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "localintermediate.h"
+#include <cmath>
+#include <cfloat>
+#include <cstdlib>
+
+namespace {
+
+using namespace glslang;
+
+typedef union {
+ double d;
+ int i[2];
+} DoubleIntUnion;
+
+// Some helper functions
+
+bool isNan(double x)
+{
+ DoubleIntUnion u;
+ // tough to find a platform independent library function, do it directly
+ u.d = x;
+ int bitPatternL = u.i[0];
+ int bitPatternH = u.i[1];
+ return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
+ ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
+}
+
+bool isInf(double x)
+{
+ DoubleIntUnion u;
+ // tough to find a platform independent library function, do it directly
+ u.d = x;
+ int bitPatternL = u.i[0];
+ int bitPatternH = u.i[1];
+ return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
+ (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
+}
+
+const double pi = 3.1415926535897932384626433832795;
+
+} // end anonymous namespace
+
+
+namespace glslang {
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+// Note: As of version 1.2, all constant operations must be folded. It is
+// not opportunistic, but rather a semantic requirement.
+//
+
+//
+// Do folding between a pair of nodes.
+// 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
+//
+// Returns a new node representing the result.
+//
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
+{
+ // For most cases, the return type matches the argument type, so set that
+ // up and just code to exceptions below.
+ TType returnType;
+ returnType.shallowCopy(getType());
+
+ //
+ // A pair of nodes is to be folded together
+ //
+
+ const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
+ TConstUnionArray leftUnionArray = getConstArray();
+ TConstUnionArray rightUnionArray = rightNode->getConstArray();
+
+ // Figure out the size of the result
+ int newComps;
+ int constComps;
+ switch(op) {
+ case EOpMatrixTimesMatrix:
+ newComps = rightNode->getMatrixCols() * getMatrixRows();
+ break;
+ case EOpMatrixTimesVector:
+ newComps = getMatrixRows();
+ break;
+ case EOpVectorTimesMatrix:
+ newComps = rightNode->getMatrixCols();
+ break;
+ default:
+ newComps = getType().computeNumComponents();
+ constComps = rightConstantNode->getType().computeNumComponents();
+ if (constComps == 1 && newComps > 1) {
+ // for a case like vec4 f = vec4(2,3,4,5) + 1.2;
+ TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
+ rightUnionArray = smearedArray;
+ } else if (constComps > 1 && newComps == 1) {
+ // for a case like vec4 f = 1.2 + vec4(2,3,4,5);
+ newComps = constComps;
+ rightUnionArray = rightNode->getConstArray();
+ TConstUnionArray smearedArray(newComps, getConstArray()[0]);
+ leftUnionArray = smearedArray;
+ returnType.shallowCopy(rightNode->getType());
+ }
+ break;
+ }
+
+ TConstUnionArray newConstArray(newComps);
+ TType constBool(EbtBool, EvqConst);
+
+ switch(op) {
+ case EOpAdd:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
+ break;
+ case EOpSub:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
+ break;
+
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpMatrixTimesScalar:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
+ break;
+ case EOpMatrixTimesMatrix:
+ for (int row = 0; row < getMatrixRows(); row++) {
+ for (int column = 0; column < rightNode->getMatrixCols(); column++) {
+ double sum = 0.0f;
+ for (int i = 0; i < rightNode->getMatrixRows(); i++)
+ sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
+ newConstArray[column * getMatrixRows() + row].setDConst(sum);
+ }
+ }
+ returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
+ break;
+ case EOpDiv:
+ for (int i = 0; i < newComps; i++) {
+ switch (getType().getBasicType()) {
+ case EbtDouble:
+ case EbtFloat:
+ newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
+ break;
+
+ case EbtInt:
+ if (rightUnionArray[i] == 0)
+ newConstArray[i].setIConst(0x7FFFFFFF);
+ else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)0x80000000)
+ newConstArray[i].setIConst(0x80000000);
+ else
+ newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
+ break;
+
+ case EbtUint:
+ if (rightUnionArray[i] == 0) {
+ newConstArray[i].setUConst(0xFFFFFFFF);
+ } else
+ newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
+ break;
+
+ case EbtInt64:
+ if (rightUnionArray[i] == 0)
+ newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
+ else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)0x8000000000000000)
+ newConstArray[i].setI64Const(0x8000000000000000);
+ else
+ newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
+ break;
+
+ case EbtUint64:
+ if (rightUnionArray[i] == 0) {
+ newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
+ } else
+ newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
+ break;
+ default:
+ return 0;
+ }
+ }
+ break;
+
+ case EOpMatrixTimesVector:
+ for (int i = 0; i < getMatrixRows(); i++) {
+ double sum = 0.0f;
+ for (int j = 0; j < rightNode->getVectorSize(); j++) {
+ sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
+ }
+ newConstArray[i].setDConst(sum);
+ }
+
+ returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
+ break;
+
+ case EOpVectorTimesMatrix:
+ for (int i = 0; i < rightNode->getMatrixCols(); i++) {
+ double sum = 0.0f;
+ for (int j = 0; j < getVectorSize(); j++)
+ sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
+ newConstArray[i].setDConst(sum);
+ }
+
+ returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
+ break;
+
+ case EOpMod:
+ for (int i = 0; i < newComps; i++) {
+ if (rightUnionArray[i] == 0)
+ newConstArray[i] = leftUnionArray[i];
+ else
+ newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
+ }
+ break;
+
+ case EOpRightShift:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
+ break;
+
+ case EOpLeftShift:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
+ break;
+
+ case EOpAnd:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
+ break;
+ case EOpInclusiveOr:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
+ break;
+ case EOpExclusiveOr:
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
+ break;
+
+ case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
+ break;
+
+ case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+ for (int i = 0; i < newComps; i++)
+ newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
+ break;
+
+ case EOpLogicalXor:
+ for (int i = 0; i < newComps; i++) {
+ switch (getType().getBasicType()) {
+ case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
+ default: assert(false && "Default missing");
+ }
+ }
+ break;
+
+ case EOpLessThan:
+ newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpGreaterThan:
+ newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpLessThanEqual:
+ newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpGreaterThanEqual:
+ newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpEqual:
+ newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
+ returnType.shallowCopy(constBool);
+ break;
+ case EOpNotEqual:
+ newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
+ returnType.shallowCopy(constBool);
+ break;
+
+ default:
+ return 0;
+ }
+
+ TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
+ newNode->setLoc(getLoc());
+
+ return newNode;
+}
+
+//
+// Do single unary node folding
+//
+// Returns a new node representing the result.
+//
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
+{
+ // First, size the result, which is mostly the same as the argument's size,
+ // but not always, and classify what is componentwise.
+ // Also, eliminate cases that can't be compile-time constant.
+ int resultSize;
+ bool componentWise = true;
+
+ int objectSize = getType().computeNumComponents();
+ switch (op) {
+ case EOpDeterminant:
+ case EOpAny:
+ case EOpAll:
+ case EOpLength:
+ componentWise = false;
+ resultSize = 1;
+ break;
+
+ case EOpEmitStreamVertex:
+ case EOpEndStreamPrimitive:
+ // These don't actually fold
+ return 0;
+
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ componentWise = false;
+ resultSize = 1;
+ break;
+
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpUnpackHalf2x16:
+ componentWise = false;
+ resultSize = 2;
+ break;
+
+ case EOpNormalize:
+ componentWise = false;
+ resultSize = objectSize;
+ break;
+
+ default:
+ resultSize = objectSize;
+ break;
+ }
+
+ // Set up for processing
+ TConstUnionArray newConstArray(resultSize);
+ const TConstUnionArray& unionArray = getConstArray();
+
+ // Process non-component-wise operations
+ switch (op) {
+ case EOpLength:
+ case EOpNormalize:
+ {
+ double sum = 0;
+ for (int i = 0; i < objectSize; i++)
+ sum += unionArray[i].getDConst() * unionArray[i].getDConst();
+ double length = sqrt(sum);
+ if (op == EOpLength)
+ newConstArray[0].setDConst(length);
+ else {
+ for (int i = 0; i < objectSize; i++)
+ newConstArray[i].setDConst(unionArray[i].getDConst() / length);
+ }
+ break;
+ }
+
+ // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
+
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpUnpackHalf2x16:
+
+ case EOpDeterminant:
+ case EOpMatrixInverse:
+ case EOpTranspose:
+
+ case EOpAny:
+ case EOpAll:
+ return 0;
+
+ default:
+ assert(componentWise);
+ break;
+ }
+
+ // Turn off the componentwise loop
+ if (! componentWise)
+ objectSize = 0;
+
+ // Process component-wise operations
+ for (int i = 0; i < objectSize; i++) {
+ switch (op) {
+ case EOpNegative:
+ switch (getType().getBasicType()) {
+ case EbtDouble:
+ case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
+ case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+ case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
+ case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
+ case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getU64Const()))); break;
+ default:
+ return 0;
+ }
+ break;
+ case EOpLogicalNot:
+ case EOpVectorLogicalNot:
+ switch (getType().getBasicType()) {
+ case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
+ default:
+ return 0;
+ }
+ break;
+ case EOpBitwiseNot:
+ newConstArray[i] = ~unionArray[i];
+ break;
+ case EOpRadians:
+ newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
+ break;
+ case EOpDegrees:
+ newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
+ break;
+ case EOpSin:
+ newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
+ break;
+ case EOpCos:
+ newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
+ break;
+ case EOpTan:
+ newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
+ break;
+ case EOpAsin:
+ newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
+ break;
+ case EOpAcos:
+ newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
+ break;
+ case EOpAtan:
+ newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
+ break;
+
+ case EOpDPdx:
+ case EOpDPdy:
+ case EOpFwidth:
+ case EOpDPdxFine:
+ case EOpDPdyFine:
+ case EOpFwidthFine:
+ case EOpDPdxCoarse:
+ case EOpDPdyCoarse:
+ case EOpFwidthCoarse:
+ // The derivatives are all mandated to create a constant 0.
+ newConstArray[i].setDConst(0.0);
+ break;
+
+ case EOpExp:
+ newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
+ break;
+ case EOpLog:
+ newConstArray[i].setDConst(log(unionArray[i].getDConst()));
+ break;
+ case EOpExp2:
+ {
+ const double inv_log2_e = 0.69314718055994530941723212145818;
+ newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
+ break;
+ }
+ case EOpLog2:
+ {
+ const double log2_e = 1.4426950408889634073599246810019;
+ newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
+ break;
+ }
+ case EOpSqrt:
+ newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
+ break;
+ case EOpInverseSqrt:
+ newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
+ break;
+
+ case EOpAbs:
+ if (unionArray[i].getType() == EbtDouble)
+ newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
+ else if (unionArray[i].getType() == EbtInt)
+ newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
+ else
+ newConstArray[i] = unionArray[i];
+ break;
+ case EOpSign:
+ #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
+ if (unionArray[i].getType() == EbtDouble)
+ newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
+ else
+ newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
+ break;
+ case EOpFloor:
+ newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
+ break;
+ case EOpTrunc:
+ if (unionArray[i].getDConst() > 0)
+ newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
+ else
+ newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
+ break;
+ case EOpRound:
+ newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
+ break;
+ case EOpRoundEven:
+ {
+ double flr = floor(unionArray[i].getDConst());
+ bool even = flr / 2.0 == floor(flr / 2.0);
+ double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
+ newConstArray[i].setDConst(rounded);
+ break;
+ }
+ case EOpCeil:
+ newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
+ break;
+ case EOpFract:
+ {
+ double x = unionArray[i].getDConst();
+ newConstArray[i].setDConst(x - floor(x));
+ break;
+ }
+
+ case EOpIsNan:
+ {
+ newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
+ break;
+ }
+ case EOpIsInf:
+ {
+ newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
+ break;
+ }
+
+ // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
+
+ case EOpSinh:
+ case EOpCosh:
+ case EOpTanh:
+ case EOpAsinh:
+ case EOpAcosh:
+ case EOpAtanh:
+
+ case EOpFloatBitsToInt:
+ case EOpFloatBitsToUint:
+ case EOpIntBitsToFloat:
+ case EOpUintBitsToFloat:
+ case EOpDoubleBitsToInt64:
+ case EOpDoubleBitsToUint64:
+
+ default:
+ return 0;
+ }
+ }
+
+ TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
+ newNode->getWritableType().getQualifier().storage = EvqConst;
+ newNode->setLoc(getLoc());
+
+ return newNode;
+}
+
+//
+// Do constant folding for an aggregate node that has all its children
+// as constants and an operator that requires constant folding.
+//
+TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
+{
+ if (! areAllChildConst(aggrNode))
+ return aggrNode;
+
+ if (aggrNode->isConstructor())
+ return foldConstructor(aggrNode);
+
+ TIntermSequence& children = aggrNode->getSequence();
+
+ // First, see if this is an operation to constant fold, kick out if not,
+ // see what size the result is if so.
+
+ bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
+ int objectSize;
+ switch (aggrNode->getOp()) {
+ case EOpAtan:
+ case EOpPow:
+ case EOpMin:
+ case EOpMax:
+ case EOpMix:
+ case EOpClamp:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ case EOpVectorEqual:
+ case EOpVectorNotEqual:
+ componentwise = true;
+ objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
+ break;
+ case EOpCross:
+ case EOpReflect:
+ case EOpRefract:
+ case EOpFaceForward:
+ objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
+ break;
+ case EOpDistance:
+ case EOpDot:
+ objectSize = 1;
+ break;
+ case EOpOuterProduct:
+ objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
+ children[1]->getAsTyped()->getType().getVectorSize();
+ break;
+ case EOpStep:
+ componentwise = true;
+ objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
+ children[1]->getAsTyped()->getType().getVectorSize());
+ break;
+ case EOpSmoothStep:
+ componentwise = true;
+ objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
+ children[2]->getAsTyped()->getType().getVectorSize());
+ break;
+ default:
+ return aggrNode;
+ }
+ TConstUnionArray newConstArray(objectSize);
+
+ TVector<TConstUnionArray> childConstUnions;
+ for (unsigned int arg = 0; arg < children.size(); ++arg)
+ childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
+
+ // Second, do the actual folding
+
+ bool isFloatingPoint = children[0]->getAsTyped()->getBasicType() == EbtFloat ||
+ children[0]->getAsTyped()->getBasicType() == EbtDouble;
+ bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt ||
+ children[0]->getAsTyped()->getBasicType() == EbtInt64;
+ bool isInt64 = children[0]->getAsTyped()->getBasicType() == EbtInt64 ||
+ children[0]->getAsTyped()->getBasicType() == EbtUint64;
+ if (componentwise) {
+ for (int comp = 0; comp < objectSize; comp++) {
+
+ // some arguments are scalars instead of matching vectors; simulate a smear
+ int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
+ int arg1comp = 0;
+ if (children.size() > 1)
+ arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
+ int arg2comp = 0;
+ if (children.size() > 2)
+ arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
+
+ switch (aggrNode->getOp()) {
+ case EOpAtan:
+ newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ break;
+ case EOpPow:
+ newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ break;
+ case EOpMin:
+ if (isFloatingPoint)
+ newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ else if (isSigned) {
+ if (isInt64)
+ newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
+ else
+ newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
+ } else {
+ if (isInt64)
+ newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
+ else
+ newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+ }
+ break;
+ case EOpMax:
+ if (isFloatingPoint)
+ newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
+ else if (isSigned) {
+ if (isInt64)
+ newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
+ else
+ newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
+ } else {
+ if (isInt64)
+ newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
+ else
+ newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
+ }
+ break;
+ case EOpClamp:
+ if (isFloatingPoint)
+ newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
+ childConstUnions[2][arg2comp].getDConst()));
+ else if (isSigned) {
+ if (isInt64)
+ newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
+ childConstUnions[2][arg2comp].getI64Const()));
+ else
+ newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
+ childConstUnions[2][arg2comp].getIConst()));
+ } else {
+ if (isInt64)
+ newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
+ childConstUnions[2][arg2comp].getU64Const()));
+ else
+ newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
+ childConstUnions[2][arg2comp].getUConst()));
+ }
+ break;
+ case EOpLessThan:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
+ break;
+ case EOpGreaterThan:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
+ break;
+ case EOpLessThanEqual:
+ newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
+ break;
+ case EOpGreaterThanEqual:
+ newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
+ break;
+ case EOpVectorEqual:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
+ break;
+ case EOpVectorNotEqual:
+ newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
+ break;
+ case EOpMix:
+ if (children[2]->getAsTyped()->getBasicType() == EbtBool)
+ newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
+ childConstUnions[0][arg0comp].getDConst());
+ else
+ newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
+ childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
+ break;
+ case EOpStep:
+ newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
+ break;
+ case EOpSmoothStep:
+ {
+ double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
+ (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
+ if (t < 0.0)
+ t = 0.0;
+ if (t > 1.0)
+ t = 1.0;
+ newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
+ break;
+ }
+ default:
+ return aggrNode;
+ }
+ }
+ } else {
+ // Non-componentwise...
+
+ int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
+ double dot;
+
+ switch (aggrNode->getOp()) {
+ case EOpDistance:
+ {
+ double sum = 0.0;
+ for (int comp = 0; comp < numComps; ++comp) {
+ double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
+ sum += diff * diff;
+ }
+ newConstArray[0].setDConst(sqrt(sum));
+ break;
+ }
+ case EOpDot:
+ newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
+ break;
+ case EOpCross:
+ newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
+ newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
+ newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
+ break;
+ case EOpFaceForward:
+ // If dot(Nref, I) < 0 return N, otherwise return –N: Arguments are (N, I, Nref).
+ dot = childConstUnions[1].dot(childConstUnions[2]);
+ for (int comp = 0; comp < numComps; ++comp) {
+ if (dot < 0.0)
+ newConstArray[comp] = childConstUnions[0][comp];
+ else
+ newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
+ }
+ break;
+ case EOpReflect:
+ // I - 2 * dot(N, I) * N: Arguments are (I, N).
+ dot = childConstUnions[0].dot(childConstUnions[1]);
+ dot *= 2.0;
+ for (int comp = 0; comp < numComps; ++comp)
+ newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
+ break;
+ case EOpRefract:
+ {
+ // Arguments are (I, N, eta).
+ // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
+ // if (k < 0.0)
+ // return dvec(0.0)
+ // else
+ // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
+ dot = childConstUnions[0].dot(childConstUnions[1]);
+ double eta = childConstUnions[2][0].getDConst();
+ double k = 1.0 - eta * eta * (1.0 - dot * dot);
+ if (k < 0.0) {
+ for (int comp = 0; comp < numComps; ++comp)
+ newConstArray[comp].setDConst(0.0);
+ } else {
+ for (int comp = 0; comp < numComps; ++comp)
+ newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
+ }
+ break;
+ }
+ case EOpOuterProduct:
+ {
+ int numRows = numComps;
+ int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
+ for (int row = 0; row < numRows; ++row)
+ for (int col = 0; col < numCols; ++col)
+ newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
+ break;
+ }
+ default:
+ return aggrNode;
+ }
+ }
+
+ TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
+ newNode->getWritableType().getQualifier().storage = EvqConst;
+ newNode->setLoc(aggrNode->getLoc());
+
+ return newNode;
+}
+
+bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
+{
+ bool allConstant = true;
+
+ // check if all the child nodes are constants so that they can be inserted into
+ // the parent node
+ if (aggrNode) {
+ TIntermSequence& childSequenceVector = aggrNode->getSequence();
+ for (TIntermSequence::iterator p = childSequenceVector.begin();
+ p != childSequenceVector.end(); p++) {
+ if (!(*p)->getAsTyped()->getAsConstantUnion())
+ return false;
+ }
+ }
+
+ return allConstant;
+}
+
+TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
+{
+ bool error = false;
+
+ TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
+ if (aggrNode->getSequence().size() == 1)
+ error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
+ else
+ error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
+
+ if (error)
+ return aggrNode;
+
+ return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
+}
+
+//
+// Constant folding of a bracket (array-style) dereference or struct-like dot
+// dereference. Can handle anything except a multi-character swizzle, though
+// all swizzles may go to foldSwizzle().
+//
+TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
+{
+ TType dereferencedType(node->getType(), index);
+ dereferencedType.getQualifier().storage = EvqConst;
+ TIntermTyped* result = 0;
+ int size = dereferencedType.computeNumComponents();
+
+ // arrays, vectors, matrices, all use simple multiplicative math
+ // while structures need to add up heterogeneous members
+ int start;
+ if (node->isArray() || ! node->isStruct())
+ start = size * index;
+ else {
+ // it is a structure
+ assert(node->isStruct());
+ start = 0;
+ for (int i = 0; i < index; ++i)
+ start += (*node->getType().getStruct())[i].type->computeNumComponents();
+ }
+
+ result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
+
+ if (result == 0)
+ result = node;
+ else
+ result->setType(dereferencedType);
+
+ return result;
+}
+
+//
+// Make a constant vector node or constant scalar node, representing a given
+// constant vector and constant swizzle into it.
+//
+TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TVectorFields& fields, const TSourceLoc& loc)
+{
+ const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
+ TConstUnionArray constArray(fields.num);
+
+ for (int i = 0; i < fields.num; i++)
+ constArray[i] = unionArray[fields.offsets[i]];
+
+ TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
+
+ if (result == 0)
+ result = node;
+ else
+ result->setType(TType(node->getBasicType(), EvqConst, fields.num));
+
+ return result;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/InfoSink.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/InfoSink.cpp
new file mode 100644
index 00000000000..2e8888270b7
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/InfoSink.cpp
@@ -0,0 +1,109 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/InfoSink.h"
+
+#include <string.h>
+
+namespace glslang {
+
+void TInfoSinkBase::append(const char* s)
+{
+ if (outputStream & EString) {
+ checkMem(strlen(s));
+ sink.append(s);
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger)
+// OutputDebugString(s);
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", s);
+}
+
+void TInfoSinkBase::append(int count, char c)
+{
+ if (outputStream & EString) {
+ checkMem(count);
+ sink.append(count, c);
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger) {
+// char str[2];
+// str[0] = c;
+// str[1] = '\0';
+// OutputDebugString(str);
+// }
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%c", c);
+}
+
+void TInfoSinkBase::append(const TPersistString& t)
+{
+ if (outputStream & EString) {
+ checkMem(t.size());
+ sink.append(t);
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger)
+// OutputDebugString(t.c_str());
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", t.c_str());
+}
+
+void TInfoSinkBase::append(const TString& t)
+{
+ if (outputStream & EString) {
+ checkMem(t.size());
+ sink.append(t.c_str());
+ }
+
+//#ifdef _WIN32
+// if (outputStream & EDebugger)
+// OutputDebugString(t.c_str());
+//#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", t.c_str());
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp
new file mode 100644
index 00000000000..6a9fb20192c
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp
@@ -0,0 +1,4312 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2016 LunarG, Inc.
+//Copyright (C) 2015-2016 Google, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins programmatically
+// that cannot be expressed in the strings, and establish mappings between
+// built-in functions and operators.
+//
+// Where to put a built-in:
+// TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string
+// TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string
+// TBuiltIns::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table,
+// including identifying what extensions are needed if a version does not allow a symbol
+// TBuiltIns::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table,
+// including identifying what extensions are needed if a version does not allow a symbol
+//
+
+#include "../Include/intermediate.h"
+#include "Initialize.h"
+
+namespace glslang {
+
+// TODO: ARB_Compatability: do full extension support
+const bool ARBCompatibility = true;
+
+const bool ForwardCompatibility = false;
+
+// change this back to false if depending on textual spellings of texturing calls when consuming the AST
+// Using PureOperatorBuiltins=false is deprecated.
+bool PureOperatorBuiltins = true;
+
+inline bool IncludeLegacy(int version, EProfile profile, int spv)
+{
+ return profile != EEsProfile && (version <= 130 || (spv == 0 && ARBCompatibility) || profile == ECompatibilityProfile);
+}
+
+// Construct TBuiltInParseables base class. This can be used for language-common constructs.
+TBuiltInParseables::TBuiltInParseables()
+{
+}
+
+// Destroy TBuiltInParseables.
+TBuiltInParseables::~TBuiltInParseables()
+{
+}
+
+TBuiltIns::TBuiltIns()
+{
+ // Set up textual representations for making all the permutations
+ // of texturing/imaging functions.
+ prefixes[EbtFloat] = "";
+ prefixes[EbtInt] = "i";
+ prefixes[EbtUint] = "u";
+ prefixes[EbtInt64] = "i64";
+ prefixes[EbtUint64] = "u64";
+ postfixes[2] = "2";
+ postfixes[3] = "3";
+ postfixes[4] = "4";
+
+ // Map from symbolic class of texturing dimension to numeric dimensions.
+ dimMap[Esd1D] = 1;
+ dimMap[Esd2D] = 2;
+ dimMap[EsdRect] = 2;
+ dimMap[Esd3D] = 3;
+ dimMap[EsdCube] = 3;
+ dimMap[EsdBuffer] = 1;
+ dimMap[EsdSubpass] = 2; // potientially unused for now
+}
+
+TBuiltIns::~TBuiltIns()
+{
+}
+
+
+//
+// Add all context-independent built-in functions and variables that are present
+// for the given version and profile. Share common ones across stages, otherwise
+// make stage-specific entries.
+//
+// Most built-ins variables can be added as simple text strings. Some need to
+// be added programmatically, which is done later in IdentifyBuiltIns() below.
+//
+void TBuiltIns::initialize(int version, EProfile profile, int spv, int vulkan)
+{
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by both vertex and fragment shaders.
+ //
+ //============================================================================
+
+ //
+ // Angle and Trigonometric Functions.
+ //
+ commonBuiltins.append(
+ "float radians(float degrees);"
+ "vec2 radians(vec2 degrees);"
+ "vec3 radians(vec3 degrees);"
+ "vec4 radians(vec4 degrees);"
+
+ "float degrees(float radians);"
+ "vec2 degrees(vec2 radians);"
+ "vec3 degrees(vec3 radians);"
+ "vec4 degrees(vec4 radians);"
+
+ "float sin(float angle);"
+ "vec2 sin(vec2 angle);"
+ "vec3 sin(vec3 angle);"
+ "vec4 sin(vec4 angle);"
+
+ "float cos(float angle);"
+ "vec2 cos(vec2 angle);"
+ "vec3 cos(vec3 angle);"
+ "vec4 cos(vec4 angle);"
+
+ "float tan(float angle);"
+ "vec2 tan(vec2 angle);"
+ "vec3 tan(vec3 angle);"
+ "vec4 tan(vec4 angle);"
+
+ "float asin(float x);"
+ "vec2 asin(vec2 x);"
+ "vec3 asin(vec3 x);"
+ "vec4 asin(vec4 x);"
+
+ "float acos(float x);"
+ "vec2 acos(vec2 x);"
+ "vec3 acos(vec3 x);"
+ "vec4 acos(vec4 x);"
+
+ "float atan(float y, float x);"
+ "vec2 atan(vec2 y, vec2 x);"
+ "vec3 atan(vec3 y, vec3 x);"
+ "vec4 atan(vec4 y, vec4 x);"
+
+ "float atan(float y_over_x);"
+ "vec2 atan(vec2 y_over_x);"
+ "vec3 atan(vec3 y_over_x);"
+ "vec4 atan(vec4 y_over_x);"
+
+ "\n");
+
+ if (version >= 130) {
+ commonBuiltins.append(
+ "float sinh(float angle);"
+ "vec2 sinh(vec2 angle);"
+ "vec3 sinh(vec3 angle);"
+ "vec4 sinh(vec4 angle);"
+
+ "float cosh(float angle);"
+ "vec2 cosh(vec2 angle);"
+ "vec3 cosh(vec3 angle);"
+ "vec4 cosh(vec4 angle);"
+
+ "float tanh(float angle);"
+ "vec2 tanh(vec2 angle);"
+ "vec3 tanh(vec3 angle);"
+ "vec4 tanh(vec4 angle);"
+
+ "float asinh(float x);"
+ "vec2 asinh(vec2 x);"
+ "vec3 asinh(vec3 x);"
+ "vec4 asinh(vec4 x);"
+
+ "float acosh(float x);"
+ "vec2 acosh(vec2 x);"
+ "vec3 acosh(vec3 x);"
+ "vec4 acosh(vec4 x);"
+
+ "float atanh(float y_over_x);"
+ "vec2 atanh(vec2 y_over_x);"
+ "vec3 atanh(vec3 y_over_x);"
+ "vec4 atanh(vec4 y_over_x);"
+
+ "\n");
+ }
+
+ //
+ // Exponential Functions.
+ //
+ commonBuiltins.append(
+ "float pow(float x, float y);"
+ "vec2 pow(vec2 x, vec2 y);"
+ "vec3 pow(vec3 x, vec3 y);"
+ "vec4 pow(vec4 x, vec4 y);"
+
+ "float exp(float x);"
+ "vec2 exp(vec2 x);"
+ "vec3 exp(vec3 x);"
+ "vec4 exp(vec4 x);"
+
+ "float log(float x);"
+ "vec2 log(vec2 x);"
+ "vec3 log(vec3 x);"
+ "vec4 log(vec4 x);"
+
+ "float exp2(float x);"
+ "vec2 exp2(vec2 x);"
+ "vec3 exp2(vec3 x);"
+ "vec4 exp2(vec4 x);"
+
+ "float log2(float x);"
+ "vec2 log2(vec2 x);"
+ "vec3 log2(vec3 x);"
+ "vec4 log2(vec4 x);"
+
+ "float sqrt(float x);"
+ "vec2 sqrt(vec2 x);"
+ "vec3 sqrt(vec3 x);"
+ "vec4 sqrt(vec4 x);"
+
+ "float inversesqrt(float x);"
+ "vec2 inversesqrt(vec2 x);"
+ "vec3 inversesqrt(vec3 x);"
+ "vec4 inversesqrt(vec4 x);"
+
+ "\n");
+
+ //
+ // Common Functions.
+ //
+ commonBuiltins.append(
+ "float abs(float x);"
+ "vec2 abs(vec2 x);"
+ "vec3 abs(vec3 x);"
+ "vec4 abs(vec4 x);"
+
+ "float sign(float x);"
+ "vec2 sign(vec2 x);"
+ "vec3 sign(vec3 x);"
+ "vec4 sign(vec4 x);"
+
+ "float floor(float x);"
+ "vec2 floor(vec2 x);"
+ "vec3 floor(vec3 x);"
+ "vec4 floor(vec4 x);"
+
+ "float ceil(float x);"
+ "vec2 ceil(vec2 x);"
+ "vec3 ceil(vec3 x);"
+ "vec4 ceil(vec4 x);"
+
+ "float fract(float x);"
+ "vec2 fract(vec2 x);"
+ "vec3 fract(vec3 x);"
+ "vec4 fract(vec4 x);"
+
+ "float mod(float x, float y);"
+ "vec2 mod(vec2 x, float y);"
+ "vec3 mod(vec3 x, float y);"
+ "vec4 mod(vec4 x, float y);"
+ "vec2 mod(vec2 x, vec2 y);"
+ "vec3 mod(vec3 x, vec3 y);"
+ "vec4 mod(vec4 x, vec4 y);"
+
+ "float min(float x, float y);"
+ "vec2 min(vec2 x, float y);"
+ "vec3 min(vec3 x, float y);"
+ "vec4 min(vec4 x, float y);"
+ "vec2 min(vec2 x, vec2 y);"
+ "vec3 min(vec3 x, vec3 y);"
+ "vec4 min(vec4 x, vec4 y);"
+
+ "float max(float x, float y);"
+ "vec2 max(vec2 x, float y);"
+ "vec3 max(vec3 x, float y);"
+ "vec4 max(vec4 x, float y);"
+ "vec2 max(vec2 x, vec2 y);"
+ "vec3 max(vec3 x, vec3 y);"
+ "vec4 max(vec4 x, vec4 y);"
+
+ "float clamp(float x, float minVal, float maxVal);"
+ "vec2 clamp(vec2 x, float minVal, float maxVal);"
+ "vec3 clamp(vec3 x, float minVal, float maxVal);"
+ "vec4 clamp(vec4 x, float minVal, float maxVal);"
+ "vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);"
+ "vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);"
+ "vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);"
+
+ "float mix(float x, float y, float a);"
+ "vec2 mix(vec2 x, vec2 y, float a);"
+ "vec3 mix(vec3 x, vec3 y, float a);"
+ "vec4 mix(vec4 x, vec4 y, float a);"
+ "vec2 mix(vec2 x, vec2 y, vec2 a);"
+ "vec3 mix(vec3 x, vec3 y, vec3 a);"
+ "vec4 mix(vec4 x, vec4 y, vec4 a);"
+
+ "float step(float edge, float x);"
+ "vec2 step(vec2 edge, vec2 x);"
+ "vec3 step(vec3 edge, vec3 x);"
+ "vec4 step(vec4 edge, vec4 x);"
+ "vec2 step(float edge, vec2 x);"
+ "vec3 step(float edge, vec3 x);"
+ "vec4 step(float edge, vec4 x);"
+
+ "float smoothstep(float edge0, float edge1, float x);"
+ "vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);"
+ "vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);"
+ "vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);"
+ "vec2 smoothstep(float edge0, float edge1, vec2 x);"
+ "vec3 smoothstep(float edge0, float edge1, vec3 x);"
+ "vec4 smoothstep(float edge0, float edge1, vec4 x);"
+
+ "\n");
+
+ if (version >= 130) {
+ commonBuiltins.append(
+ " int abs( int x);"
+ "ivec2 abs(ivec2 x);"
+ "ivec3 abs(ivec3 x);"
+ "ivec4 abs(ivec4 x);"
+
+ " int sign( int x);"
+ "ivec2 sign(ivec2 x);"
+ "ivec3 sign(ivec3 x);"
+ "ivec4 sign(ivec4 x);"
+
+ "float trunc(float x);"
+ "vec2 trunc(vec2 x);"
+ "vec3 trunc(vec3 x);"
+ "vec4 trunc(vec4 x);"
+
+ "float round(float x);"
+ "vec2 round(vec2 x);"
+ "vec3 round(vec3 x);"
+ "vec4 round(vec4 x);"
+
+ "float roundEven(float x);"
+ "vec2 roundEven(vec2 x);"
+ "vec3 roundEven(vec3 x);"
+ "vec4 roundEven(vec4 x);"
+
+ "float modf(float, out float);"
+ "vec2 modf(vec2, out vec2 );"
+ "vec3 modf(vec3, out vec3 );"
+ "vec4 modf(vec4, out vec4 );"
+
+ " int min(int x, int y);"
+ "ivec2 min(ivec2 x, int y);"
+ "ivec3 min(ivec3 x, int y);"
+ "ivec4 min(ivec4 x, int y);"
+ "ivec2 min(ivec2 x, ivec2 y);"
+ "ivec3 min(ivec3 x, ivec3 y);"
+ "ivec4 min(ivec4 x, ivec4 y);"
+
+ " uint min(uint x, uint y);"
+ "uvec2 min(uvec2 x, uint y);"
+ "uvec3 min(uvec3 x, uint y);"
+ "uvec4 min(uvec4 x, uint y);"
+ "uvec2 min(uvec2 x, uvec2 y);"
+ "uvec3 min(uvec3 x, uvec3 y);"
+ "uvec4 min(uvec4 x, uvec4 y);"
+
+ " int max(int x, int y);"
+ "ivec2 max(ivec2 x, int y);"
+ "ivec3 max(ivec3 x, int y);"
+ "ivec4 max(ivec4 x, int y);"
+ "ivec2 max(ivec2 x, ivec2 y);"
+ "ivec3 max(ivec3 x, ivec3 y);"
+ "ivec4 max(ivec4 x, ivec4 y);"
+
+ " uint max(uint x, uint y);"
+ "uvec2 max(uvec2 x, uint y);"
+ "uvec3 max(uvec3 x, uint y);"
+ "uvec4 max(uvec4 x, uint y);"
+ "uvec2 max(uvec2 x, uvec2 y);"
+ "uvec3 max(uvec3 x, uvec3 y);"
+ "uvec4 max(uvec4 x, uvec4 y);"
+
+ "int clamp(int x, int minVal, int maxVal);"
+ "ivec2 clamp(ivec2 x, int minVal, int maxVal);"
+ "ivec3 clamp(ivec3 x, int minVal, int maxVal);"
+ "ivec4 clamp(ivec4 x, int minVal, int maxVal);"
+ "ivec2 clamp(ivec2 x, ivec2 minVal, ivec2 maxVal);"
+ "ivec3 clamp(ivec3 x, ivec3 minVal, ivec3 maxVal);"
+ "ivec4 clamp(ivec4 x, ivec4 minVal, ivec4 maxVal);"
+
+ "uint clamp(uint x, uint minVal, uint maxVal);"
+ "uvec2 clamp(uvec2 x, uint minVal, uint maxVal);"
+ "uvec3 clamp(uvec3 x, uint minVal, uint maxVal);"
+ "uvec4 clamp(uvec4 x, uint minVal, uint maxVal);"
+ "uvec2 clamp(uvec2 x, uvec2 minVal, uvec2 maxVal);"
+ "uvec3 clamp(uvec3 x, uvec3 minVal, uvec3 maxVal);"
+ "uvec4 clamp(uvec4 x, uvec4 minVal, uvec4 maxVal);"
+
+ "float mix(float x, float y, bool a);"
+ "vec2 mix(vec2 x, vec2 y, bvec2 a);"
+ "vec3 mix(vec3 x, vec3 y, bvec3 a);"
+ "vec4 mix(vec4 x, vec4 y, bvec4 a);"
+
+ "bool isnan(float x);"
+ "bvec2 isnan(vec2 x);"
+ "bvec3 isnan(vec3 x);"
+ "bvec4 isnan(vec4 x);"
+
+ "bool isinf(float x);"
+ "bvec2 isinf(vec2 x);"
+ "bvec3 isinf(vec3 x);"
+ "bvec4 isinf(vec4 x);"
+
+ "\n");
+ }
+
+ //
+ // double functions added to desktop 4.00, but not fma, frexp, ldexp, or pack/unpack
+ //
+ if (profile != EEsProfile && version >= 400) {
+ commonBuiltins.append(
+
+ "double sqrt(double);"
+ "dvec2 sqrt(dvec2);"
+ "dvec3 sqrt(dvec3);"
+ "dvec4 sqrt(dvec4);"
+
+ "double inversesqrt(double);"
+ "dvec2 inversesqrt(dvec2);"
+ "dvec3 inversesqrt(dvec3);"
+ "dvec4 inversesqrt(dvec4);"
+
+ "double abs(double);"
+ "dvec2 abs(dvec2);"
+ "dvec3 abs(dvec3);"
+ "dvec4 abs(dvec4);"
+
+ "double sign(double);"
+ "dvec2 sign(dvec2);"
+ "dvec3 sign(dvec3);"
+ "dvec4 sign(dvec4);"
+
+ "double floor(double);"
+ "dvec2 floor(dvec2);"
+ "dvec3 floor(dvec3);"
+ "dvec4 floor(dvec4);"
+
+ "double trunc(double);"
+ "dvec2 trunc(dvec2);"
+ "dvec3 trunc(dvec3);"
+ "dvec4 trunc(dvec4);"
+
+ "double round(double);"
+ "dvec2 round(dvec2);"
+ "dvec3 round(dvec3);"
+ "dvec4 round(dvec4);"
+
+ "double roundEven(double);"
+ "dvec2 roundEven(dvec2);"
+ "dvec3 roundEven(dvec3);"
+ "dvec4 roundEven(dvec4);"
+
+ "double ceil(double);"
+ "dvec2 ceil(dvec2);"
+ "dvec3 ceil(dvec3);"
+ "dvec4 ceil(dvec4);"
+
+ "double fract(double);"
+ "dvec2 fract(dvec2);"
+ "dvec3 fract(dvec3);"
+ "dvec4 fract(dvec4);"
+
+ "double mod(double, double);"
+ "dvec2 mod(dvec2 , double);"
+ "dvec3 mod(dvec3 , double);"
+ "dvec4 mod(dvec4 , double);"
+ "dvec2 mod(dvec2 , dvec2);"
+ "dvec3 mod(dvec3 , dvec3);"
+ "dvec4 mod(dvec4 , dvec4);"
+
+ "double modf(double, out double);"
+ "dvec2 modf(dvec2, out dvec2);"
+ "dvec3 modf(dvec3, out dvec3);"
+ "dvec4 modf(dvec4, out dvec4);"
+
+ "double min(double, double);"
+ "dvec2 min(dvec2, double);"
+ "dvec3 min(dvec3, double);"
+ "dvec4 min(dvec4, double);"
+ "dvec2 min(dvec2, dvec2);"
+ "dvec3 min(dvec3, dvec3);"
+ "dvec4 min(dvec4, dvec4);"
+
+ "double max(double, double);"
+ "dvec2 max(dvec2 , double);"
+ "dvec3 max(dvec3 , double);"
+ "dvec4 max(dvec4 , double);"
+ "dvec2 max(dvec2 , dvec2);"
+ "dvec3 max(dvec3 , dvec3);"
+ "dvec4 max(dvec4 , dvec4);"
+
+ "double clamp(double, double, double);"
+ "dvec2 clamp(dvec2 , double, double);"
+ "dvec3 clamp(dvec3 , double, double);"
+ "dvec4 clamp(dvec4 , double, double);"
+ "dvec2 clamp(dvec2 , dvec2 , dvec2);"
+ "dvec3 clamp(dvec3 , dvec3 , dvec3);"
+ "dvec4 clamp(dvec4 , dvec4 , dvec4);"
+
+ "double mix(double, double, double);"
+ "dvec2 mix(dvec2, dvec2, double);"
+ "dvec3 mix(dvec3, dvec3, double);"
+ "dvec4 mix(dvec4, dvec4, double);"
+ "dvec2 mix(dvec2, dvec2, dvec2);"
+ "dvec3 mix(dvec3, dvec3, dvec3);"
+ "dvec4 mix(dvec4, dvec4, dvec4);"
+ "double mix(double, double, bool);"
+ "dvec2 mix(dvec2, dvec2, bvec2);"
+ "dvec3 mix(dvec3, dvec3, bvec3);"
+ "dvec4 mix(dvec4, dvec4, bvec4);"
+
+ "double step(double, double);"
+ "dvec2 step(dvec2 , dvec2);"
+ "dvec3 step(dvec3 , dvec3);"
+ "dvec4 step(dvec4 , dvec4);"
+ "dvec2 step(double, dvec2);"
+ "dvec3 step(double, dvec3);"
+ "dvec4 step(double, dvec4);"
+
+ "double smoothstep(double, double, double);"
+ "dvec2 smoothstep(dvec2 , dvec2 , dvec2);"
+ "dvec3 smoothstep(dvec3 , dvec3 , dvec3);"
+ "dvec4 smoothstep(dvec4 , dvec4 , dvec4);"
+ "dvec2 smoothstep(double, double, dvec2);"
+ "dvec3 smoothstep(double, double, dvec3);"
+ "dvec4 smoothstep(double, double, dvec4);"
+
+ "bool isnan(double);"
+ "bvec2 isnan(dvec2);"
+ "bvec3 isnan(dvec3);"
+ "bvec4 isnan(dvec4);"
+
+ "bool isinf(double);"
+ "bvec2 isinf(dvec2);"
+ "bvec3 isinf(dvec3);"
+ "bvec4 isinf(dvec4);"
+
+ "double length(double);"
+ "double length(dvec2);"
+ "double length(dvec3);"
+ "double length(dvec4);"
+
+ "double distance(double, double);"
+ "double distance(dvec2 , dvec2);"
+ "double distance(dvec3 , dvec3);"
+ "double distance(dvec4 , dvec4);"
+
+ "double dot(double, double);"
+ "double dot(dvec2 , dvec2);"
+ "double dot(dvec3 , dvec3);"
+ "double dot(dvec4 , dvec4);"
+
+ "dvec3 cross(dvec3, dvec3);"
+
+ "double normalize(double);"
+ "dvec2 normalize(dvec2);"
+ "dvec3 normalize(dvec3);"
+ "dvec4 normalize(dvec4);"
+
+ "double faceforward(double, double, double);"
+ "dvec2 faceforward(dvec2, dvec2, dvec2);"
+ "dvec3 faceforward(dvec3, dvec3, dvec3);"
+ "dvec4 faceforward(dvec4, dvec4, dvec4);"
+
+ "double reflect(double, double);"
+ "dvec2 reflect(dvec2 , dvec2 );"
+ "dvec3 reflect(dvec3 , dvec3 );"
+ "dvec4 reflect(dvec4 , dvec4 );"
+
+ "double refract(double, double, double);"
+ "dvec2 refract(dvec2 , dvec2 , double);"
+ "dvec3 refract(dvec3 , dvec3 , double);"
+ "dvec4 refract(dvec4 , dvec4 , double);"
+
+ "dmat2 matrixCompMult(dmat2, dmat2);"
+ "dmat3 matrixCompMult(dmat3, dmat3);"
+ "dmat4 matrixCompMult(dmat4, dmat4);"
+ "dmat2x3 matrixCompMult(dmat2x3, dmat2x3);"
+ "dmat2x4 matrixCompMult(dmat2x4, dmat2x4);"
+ "dmat3x2 matrixCompMult(dmat3x2, dmat3x2);"
+ "dmat3x4 matrixCompMult(dmat3x4, dmat3x4);"
+ "dmat4x2 matrixCompMult(dmat4x2, dmat4x2);"
+ "dmat4x3 matrixCompMult(dmat4x3, dmat4x3);"
+
+ "dmat2 outerProduct(dvec2, dvec2);"
+ "dmat3 outerProduct(dvec3, dvec3);"
+ "dmat4 outerProduct(dvec4, dvec4);"
+ "dmat2x3 outerProduct(dvec3, dvec2);"
+ "dmat3x2 outerProduct(dvec2, dvec3);"
+ "dmat2x4 outerProduct(dvec4, dvec2);"
+ "dmat4x2 outerProduct(dvec2, dvec4);"
+ "dmat3x4 outerProduct(dvec4, dvec3);"
+ "dmat4x3 outerProduct(dvec3, dvec4);"
+
+ "dmat2 transpose(dmat2);"
+ "dmat3 transpose(dmat3);"
+ "dmat4 transpose(dmat4);"
+ "dmat2x3 transpose(dmat3x2);"
+ "dmat3x2 transpose(dmat2x3);"
+ "dmat2x4 transpose(dmat4x2);"
+ "dmat4x2 transpose(dmat2x4);"
+ "dmat3x4 transpose(dmat4x3);"
+ "dmat4x3 transpose(dmat3x4);"
+
+ "double determinant(dmat2);"
+ "double determinant(dmat3);"
+ "double determinant(dmat4);"
+
+ "dmat2 inverse(dmat2);"
+ "dmat3 inverse(dmat3);"
+ "dmat4 inverse(dmat4);"
+
+ "bvec2 lessThan(dvec2, dvec2);"
+ "bvec3 lessThan(dvec3, dvec3);"
+ "bvec4 lessThan(dvec4, dvec4);"
+
+ "bvec2 lessThanEqual(dvec2, dvec2);"
+ "bvec3 lessThanEqual(dvec3, dvec3);"
+ "bvec4 lessThanEqual(dvec4, dvec4);"
+
+ "bvec2 greaterThan(dvec2, dvec2);"
+ "bvec3 greaterThan(dvec3, dvec3);"
+ "bvec4 greaterThan(dvec4, dvec4);"
+
+ "bvec2 greaterThanEqual(dvec2, dvec2);"
+ "bvec3 greaterThanEqual(dvec3, dvec3);"
+ "bvec4 greaterThanEqual(dvec4, dvec4);"
+
+ "bvec2 equal(dvec2, dvec2);"
+ "bvec3 equal(dvec3, dvec3);"
+ "bvec4 equal(dvec4, dvec4);"
+
+ "bvec2 notEqual(dvec2, dvec2);"
+ "bvec3 notEqual(dvec3, dvec3);"
+ "bvec4 notEqual(dvec4, dvec4);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+
+ "int64_t abs(int64_t);"
+ "i64vec2 abs(i64vec2);"
+ "i64vec3 abs(i64vec3);"
+ "i64vec4 abs(i64vec4);"
+
+ "int64_t sign(int64_t);"
+ "i64vec2 sign(i64vec2);"
+ "i64vec3 sign(i64vec3);"
+ "i64vec4 sign(i64vec4);"
+
+ "int64_t min(int64_t, int64_t);"
+ "i64vec2 min(i64vec2, int64_t);"
+ "i64vec3 min(i64vec3, int64_t);"
+ "i64vec4 min(i64vec4, int64_t);"
+ "i64vec2 min(i64vec2, i64vec2);"
+ "i64vec3 min(i64vec3, i64vec3);"
+ "i64vec4 min(i64vec4, i64vec4);"
+ "uint64_t min(uint64_t, uint64_t);"
+ "u64vec2 min(u64vec2, uint64_t);"
+ "u64vec3 min(u64vec3, uint64_t);"
+ "u64vec4 min(u64vec4, uint64_t);"
+ "u64vec2 min(u64vec2, u64vec2);"
+ "u64vec3 min(u64vec3, u64vec3);"
+ "u64vec4 min(u64vec4, u64vec4);"
+
+ "int64_t max(int64_t, int64_t);"
+ "i64vec2 max(i64vec2, int64_t);"
+ "i64vec3 max(i64vec3, int64_t);"
+ "i64vec4 max(i64vec4, int64_t);"
+ "i64vec2 max(i64vec2, i64vec2);"
+ "i64vec3 max(i64vec3, i64vec3);"
+ "i64vec4 max(i64vec4, i64vec4);"
+ "uint64_t max(uint64_t, uint64_t);"
+ "u64vec2 max(u64vec2, uint64_t);"
+ "u64vec3 max(u64vec3, uint64_t);"
+ "u64vec4 max(u64vec4, uint64_t);"
+ "u64vec2 max(u64vec2, u64vec2);"
+ "u64vec3 max(u64vec3, u64vec3);"
+ "u64vec4 max(u64vec4, u64vec4);"
+
+ "int64_t clamp(int64_t, int64_t, int64_t);"
+ "i64vec2 clamp(i64vec2, int64_t, int64_t);"
+ "i64vec3 clamp(i64vec3, int64_t, int64_t);"
+ "i64vec4 clamp(i64vec4, int64_t, int64_t);"
+ "i64vec2 clamp(i64vec2, i64vec2, i64vec2);"
+ "i64vec3 clamp(i64vec3, i64vec3, i64vec3);"
+ "i64vec4 clamp(i64vec4, i64vec4, i64vec4);"
+ "uint64_t clamp(uint64_t, uint64_t, uint64_t);"
+ "u64vec2 clamp(u64vec2, uint64_t, uint64_t);"
+ "u64vec3 clamp(u64vec3, uint64_t, uint64_t);"
+ "u64vec4 clamp(u64vec4, uint64_t, uint64_t);"
+ "u64vec2 clamp(u64vec2, u64vec2, u64vec2);"
+ "u64vec3 clamp(u64vec3, u64vec3, u64vec3);"
+ "u64vec4 clamp(u64vec4, u64vec4, u64vec4);"
+
+ "int64_t mix(int64_t, int64_t, bool);"
+ "i64vec2 mix(i64vec2, i64vec2, bvec2);"
+ "i64vec3 mix(i64vec3, i64vec3, bvec3);"
+ "i64vec4 mix(i64vec4, i64vec4, bvec4);"
+ "uint64_t mix(uint64_t, uint64_t, bool);"
+ "u64vec2 mix(u64vec2, u64vec2, bvec2);"
+ "u64vec3 mix(u64vec3, u64vec3, bvec3);"
+ "u64vec4 mix(u64vec4, u64vec4, bvec4);"
+
+ "int64_t doubleBitsToInt64(double);"
+ "i64vec2 doubleBitsToInt64(dvec2);"
+ "i64vec3 doubleBitsToInt64(dvec3);"
+ "i64vec4 doubleBitsToInt64(dvec4);"
+
+ "uint64_t doubleBitsToUint64(double);"
+ "u64vec2 doubleBitsToUint64(dvec2);"
+ "u64vec3 doubleBitsToUint64(dvec3);"
+ "u64vec4 doubleBitsToUint64(dvec4);"
+
+ "double int64BitsToDouble(int64_t);"
+ "dvec2 int64BitsToDouble(i64vec2);"
+ "dvec3 int64BitsToDouble(i64vec3);"
+ "dvec4 int64BitsToDouble(i64vec4);"
+
+ "double uint64BitsToDouble(uint64_t);"
+ "dvec2 uint64BitsToDouble(u64vec2);"
+ "dvec3 uint64BitsToDouble(u64vec3);"
+ "dvec4 uint64BitsToDouble(u64vec4);"
+
+ "int64_t packInt2x32(ivec2);"
+ "uint64_t packUint2x32(uvec2);"
+ "ivec2 unpackInt2x32(int64_t);"
+ "uvec2 unpackUint2x32(uint64_t);"
+
+ "bvec2 lessThan(i64vec2, i64vec2);"
+ "bvec3 lessThan(i64vec3, i64vec3);"
+ "bvec4 lessThan(i64vec4, i64vec4);"
+ "bvec2 lessThan(u64vec2, u64vec2);"
+ "bvec3 lessThan(u64vec3, u64vec3);"
+ "bvec4 lessThan(u64vec4, u64vec4);"
+
+ "bvec2 lessThanEqual(i64vec2, i64vec2);"
+ "bvec3 lessThanEqual(i64vec3, i64vec3);"
+ "bvec4 lessThanEqual(i64vec4, i64vec4);"
+ "bvec2 lessThanEqual(u64vec2, u64vec2);"
+ "bvec3 lessThanEqual(u64vec3, u64vec3);"
+ "bvec4 lessThanEqual(u64vec4, u64vec4);"
+
+ "bvec2 greaterThan(i64vec2, i64vec2);"
+ "bvec3 greaterThan(i64vec3, i64vec3);"
+ "bvec4 greaterThan(i64vec4, i64vec4);"
+ "bvec2 greaterThan(u64vec2, u64vec2);"
+ "bvec3 greaterThan(u64vec3, u64vec3);"
+ "bvec4 greaterThan(u64vec4, u64vec4);"
+
+ "bvec2 greaterThanEqual(i64vec2, i64vec2);"
+ "bvec3 greaterThanEqual(i64vec3, i64vec3);"
+ "bvec4 greaterThanEqual(i64vec4, i64vec4);"
+ "bvec2 greaterThanEqual(u64vec2, u64vec2);"
+ "bvec3 greaterThanEqual(u64vec3, u64vec3);"
+ "bvec4 greaterThanEqual(u64vec4, u64vec4);"
+
+ "bvec2 equal(i64vec2, i64vec2);"
+ "bvec3 equal(i64vec3, i64vec3);"
+ "bvec4 equal(i64vec4, i64vec4);"
+ "bvec2 equal(u64vec2, u64vec2);"
+ "bvec3 equal(u64vec3, u64vec3);"
+ "bvec4 equal(u64vec4, u64vec4);"
+
+ "bvec2 notEqual(i64vec2, i64vec2);"
+ "bvec3 notEqual(i64vec3, i64vec3);"
+ "bvec4 notEqual(i64vec4, i64vec4);"
+ "bvec2 notEqual(u64vec2, u64vec2);"
+ "bvec3 notEqual(u64vec3, u64vec3);"
+ "bvec4 notEqual(u64vec4, u64vec4);"
+
+ "\n"
+ );
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 430)) {
+ commonBuiltins.append(
+ "uint atomicAdd(coherent volatile inout uint, uint);"
+ " int atomicAdd(coherent volatile inout int, int);"
+
+ "uint atomicMin(coherent volatile inout uint, uint);"
+ " int atomicMin(coherent volatile inout int, int);"
+
+ "uint atomicMax(coherent volatile inout uint, uint);"
+ " int atomicMax(coherent volatile inout int, int);"
+
+ "uint atomicAnd(coherent volatile inout uint, uint);"
+ " int atomicAnd(coherent volatile inout int, int);"
+
+ "uint atomicOr (coherent volatile inout uint, uint);"
+ " int atomicOr (coherent volatile inout int, int);"
+
+ "uint atomicXor(coherent volatile inout uint, uint);"
+ " int atomicXor(coherent volatile inout int, int);"
+
+ "uint atomicExchange(coherent volatile inout uint, uint);"
+ " int atomicExchange(coherent volatile inout int, int);"
+
+ "uint atomicCompSwap(coherent volatile inout uint, uint, uint);"
+ " int atomicCompSwap(coherent volatile inout int, int, int);"
+
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 450)) {
+ commonBuiltins.append(
+ "int mix(int x, int y, bool a);"
+ "ivec2 mix(ivec2 x, ivec2 y, bvec2 a);"
+ "ivec3 mix(ivec3 x, ivec3 y, bvec3 a);"
+ "ivec4 mix(ivec4 x, ivec4 y, bvec4 a);"
+
+ "uint mix(uint x, uint y, bool a);"
+ "uvec2 mix(uvec2 x, uvec2 y, bvec2 a);"
+ "uvec3 mix(uvec3 x, uvec3 y, bvec3 a);"
+ "uvec4 mix(uvec4 x, uvec4 y, bvec4 a);"
+
+ "bool mix(bool x, bool y, bool a);"
+ "bvec2 mix(bvec2 x, bvec2 y, bvec2 a);"
+ "bvec3 mix(bvec3 x, bvec3 y, bvec3 a);"
+ "bvec4 mix(bvec4 x, bvec4 y, bvec4 a);"
+
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && version >= 330)) {
+ commonBuiltins.append(
+ "int floatBitsToInt(float value);"
+ "ivec2 floatBitsToInt(vec2 value);"
+ "ivec3 floatBitsToInt(vec3 value);"
+ "ivec4 floatBitsToInt(vec4 value);"
+
+ "uint floatBitsToUint(float value);"
+ "uvec2 floatBitsToUint(vec2 value);"
+ "uvec3 floatBitsToUint(vec3 value);"
+ "uvec4 floatBitsToUint(vec4 value);"
+
+ "float intBitsToFloat(int value);"
+ "vec2 intBitsToFloat(ivec2 value);"
+ "vec3 intBitsToFloat(ivec3 value);"
+ "vec4 intBitsToFloat(ivec4 value);"
+
+ "float uintBitsToFloat(uint value);"
+ "vec2 uintBitsToFloat(uvec2 value);"
+ "vec3 uintBitsToFloat(uvec3 value);"
+ "vec4 uintBitsToFloat(uvec4 value);"
+
+ "\n");
+ }
+
+ if ((profile != EEsProfile && version >= 400) ||
+ (profile == EEsProfile && version >= 310)) { // GL_OES_gpu_shader5
+
+ commonBuiltins.append(
+ "float fma(float, float, float );"
+ "vec2 fma(vec2, vec2, vec2 );"
+ "vec3 fma(vec3, vec3, vec3 );"
+ "vec4 fma(vec4, vec4, vec4 );"
+ "\n");
+
+ if (profile != EEsProfile) {
+ commonBuiltins.append(
+ "double fma(double, double, double);"
+ "dvec2 fma(dvec2, dvec2, dvec2 );"
+ "dvec3 fma(dvec3, dvec3, dvec3 );"
+ "dvec4 fma(dvec4, dvec4, dvec4 );"
+ "\n");
+ }
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ "highp float frexp(highp float, out highp int);"
+ "highp vec2 frexp(highp vec2, out highp ivec2);"
+ "highp vec3 frexp(highp vec3, out highp ivec3);"
+ "highp vec4 frexp(highp vec4, out highp ivec4);"
+
+ "highp float ldexp(highp float, highp int);"
+ "highp vec2 ldexp(highp vec2, highp ivec2);"
+ "highp vec3 ldexp(highp vec3, highp ivec3);"
+ "highp vec4 ldexp(highp vec4, highp ivec4);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 400) {
+ commonBuiltins.append(
+ "double frexp(double, out int);"
+ "dvec2 frexp( dvec2, out ivec2);"
+ "dvec3 frexp( dvec3, out ivec3);"
+ "dvec4 frexp( dvec4, out ivec4);"
+
+ "double ldexp(double, int);"
+ "dvec2 ldexp( dvec2, ivec2);"
+ "dvec3 ldexp( dvec3, ivec3);"
+ "dvec4 ldexp( dvec4, ivec4);"
+
+ "double packDouble2x32(uvec2);"
+ "uvec2 unpackDouble2x32(double);"
+
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ "highp uint packUnorm2x16(vec2);"
+ "highp vec2 unpackUnorm2x16(highp uint);"
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && version >= 420)) {
+ commonBuiltins.append(
+ "highp uint packSnorm2x16(vec2);"
+ "highp vec2 unpackSnorm2x16(highp uint);"
+ "highp uint packHalf2x16(mediump vec2);"
+ "mediump vec2 unpackHalf2x16(highp uint);"
+ "\n");
+ }
+
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ "highp uint packSnorm4x8 (mediump vec4);"
+ "mediump vec4 unpackSnorm4x8(highp uint);"
+ "highp uint packUnorm4x8 (mediump vec4);"
+ "mediump vec4 unpackUnorm4x8(highp uint);"
+ "\n");
+ }
+
+ //
+ // Geometric Functions.
+ //
+ commonBuiltins.append(
+ "float length(float x);"
+ "float length(vec2 x);"
+ "float length(vec3 x);"
+ "float length(vec4 x);"
+
+ "float distance(float p0, float p1);"
+ "float distance(vec2 p0, vec2 p1);"
+ "float distance(vec3 p0, vec3 p1);"
+ "float distance(vec4 p0, vec4 p1);"
+
+ "float dot(float x, float y);"
+ "float dot(vec2 x, vec2 y);"
+ "float dot(vec3 x, vec3 y);"
+ "float dot(vec4 x, vec4 y);"
+
+ "vec3 cross(vec3 x, vec3 y);"
+ "float normalize(float x);"
+ "vec2 normalize(vec2 x);"
+ "vec3 normalize(vec3 x);"
+ "vec4 normalize(vec4 x);"
+
+ "float faceforward(float N, float I, float Nref);"
+ "vec2 faceforward(vec2 N, vec2 I, vec2 Nref);"
+ "vec3 faceforward(vec3 N, vec3 I, vec3 Nref);"
+ "vec4 faceforward(vec4 N, vec4 I, vec4 Nref);"
+
+ "float reflect(float I, float N);"
+ "vec2 reflect(vec2 I, vec2 N);"
+ "vec3 reflect(vec3 I, vec3 N);"
+ "vec4 reflect(vec4 I, vec4 N);"
+
+ "float refract(float I, float N, float eta);"
+ "vec2 refract(vec2 I, vec2 N, float eta);"
+ "vec3 refract(vec3 I, vec3 N, float eta);"
+ "vec4 refract(vec4 I, vec4 N, float eta);"
+
+ "\n");
+
+ //
+ // Matrix Functions.
+ //
+ commonBuiltins.append(
+ "mat2 matrixCompMult(mat2 x, mat2 y);"
+ "mat3 matrixCompMult(mat3 x, mat3 y);"
+ "mat4 matrixCompMult(mat4 x, mat4 y);"
+
+ "\n");
+
+ // 120 is correct for both ES and desktop
+ if (version >= 120) {
+ commonBuiltins.append(
+ "mat2 outerProduct(vec2 c, vec2 r);"
+ "mat3 outerProduct(vec3 c, vec3 r);"
+ "mat4 outerProduct(vec4 c, vec4 r);"
+ "mat2x3 outerProduct(vec3 c, vec2 r);"
+ "mat3x2 outerProduct(vec2 c, vec3 r);"
+ "mat2x4 outerProduct(vec4 c, vec2 r);"
+ "mat4x2 outerProduct(vec2 c, vec4 r);"
+ "mat3x4 outerProduct(vec4 c, vec3 r);"
+ "mat4x3 outerProduct(vec3 c, vec4 r);"
+
+ "mat2 transpose(mat2 m);"
+ "mat3 transpose(mat3 m);"
+ "mat4 transpose(mat4 m);"
+ "mat2x3 transpose(mat3x2 m);"
+ "mat3x2 transpose(mat2x3 m);"
+ "mat2x4 transpose(mat4x2 m);"
+ "mat4x2 transpose(mat2x4 m);"
+ "mat3x4 transpose(mat4x3 m);"
+ "mat4x3 transpose(mat3x4 m);"
+
+ "mat2x3 matrixCompMult(mat2x3, mat2x3);"
+ "mat2x4 matrixCompMult(mat2x4, mat2x4);"
+ "mat3x2 matrixCompMult(mat3x2, mat3x2);"
+ "mat3x4 matrixCompMult(mat3x4, mat3x4);"
+ "mat4x2 matrixCompMult(mat4x2, mat4x2);"
+ "mat4x3 matrixCompMult(mat4x3, mat4x3);"
+
+ "\n");
+
+ // 150 is correct for both ES and desktop
+ if (version >= 150) {
+ commonBuiltins.append(
+ "float determinant(mat2 m);"
+ "float determinant(mat3 m);"
+ "float determinant(mat4 m);"
+
+ "mat2 inverse(mat2 m);"
+ "mat3 inverse(mat3 m);"
+ "mat4 inverse(mat4 m);"
+
+ "\n");
+ }
+ }
+
+ //
+ // Vector relational functions.
+ //
+ commonBuiltins.append(
+ "bvec2 lessThan(vec2 x, vec2 y);"
+ "bvec3 lessThan(vec3 x, vec3 y);"
+ "bvec4 lessThan(vec4 x, vec4 y);"
+
+ "bvec2 lessThan(ivec2 x, ivec2 y);"
+ "bvec3 lessThan(ivec3 x, ivec3 y);"
+ "bvec4 lessThan(ivec4 x, ivec4 y);"
+
+ "bvec2 lessThanEqual(vec2 x, vec2 y);"
+ "bvec3 lessThanEqual(vec3 x, vec3 y);"
+ "bvec4 lessThanEqual(vec4 x, vec4 y);"
+
+ "bvec2 lessThanEqual(ivec2 x, ivec2 y);"
+ "bvec3 lessThanEqual(ivec3 x, ivec3 y);"
+ "bvec4 lessThanEqual(ivec4 x, ivec4 y);"
+
+ "bvec2 greaterThan(vec2 x, vec2 y);"
+ "bvec3 greaterThan(vec3 x, vec3 y);"
+ "bvec4 greaterThan(vec4 x, vec4 y);"
+
+ "bvec2 greaterThan(ivec2 x, ivec2 y);"
+ "bvec3 greaterThan(ivec3 x, ivec3 y);"
+ "bvec4 greaterThan(ivec4 x, ivec4 y);"
+
+ "bvec2 greaterThanEqual(vec2 x, vec2 y);"
+ "bvec3 greaterThanEqual(vec3 x, vec3 y);"
+ "bvec4 greaterThanEqual(vec4 x, vec4 y);"
+
+ "bvec2 greaterThanEqual(ivec2 x, ivec2 y);"
+ "bvec3 greaterThanEqual(ivec3 x, ivec3 y);"
+ "bvec4 greaterThanEqual(ivec4 x, ivec4 y);"
+
+ "bvec2 equal(vec2 x, vec2 y);"
+ "bvec3 equal(vec3 x, vec3 y);"
+ "bvec4 equal(vec4 x, vec4 y);"
+
+ "bvec2 equal(ivec2 x, ivec2 y);"
+ "bvec3 equal(ivec3 x, ivec3 y);"
+ "bvec4 equal(ivec4 x, ivec4 y);"
+
+ "bvec2 equal(bvec2 x, bvec2 y);"
+ "bvec3 equal(bvec3 x, bvec3 y);"
+ "bvec4 equal(bvec4 x, bvec4 y);"
+
+ "bvec2 notEqual(vec2 x, vec2 y);"
+ "bvec3 notEqual(vec3 x, vec3 y);"
+ "bvec4 notEqual(vec4 x, vec4 y);"
+
+ "bvec2 notEqual(ivec2 x, ivec2 y);"
+ "bvec3 notEqual(ivec3 x, ivec3 y);"
+ "bvec4 notEqual(ivec4 x, ivec4 y);"
+
+ "bvec2 notEqual(bvec2 x, bvec2 y);"
+ "bvec3 notEqual(bvec3 x, bvec3 y);"
+ "bvec4 notEqual(bvec4 x, bvec4 y);"
+
+ "bool any(bvec2 x);"
+ "bool any(bvec3 x);"
+ "bool any(bvec4 x);"
+
+ "bool all(bvec2 x);"
+ "bool all(bvec3 x);"
+ "bool all(bvec4 x);"
+
+ "bvec2 not(bvec2 x);"
+ "bvec3 not(bvec3 x);"
+ "bvec4 not(bvec4 x);"
+
+ "\n");
+
+ if (version >= 130) {
+ commonBuiltins.append(
+ "bvec2 lessThan(uvec2 x, uvec2 y);"
+ "bvec3 lessThan(uvec3 x, uvec3 y);"
+ "bvec4 lessThan(uvec4 x, uvec4 y);"
+
+ "bvec2 lessThanEqual(uvec2 x, uvec2 y);"
+ "bvec3 lessThanEqual(uvec3 x, uvec3 y);"
+ "bvec4 lessThanEqual(uvec4 x, uvec4 y);"
+
+ "bvec2 greaterThan(uvec2 x, uvec2 y);"
+ "bvec3 greaterThan(uvec3 x, uvec3 y);"
+ "bvec4 greaterThan(uvec4 x, uvec4 y);"
+
+ "bvec2 greaterThanEqual(uvec2 x, uvec2 y);"
+ "bvec3 greaterThanEqual(uvec3 x, uvec3 y);"
+ "bvec4 greaterThanEqual(uvec4 x, uvec4 y);"
+
+ "bvec2 equal(uvec2 x, uvec2 y);"
+ "bvec3 equal(uvec3 x, uvec3 y);"
+ "bvec4 equal(uvec4 x, uvec4 y);"
+
+ "bvec2 notEqual(uvec2 x, uvec2 y);"
+ "bvec3 notEqual(uvec3 x, uvec3 y);"
+ "bvec4 notEqual(uvec4 x, uvec4 y);"
+
+ "\n");
+ }
+
+ //
+ // Original-style texture functions existing in all stages.
+ // (Per-stage functions below.)
+ //
+ if ((profile == EEsProfile && version == 100) ||
+ profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spv == 0) {
+ commonBuiltins.append(
+ "vec4 texture2D(sampler2D, vec2);"
+
+ "vec4 texture2DProj(sampler2D, vec3);"
+ "vec4 texture2DProj(sampler2D, vec4);"
+
+ "vec4 texture3D(sampler3D, vec3);" // OES_texture_3D, but caught by keyword check
+ "vec4 texture3DProj(sampler3D, vec4);" // OES_texture_3D, but caught by keyword check
+
+ "vec4 textureCube(samplerCube, vec3);"
+
+ "\n");
+ }
+ }
+
+ if ( profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spv == 0) {
+ commonBuiltins.append(
+ "vec4 texture1D(sampler1D, float);"
+
+ "vec4 texture1DProj(sampler1D, vec2);"
+ "vec4 texture1DProj(sampler1D, vec4);"
+
+ "vec4 shadow1D(sampler1DShadow, vec3);"
+ "vec4 shadow2D(sampler2DShadow, vec3);"
+ "vec4 shadow1DProj(sampler1DShadow, vec4);"
+ "vec4 shadow2DProj(sampler2DShadow, vec4);"
+
+ "vec4 texture2DRect(sampler2DRect, vec2);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 texture2DRectProj(sampler2DRect, vec3);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 texture2DRectProj(sampler2DRect, vec4);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 shadow2DRect(sampler2DRectShadow, vec3);" // GL_ARB_texture_rectangle, caught by keyword check
+ "vec4 shadow2DRectProj(sampler2DRectShadow, vec4);" // GL_ARB_texture_rectangle, caught by keyword check
+
+ "\n");
+ }
+ }
+
+ if (profile == EEsProfile) {
+ if (spv == 0) {
+ commonBuiltins.append(
+ "vec4 texture2D(samplerExternalOES, vec2 coord);" // GL_OES_EGL_image_external, caught by keyword check
+ "vec4 texture2DProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external, caught by keyword check
+ "vec4 texture2DProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external, caught by keyword check
+ "vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);" // GL_EXT_shader_texture_lod
+ "vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);" // GL_EXT_shader_texture_lod
+
+ "\n");
+ }
+ }
+
+ //
+ // Noise functions.
+ //
+ if (profile != EEsProfile) {
+ commonBuiltins.append(
+ "float noise1(float x);"
+ "float noise1(vec2 x);"
+ "float noise1(vec3 x);"
+ "float noise1(vec4 x);"
+
+ "vec2 noise2(float x);"
+ "vec2 noise2(vec2 x);"
+ "vec2 noise2(vec3 x);"
+ "vec2 noise2(vec4 x);"
+
+ "vec3 noise3(float x);"
+ "vec3 noise3(vec2 x);"
+ "vec3 noise3(vec3 x);"
+ "vec3 noise3(vec4 x);"
+
+ "vec4 noise4(float x);"
+ "vec4 noise4(vec2 x);"
+ "vec4 noise4(vec3 x);"
+ "vec4 noise4(vec4 x);"
+
+ "\n");
+ }
+
+ if (vulkan == 0) {
+ //
+ // Atomic counter functions.
+ //
+ if ((profile != EEsProfile && version >= 300) ||
+ (profile == EEsProfile && version >= 310)) {
+ commonBuiltins.append(
+ "uint atomicCounterIncrement(atomic_uint x);"
+ "uint atomicCounterDecrement(atomic_uint x);"
+ "uint atomicCounter(atomic_uint x);"
+
+ "\n");
+ }
+ }
+
+ // Bitfield
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ commonBuiltins.append(
+ " int bitfieldExtract( int, int, int);"
+ "ivec2 bitfieldExtract(ivec2, int, int);"
+ "ivec3 bitfieldExtract(ivec3, int, int);"
+ "ivec4 bitfieldExtract(ivec4, int, int);"
+
+ " uint bitfieldExtract( uint, int, int);"
+ "uvec2 bitfieldExtract(uvec2, int, int);"
+ "uvec3 bitfieldExtract(uvec3, int, int);"
+ "uvec4 bitfieldExtract(uvec4, int, int);"
+
+ " int bitfieldInsert( int base, int, int, int);"
+ "ivec2 bitfieldInsert(ivec2 base, ivec2, int, int);"
+ "ivec3 bitfieldInsert(ivec3 base, ivec3, int, int);"
+ "ivec4 bitfieldInsert(ivec4 base, ivec4, int, int);"
+
+ " uint bitfieldInsert( uint base, uint, int, int);"
+ "uvec2 bitfieldInsert(uvec2 base, uvec2, int, int);"
+ "uvec3 bitfieldInsert(uvec3 base, uvec3, int, int);"
+ "uvec4 bitfieldInsert(uvec4 base, uvec4, int, int);"
+
+ "lowp int findLSB( int);"
+ "lowp ivec2 findLSB(ivec2);"
+ "lowp ivec3 findLSB(ivec3);"
+ "lowp ivec4 findLSB(ivec4);"
+
+ "lowp int findLSB( uint);"
+ "lowp ivec2 findLSB(uvec2);"
+ "lowp ivec3 findLSB(uvec3);"
+ "lowp ivec4 findLSB(uvec4);"
+
+ "\n");
+ }
+
+ if (profile != EEsProfile && version >= 400) {
+ commonBuiltins.append(
+ " uint uaddCarry( uint, uint, out uint carry);"
+ "uvec2 uaddCarry(uvec2, uvec2, out uvec2 carry);"
+ "uvec3 uaddCarry(uvec3, uvec3, out uvec3 carry);"
+ "uvec4 uaddCarry(uvec4, uvec4, out uvec4 carry);"
+
+ " uint usubBorrow( uint, uint, out uint borrow);"
+ "uvec2 usubBorrow(uvec2, uvec2, out uvec2 borrow);"
+ "uvec3 usubBorrow(uvec3, uvec3, out uvec3 borrow);"
+ "uvec4 usubBorrow(uvec4, uvec4, out uvec4 borrow);"
+
+ "void umulExtended( uint, uint, out uint, out uint lsb);"
+ "void umulExtended(uvec2, uvec2, out uvec2, out uvec2 lsb);"
+ "void umulExtended(uvec3, uvec3, out uvec3, out uvec3 lsb);"
+ "void umulExtended(uvec4, uvec4, out uvec4, out uvec4 lsb);"
+
+ "void imulExtended( int, int, out int, out int lsb);"
+ "void imulExtended(ivec2, ivec2, out ivec2, out ivec2 lsb);"
+ "void imulExtended(ivec3, ivec3, out ivec3, out ivec3 lsb);"
+ "void imulExtended(ivec4, ivec4, out ivec4, out ivec4 lsb);"
+
+ " int bitfieldReverse( int);"
+ "ivec2 bitfieldReverse(ivec2);"
+ "ivec3 bitfieldReverse(ivec3);"
+ "ivec4 bitfieldReverse(ivec4);"
+
+ " uint bitfieldReverse( uint);"
+ "uvec2 bitfieldReverse(uvec2);"
+ "uvec3 bitfieldReverse(uvec3);"
+ "uvec4 bitfieldReverse(uvec4);"
+
+ " int bitCount( int);"
+ "ivec2 bitCount(ivec2);"
+ "ivec3 bitCount(ivec3);"
+ "ivec4 bitCount(ivec4);"
+
+ " int bitCount( uint);"
+ "ivec2 bitCount(uvec2);"
+ "ivec3 bitCount(uvec3);"
+ "ivec4 bitCount(uvec4);"
+
+ " int findMSB( int);"
+ "ivec2 findMSB(ivec2);"
+ "ivec3 findMSB(ivec3);"
+ "ivec4 findMSB(ivec4);"
+
+ " int findMSB( uint);"
+ "ivec2 findMSB(uvec2);"
+ "ivec3 findMSB(uvec3);"
+ "ivec4 findMSB(uvec4);"
+
+ "\n");
+ }
+
+ if (profile == EEsProfile && version >= 310) {
+ commonBuiltins.append(
+ "highp uint uaddCarry(highp uint, highp uint, out lowp uint carry);"
+ "highp uvec2 uaddCarry(highp uvec2, highp uvec2, out lowp uvec2 carry);"
+ "highp uvec3 uaddCarry(highp uvec3, highp uvec3, out lowp uvec3 carry);"
+ "highp uvec4 uaddCarry(highp uvec4, highp uvec4, out lowp uvec4 carry);"
+
+ "highp uint usubBorrow(highp uint, highp uint, out lowp uint borrow);"
+ "highp uvec2 usubBorrow(highp uvec2, highp uvec2, out lowp uvec2 borrow);"
+ "highp uvec3 usubBorrow(highp uvec3, highp uvec3, out lowp uvec3 borrow);"
+ "highp uvec4 usubBorrow(highp uvec4, highp uvec4, out lowp uvec4 borrow);"
+
+ "void umulExtended(highp uint, highp uint, highp out uint, out highp uint lsb);"
+ "void umulExtended(highp uvec2, highp uvec2, highp out uvec2, out highp uvec2 lsb);"
+ "void umulExtended(highp uvec3, highp uvec3, highp out uvec3, out highp uvec3 lsb);"
+ "void umulExtended(highp uvec4, highp uvec4, highp out uvec4, out highp uvec4 lsb);"
+
+ "void imulExtended(highp int, highp int, highp out int, out highp int lsb);"
+ "void imulExtended(highp ivec2, highp ivec2, highp out ivec2, out highp ivec2 lsb);"
+ "void imulExtended(highp ivec3, highp ivec3, highp out ivec3, out highp ivec3 lsb);"
+ "void imulExtended(highp ivec4, highp ivec4, highp out ivec4, out highp ivec4 lsb);"
+
+ "highp int bitfieldReverse(highp int);"
+ "highp ivec2 bitfieldReverse(highp ivec2);"
+ "highp ivec3 bitfieldReverse(highp ivec3);"
+ "highp ivec4 bitfieldReverse(highp ivec4);"
+
+ "highp uint bitfieldReverse(highp uint);"
+ "highp uvec2 bitfieldReverse(highp uvec2);"
+ "highp uvec3 bitfieldReverse(highp uvec3);"
+ "highp uvec4 bitfieldReverse(highp uvec4);"
+
+ "lowp int bitCount( int);"
+ "lowp ivec2 bitCount(ivec2);"
+ "lowp ivec3 bitCount(ivec3);"
+ "lowp ivec4 bitCount(ivec4);"
+
+ "lowp int bitCount( uint);"
+ "lowp ivec2 bitCount(uvec2);"
+ "lowp ivec3 bitCount(uvec3);"
+ "lowp ivec4 bitCount(uvec4);"
+
+ "lowp int findMSB(highp int);"
+ "lowp ivec2 findMSB(highp ivec2);"
+ "lowp ivec3 findMSB(highp ivec3);"
+ "lowp ivec4 findMSB(highp ivec4);"
+
+ "lowp int findMSB(highp uint);"
+ "lowp ivec2 findMSB(highp uvec2);"
+ "lowp ivec3 findMSB(highp uvec3);"
+ "lowp ivec4 findMSB(highp uvec4);"
+
+ "\n");
+ }
+
+ // GL_ARB_shader_ballot
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "uint64_t ballotARB(bool);"
+
+ "float readInvocationARB(float, uint);"
+ "vec2 readInvocationARB(vec2, uint);"
+ "vec3 readInvocationARB(vec3, uint);"
+ "vec4 readInvocationARB(vec4, uint);"
+
+ "int readInvocationARB(int, uint);"
+ "ivec2 readInvocationARB(ivec2, uint);"
+ "ivec3 readInvocationARB(ivec3, uint);"
+ "ivec4 readInvocationARB(ivec4, uint);"
+
+ "uint readInvocationARB(uint, uint);"
+ "uvec2 readInvocationARB(uvec2, uint);"
+ "uvec3 readInvocationARB(uvec3, uint);"
+ "uvec4 readInvocationARB(uvec4, uint);"
+
+ "float readFirstInvocationARB(float);"
+ "vec2 readFirstInvocationARB(vec2);"
+ "vec3 readFirstInvocationARB(vec3);"
+ "vec4 readFirstInvocationARB(vec4);"
+
+ "int readFirstInvocationARB(int);"
+ "ivec2 readFirstInvocationARB(ivec2);"
+ "ivec3 readFirstInvocationARB(ivec3);"
+ "ivec4 readFirstInvocationARB(ivec4);"
+
+ "uint readFirstInvocationARB(uint);"
+ "uvec2 readFirstInvocationARB(uvec2);"
+ "uvec3 readFirstInvocationARB(uvec3);"
+ "uvec4 readFirstInvocationARB(uvec4);"
+
+ "\n");
+ }
+
+ // GL_ARB_shader_group_vote
+ if (profile != EEsProfile && version >= 430) {
+ commonBuiltins.append(
+ "bool anyInvocationARB(bool);"
+ "bool allInvocationsARB(bool);"
+ "bool allInvocationsEqualARB(bool);"
+
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by vertex shaders only.
+ // (Except legacy lod functions, where it depends which release they are
+ // vertex only.)
+ //
+ //============================================================================
+
+ //
+ // Geometric Functions.
+ //
+ if (IncludeLegacy(version, profile, spv))
+ stageBuiltins[EShLangVertex].append("vec4 ftransform();");
+
+ //
+ // Original-style texture Functions with lod.
+ //
+ TString* s;
+ if (version == 100)
+ s = &stageBuiltins[EShLangVertex];
+ else
+ s = &commonBuiltins;
+ if ((profile == EEsProfile && version == 100) ||
+ profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spv == 0) {
+ s->append(
+ "vec4 texture2DLod(sampler2D, vec2, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjLod(sampler2D, vec3, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjLod(sampler2D, vec4, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture3DLod(sampler3D, vec3, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check
+ "vec4 texture3DProjLod(sampler3D, vec4, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check
+ "vec4 textureCubeLod(samplerCube, vec3, float);" // GL_ARB_shader_texture_lod
+
+ "\n");
+ }
+ }
+ if ( profile == ECompatibilityProfile ||
+ (profile == ECoreProfile && version < 420) ||
+ profile == ENoProfile) {
+ if (spv == 0) {
+ s->append(
+ "vec4 texture1DLod(sampler1D, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjLod(sampler1D, vec2, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjLod(sampler1D, vec4, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DLod(sampler1DShadow, vec3, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DLod(sampler2DShadow, vec3, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DProjLod(sampler1DShadow, vec4, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DProjLod(sampler2DShadow, vec4, float);" // GL_ARB_shader_texture_lod
+
+ "vec4 texture1DGradARB(sampler1D, float, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjGradARB(sampler1D, vec2, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture1DProjGradARB(sampler1D, vec4, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DGradARB(sampler2D, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjGradARB(sampler2D, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DProjGradARB(sampler2D, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture3DGradARB(sampler3D, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod
+ "vec4 texture3DProjGradARB(sampler3D, vec4, vec3, vec3);" // GL_ARB_shader_texture_lod
+ "vec4 textureCubeGradARB(samplerCube, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DGradARB(sampler1DShadow, vec3, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow1DProjGradARB( sampler1DShadow, vec4, float, float);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DGradARB(sampler2DShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DProjGradARB( sampler2DShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DRectGradARB(sampler2DRect, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DRectProjGradARB( sampler2DRect, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 texture2DRectProjGradARB( sampler2DRect, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DRectGradARB( sampler2DRectShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod
+ "vec4 shadow2DRectProjGradARB(sampler2DRectShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod
+
+ "\n");
+ }
+ }
+
+ if ((profile != EEsProfile && version >= 150) ||
+ (profile == EEsProfile && version >= 310)) {
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by geometry shaders only.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile && version >= 400) {
+ stageBuiltins[EShLangGeometry].append(
+ "void EmitStreamVertex(int);"
+ "void EndStreamPrimitive(int);"
+ );
+ }
+ stageBuiltins[EShLangGeometry].append(
+ "void EmitVertex();"
+ "void EndPrimitive();"
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Prototypes for all control functions.
+ //
+ //============================================================================
+ bool esBarrier = (profile == EEsProfile && version >= 310);
+ if ((profile != EEsProfile && version >= 150) || esBarrier)
+ stageBuiltins[EShLangTessControl].append(
+ "void barrier();"
+ );
+ if ((profile != EEsProfile && version >= 420) || esBarrier)
+ stageBuiltins[EShLangCompute].append(
+ "void barrier();"
+ );
+ if ((profile != EEsProfile && version >= 130) || esBarrier)
+ commonBuiltins.append(
+ "void memoryBarrier();"
+ );
+ if ((profile != EEsProfile && version >= 420) || esBarrier) {
+ commonBuiltins.append(
+ "void memoryBarrierAtomicCounter();"
+ "void memoryBarrierBuffer();"
+ "void memoryBarrierImage();"
+ );
+ stageBuiltins[EShLangCompute].append(
+ "void memoryBarrierShared();"
+ "void groupMemoryBarrier();"
+ );
+ }
+
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by fragment shaders only.
+ //
+ //============================================================================
+
+ //
+ // Original-style texture Functions with bias.
+ //
+ if (spv == 0 && (profile != EEsProfile || version == 100)) {
+ stageBuiltins[EShLangFragment].append(
+ "vec4 texture2D(sampler2D, vec2, float);"
+ "vec4 texture2DProj(sampler2D, vec3, float);"
+ "vec4 texture2DProj(sampler2D, vec4, float);"
+ "vec4 texture3D(sampler3D, vec3, float);" // OES_texture_3D
+ "vec4 texture3DProj(sampler3D, vec4, float);" // OES_texture_3D
+ "vec4 textureCube(samplerCube, vec3, float);"
+
+ "\n");
+ }
+ if (spv == 0 && (profile != EEsProfile && version > 100)) {
+ stageBuiltins[EShLangFragment].append(
+ "vec4 texture1D(sampler1D, float, float);"
+ "vec4 texture1DProj(sampler1D, vec2, float);"
+ "vec4 texture1DProj(sampler1D, vec4, float);"
+ "vec4 shadow1D(sampler1DShadow, vec3, float);"
+ "vec4 shadow2D(sampler2DShadow, vec3, float);"
+ "vec4 shadow1DProj(sampler1DShadow, vec4, float);"
+ "vec4 shadow2DProj(sampler2DShadow, vec4, float);"
+
+ "\n");
+ }
+ if (spv == 0 && profile == EEsProfile) {
+ stageBuiltins[EShLangFragment].append(
+ "vec4 texture2DLodEXT(sampler2D, vec2, float);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjLodEXT(sampler2D, vec3, float);" // GL_EXT_shader_texture_lod
+ "vec4 texture2DProjLodEXT(sampler2D, vec4, float);" // GL_EXT_shader_texture_lod
+ "vec4 textureCubeLodEXT(samplerCube, vec3, float);" // GL_EXT_shader_texture_lod
+
+ "\n");
+ }
+
+ stageBuiltins[EShLangFragment].append(
+ "float dFdx(float p);"
+ "vec2 dFdx(vec2 p);"
+ "vec3 dFdx(vec3 p);"
+ "vec4 dFdx(vec4 p);"
+
+ "float dFdy(float p);"
+ "vec2 dFdy(vec2 p);"
+ "vec3 dFdy(vec3 p);"
+ "vec4 dFdy(vec4 p);"
+
+ "float fwidth(float p);"
+ "vec2 fwidth(vec2 p);"
+ "vec3 fwidth(vec3 p);"
+ "vec4 fwidth(vec4 p);"
+
+ "\n");
+
+ // GL_ARB_derivative_control
+ if (profile != EEsProfile && version >= 400) {
+ stageBuiltins[EShLangFragment].append(
+ "float dFdxFine(float p);"
+ "vec2 dFdxFine(vec2 p);"
+ "vec3 dFdxFine(vec3 p);"
+ "vec4 dFdxFine(vec4 p);"
+
+ "float dFdyFine(float p);"
+ "vec2 dFdyFine(vec2 p);"
+ "vec3 dFdyFine(vec3 p);"
+ "vec4 dFdyFine(vec4 p);"
+
+ "float fwidthFine(float p);"
+ "vec2 fwidthFine(vec2 p);"
+ "vec3 fwidthFine(vec3 p);"
+ "vec4 fwidthFine(vec4 p);"
+
+ "\n");
+
+ stageBuiltins[EShLangFragment].append(
+ "float dFdxCoarse(float p);"
+ "vec2 dFdxCoarse(vec2 p);"
+ "vec3 dFdxCoarse(vec3 p);"
+ "vec4 dFdxCoarse(vec4 p);"
+
+ "float dFdyCoarse(float p);"
+ "vec2 dFdyCoarse(vec2 p);"
+ "vec3 dFdyCoarse(vec3 p);"
+ "vec4 dFdyCoarse(vec4 p);"
+
+ "float fwidthCoarse(float p);"
+ "vec2 fwidthCoarse(vec2 p);"
+ "vec3 fwidthCoarse(vec3 p);"
+ "vec4 fwidthCoarse(vec4 p);"
+
+ "\n");
+ }
+
+ // GL_OES_shader_multisample_interpolation
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 400)) {
+ stageBuiltins[EShLangFragment].append(
+ "float interpolateAtCentroid(float);"
+ "vec2 interpolateAtCentroid(vec2);"
+ "vec3 interpolateAtCentroid(vec3);"
+ "vec4 interpolateAtCentroid(vec4);"
+
+ "float interpolateAtSample(float, int);"
+ "vec2 interpolateAtSample(vec2, int);"
+ "vec3 interpolateAtSample(vec3, int);"
+ "vec4 interpolateAtSample(vec4, int);"
+
+ "float interpolateAtOffset(float, vec2);"
+ "vec2 interpolateAtOffset(vec2, vec2);"
+ "vec3 interpolateAtOffset(vec3, vec2);"
+ "vec4 interpolateAtOffset(vec4, vec2);"
+
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Standard Uniforms
+ //
+ //============================================================================
+
+ //
+ // Depth range in window coordinates, p. 33
+ //
+ if (vulkan == 0) {
+ commonBuiltins.append(
+ "struct gl_DepthRangeParameters {"
+ );
+ if (profile == EEsProfile) {
+ commonBuiltins.append(
+ "highp float near;" // n
+ "highp float far;" // f
+ "highp float diff;" // f - n
+ );
+ } else {
+ commonBuiltins.append(
+ "float near;" // n
+ "float far;" // f
+ "float diff;" // f - n
+ );
+ }
+
+ commonBuiltins.append(
+ "};"
+ "uniform gl_DepthRangeParameters gl_DepthRange;"
+ "\n");
+ }
+
+ if (vulkan == 0 && IncludeLegacy(version, profile, spv)) {
+ //
+ // Matrix state. p. 31, 32, 37, 39, 40.
+ //
+ commonBuiltins.append(
+ "uniform mat4 gl_ModelViewMatrix;"
+ "uniform mat4 gl_ProjectionMatrix;"
+ "uniform mat4 gl_ModelViewProjectionMatrix;"
+
+ //
+ // Derived matrix state that provides inverse and transposed versions
+ // of the matrices above.
+ //
+ "uniform mat3 gl_NormalMatrix;"
+
+ "uniform mat4 gl_ModelViewMatrixInverse;"
+ "uniform mat4 gl_ProjectionMatrixInverse;"
+ "uniform mat4 gl_ModelViewProjectionMatrixInverse;"
+
+ "uniform mat4 gl_ModelViewMatrixTranspose;"
+ "uniform mat4 gl_ProjectionMatrixTranspose;"
+ "uniform mat4 gl_ModelViewProjectionMatrixTranspose;"
+
+ "uniform mat4 gl_ModelViewMatrixInverseTranspose;"
+ "uniform mat4 gl_ProjectionMatrixInverseTranspose;"
+ "uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;"
+
+ //
+ // Normal scaling p. 39.
+ //
+ "uniform float gl_NormalScale;"
+
+ //
+ // Point Size, p. 66, 67.
+ //
+ "struct gl_PointParameters {"
+ "float size;"
+ "float sizeMin;"
+ "float sizeMax;"
+ "float fadeThresholdSize;"
+ "float distanceConstantAttenuation;"
+ "float distanceLinearAttenuation;"
+ "float distanceQuadraticAttenuation;"
+ "};"
+
+ "uniform gl_PointParameters gl_Point;"
+
+ //
+ // Material State p. 50, 55.
+ //
+ "struct gl_MaterialParameters {"
+ "vec4 emission;" // Ecm
+ "vec4 ambient;" // Acm
+ "vec4 diffuse;" // Dcm
+ "vec4 specular;" // Scm
+ "float shininess;" // Srm
+ "};"
+ "uniform gl_MaterialParameters gl_FrontMaterial;"
+ "uniform gl_MaterialParameters gl_BackMaterial;"
+
+ //
+ // Light State p 50, 53, 55.
+ //
+ "struct gl_LightSourceParameters {"
+ "vec4 ambient;" // Acli
+ "vec4 diffuse;" // Dcli
+ "vec4 specular;" // Scli
+ "vec4 position;" // Ppli
+ "vec4 halfVector;" // Derived: Hi
+ "vec3 spotDirection;" // Sdli
+ "float spotExponent;" // Srli
+ "float spotCutoff;" // Crli
+ // (range: [0.0,90.0], 180.0)
+ "float spotCosCutoff;" // Derived: cos(Crli)
+ // (range: [1.0,0.0],-1.0)
+ "float constantAttenuation;" // K0
+ "float linearAttenuation;" // K1
+ "float quadraticAttenuation;"// K2
+ "};"
+
+
+ "struct gl_LightModelParameters {"
+ "vec4 ambient;" // Acs
+ "};"
+
+ "uniform gl_LightModelParameters gl_LightModel;"
+
+ //
+ // Derived state from products of light and material.
+ //
+ "struct gl_LightModelProducts {"
+ "vec4 sceneColor;" // Derived. Ecm + Acm * Acs
+ "};"
+
+ "uniform gl_LightModelProducts gl_FrontLightModelProduct;"
+ "uniform gl_LightModelProducts gl_BackLightModelProduct;"
+
+ "struct gl_LightProducts {"
+ "vec4 ambient;" // Acm * Acli
+ "vec4 diffuse;" // Dcm * Dcli
+ "vec4 specular;" // Scm * Scli
+ "};"
+
+ //
+ // Fog p. 161
+ //
+ "struct gl_FogParameters {"
+ "vec4 color;"
+ "float density;"
+ "float start;"
+ "float end;"
+ "float scale;" // 1 / (gl_FogEnd - gl_FogStart)
+ "};"
+
+ "uniform gl_FogParameters gl_Fog;"
+
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the compute shader.
+ //
+ //============================================================================
+
+ if ((profile != EEsProfile && version >= 420) ||
+ (profile == EEsProfile && version >= 310)) {
+ stageBuiltins[EShLangCompute].append(
+ "in highp uvec3 gl_NumWorkGroups;"
+ "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);"
+
+ "in highp uvec3 gl_WorkGroupID;"
+ "in highp uvec3 gl_LocalInvocationID;"
+
+ "in highp uvec3 gl_GlobalInvocationID;"
+ "in highp uint gl_LocalInvocationIndex;"
+
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the vertex shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile) {
+ if (version < 130) {
+ stageBuiltins[EShLangVertex].append(
+ "attribute vec4 gl_Color;"
+ "attribute vec4 gl_SecondaryColor;"
+ "attribute vec3 gl_Normal;"
+ "attribute vec4 gl_Vertex;"
+ "attribute vec4 gl_MultiTexCoord0;"
+ "attribute vec4 gl_MultiTexCoord1;"
+ "attribute vec4 gl_MultiTexCoord2;"
+ "attribute vec4 gl_MultiTexCoord3;"
+ "attribute vec4 gl_MultiTexCoord4;"
+ "attribute vec4 gl_MultiTexCoord5;"
+ "attribute vec4 gl_MultiTexCoord6;"
+ "attribute vec4 gl_MultiTexCoord7;"
+ "attribute float gl_FogCoord;"
+ "\n");
+ } else if (IncludeLegacy(version, profile, spv)) {
+ stageBuiltins[EShLangVertex].append(
+ "in vec4 gl_Color;"
+ "in vec4 gl_SecondaryColor;"
+ "in vec3 gl_Normal;"
+ "in vec4 gl_Vertex;"
+ "in vec4 gl_MultiTexCoord0;"
+ "in vec4 gl_MultiTexCoord1;"
+ "in vec4 gl_MultiTexCoord2;"
+ "in vec4 gl_MultiTexCoord3;"
+ "in vec4 gl_MultiTexCoord4;"
+ "in vec4 gl_MultiTexCoord5;"
+ "in vec4 gl_MultiTexCoord6;"
+ "in vec4 gl_MultiTexCoord7;"
+ "in float gl_FogCoord;"
+ "\n");
+ }
+
+ if (version < 150) {
+ if (version < 130) {
+ stageBuiltins[EShLangVertex].append(
+ " vec4 gl_ClipVertex;" // needs qualifier fixed later
+ "varying vec4 gl_FrontColor;"
+ "varying vec4 gl_BackColor;"
+ "varying vec4 gl_FrontSecondaryColor;"
+ "varying vec4 gl_BackSecondaryColor;"
+ "varying vec4 gl_TexCoord[];"
+ "varying float gl_FogFragCoord;"
+ "\n");
+ } else if (IncludeLegacy(version, profile, spv)) {
+ stageBuiltins[EShLangVertex].append(
+ " vec4 gl_ClipVertex;" // needs qualifier fixed later
+ "out vec4 gl_FrontColor;"
+ "out vec4 gl_BackColor;"
+ "out vec4 gl_FrontSecondaryColor;"
+ "out vec4 gl_BackSecondaryColor;"
+ "out vec4 gl_TexCoord[];"
+ "out float gl_FogFragCoord;"
+ "\n");
+ }
+ stageBuiltins[EShLangVertex].append(
+ "vec4 gl_Position;" // needs qualifier fixed later
+ "float gl_PointSize;" // needs qualifier fixed later
+ );
+
+ if (version == 130 || version == 140)
+ stageBuiltins[EShLangVertex].append(
+ "out float gl_ClipDistance[];"
+ );
+ } else {
+ // version >= 150
+ stageBuiltins[EShLangVertex].append(
+ "out gl_PerVertex {"
+ "vec4 gl_Position;" // needs qualifier fixed later
+ "float gl_PointSize;" // needs qualifier fixed later
+ "float gl_ClipDistance[];"
+ );
+ if (IncludeLegacy(version, profile, spv))
+ stageBuiltins[EShLangVertex].append(
+ "vec4 gl_ClipVertex;" // needs qualifier fixed later
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangVertex].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangVertex].append(
+ "};"
+ "\n");
+ }
+ if (version >= 130 && vulkan == 0)
+ stageBuiltins[EShLangVertex].append(
+ "int gl_VertexID;" // needs qualifier fixed later
+ );
+ if (version >= 140 && vulkan == 0)
+ stageBuiltins[EShLangVertex].append(
+ "int gl_InstanceID;" // needs qualifier fixed later
+ );
+ if (vulkan > 0 && version >= 140)
+ stageBuiltins[EShLangVertex].append(
+ "in int gl_VertexIndex;"
+ "in int gl_InstanceIndex;"
+ );
+ if (version >= 440) {
+ stageBuiltins[EShLangVertex].append(
+ "in int gl_BaseVertexARB;"
+ "in int gl_BaseInstanceARB;"
+ "in int gl_DrawIDARB;"
+ );
+ }
+ } else {
+ // ES profile
+ if (version == 100) {
+ stageBuiltins[EShLangVertex].append(
+ "highp vec4 gl_Position;" // needs qualifier fixed later
+ "mediump float gl_PointSize;" // needs qualifier fixed later
+ );
+ } else {
+ if (vulkan == 0)
+ stageBuiltins[EShLangVertex].append(
+ "in highp int gl_VertexID;" // needs qualifier fixed later
+ "in highp int gl_InstanceID;" // needs qualifier fixed later
+ );
+ if (vulkan > 0)
+ stageBuiltins[EShLangVertex].append(
+ "in highp int gl_VertexIndex;"
+ "in highp int gl_InstanceIndex;"
+ );
+ if (version < 310)
+ stageBuiltins[EShLangVertex].append(
+ "highp vec4 gl_Position;" // needs qualifier fixed later
+ "highp float gl_PointSize;" // needs qualifier fixed later
+ );
+ else
+ stageBuiltins[EShLangVertex].append(
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;" // needs qualifier fixed later
+ "highp float gl_PointSize;" // needs qualifier fixed later
+ "};"
+ );
+ }
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the geometry shader.
+ //
+ //============================================================================
+
+ if (profile == ECoreProfile || profile == ECompatibilityProfile) {
+ stageBuiltins[EShLangGeometry].append(
+ "in gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (profile == ECompatibilityProfile)
+ stageBuiltins[EShLangGeometry].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangGeometry].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangGeometry].append(
+ "} gl_in[];"
+
+ "in int gl_PrimitiveIDIn;"
+ "out gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ "\n");
+ if (profile == ECompatibilityProfile && version >= 400)
+ stageBuiltins[EShLangGeometry].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangGeometry].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangGeometry].append(
+ "};"
+
+ "out int gl_PrimitiveID;"
+ "out int gl_Layer;");
+
+ if (profile == ECompatibilityProfile && version < 400)
+ stageBuiltins[EShLangGeometry].append(
+ "out vec4 gl_ClipVertex;"
+ );
+
+ if (version >= 400)
+ stageBuiltins[EShLangGeometry].append(
+ "in int gl_InvocationID;"
+ );
+ // GL_ARB_viewport_array
+ if (version >= 150)
+ stageBuiltins[EShLangGeometry].append(
+ "out int gl_ViewportIndex;"
+ );
+ stageBuiltins[EShLangGeometry].append("\n");
+ } else if (profile == EEsProfile && version >= 310) {
+ stageBuiltins[EShLangGeometry].append(
+ "in gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ "} gl_in[];"
+ "\n"
+ "in highp int gl_PrimitiveIDIn;"
+ "in highp int gl_InvocationID;"
+ "\n"
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ "};"
+ "\n"
+ "out highp int gl_PrimitiveID;"
+ "out highp int gl_Layer;"
+ "\n"
+ );
+ }
+
+
+ //============================================================================
+ //
+ // Define the interface to the tessellation control shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile && version >= 150) {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessControl].append(
+ "in int gl_PatchVerticesIn;"
+ "in int gl_PrimitiveID;"
+ "in int gl_InvocationID;"
+
+ "out gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (profile == ECompatibilityProfile)
+ stageBuiltins[EShLangTessControl].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangTessControl].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangTessControl].append(
+ "} gl_out[];"
+
+ "patch out float gl_TessLevelOuter[4];"
+ "patch out float gl_TessLevelInner[2];"
+ "\n");
+ } else {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessControl].append(
+ "in highp int gl_PatchVerticesIn;"
+ "in highp int gl_PrimitiveID;"
+ "in highp int gl_InvocationID;"
+
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ );
+ stageBuiltins[EShLangTessControl].append(
+ "} gl_out[];"
+
+ "patch out highp float gl_TessLevelOuter[4];"
+ "patch out highp float gl_TessLevelInner[2];"
+ "patch out highp vec4 gl_BoundingBoxOES[2];"
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the tessellation evaluation shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile && version >= 150) {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessEvaluation].append(
+ "in int gl_PatchVerticesIn;"
+ "in int gl_PrimitiveID;"
+ "in vec3 gl_TessCoord;"
+
+ "patch in float gl_TessLevelOuter[4];"
+ "patch in float gl_TessLevelInner[2];"
+
+ "out gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (version >= 400 && profile == ECompatibilityProfile)
+ stageBuiltins[EShLangTessEvaluation].append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (version >= 450)
+ stageBuiltins[EShLangTessEvaluation].append(
+ "float gl_CullDistance[];"
+ );
+ stageBuiltins[EShLangTessEvaluation].append(
+ "};"
+ "\n");
+ } else if (profile == EEsProfile && version >= 310) {
+ // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below,
+ // as it depends on the resource sizing of gl_MaxPatchVertices.
+
+ stageBuiltins[EShLangTessEvaluation].append(
+ "in highp int gl_PatchVerticesIn;"
+ "in highp int gl_PrimitiveID;"
+ "in highp vec3 gl_TessCoord;"
+
+ "patch in highp float gl_TessLevelOuter[4];"
+ "patch in highp float gl_TessLevelInner[2];"
+
+ "out gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ );
+ stageBuiltins[EShLangTessEvaluation].append(
+ "};"
+ "\n");
+ }
+
+ //============================================================================
+ //
+ // Define the interface to the fragment shader.
+ //
+ //============================================================================
+
+ if (profile != EEsProfile) {
+
+ stageBuiltins[EShLangFragment].append(
+ "vec4 gl_FragCoord;" // needs qualifier fixed later
+ "bool gl_FrontFacing;" // needs qualifier fixed later
+ "float gl_FragDepth;" // needs qualifier fixed later
+ );
+ if (version >= 120)
+ stageBuiltins[EShLangFragment].append(
+ "vec2 gl_PointCoord;" // needs qualifier fixed later
+ );
+ if (IncludeLegacy(version, profile, spv) || (! ForwardCompatibility && version < 420))
+ stageBuiltins[EShLangFragment].append(
+ "vec4 gl_FragColor;" // needs qualifier fixed later
+ );
+
+ if (version < 130) {
+ stageBuiltins[EShLangFragment].append(
+ "varying vec4 gl_Color;"
+ "varying vec4 gl_SecondaryColor;"
+ "varying vec4 gl_TexCoord[];"
+ "varying float gl_FogFragCoord;"
+ );
+ } else {
+ stageBuiltins[EShLangFragment].append(
+ "in float gl_ClipDistance[];"
+ );
+
+ if (IncludeLegacy(version, profile, spv)) {
+ if (version < 150)
+ stageBuiltins[EShLangFragment].append(
+ "in float gl_FogFragCoord;"
+ "in vec4 gl_TexCoord[];"
+ "in vec4 gl_Color;"
+ "in vec4 gl_SecondaryColor;"
+ );
+ else
+ stageBuiltins[EShLangFragment].append(
+ "in gl_PerFragment {"
+ "in float gl_FogFragCoord;"
+ "in vec4 gl_TexCoord[];"
+ "in vec4 gl_Color;"
+ "in vec4 gl_SecondaryColor;"
+ "};"
+ );
+ }
+ }
+
+ if (version >= 150)
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_PrimitiveID;"
+ );
+
+ if (version >= 400)
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_SampleID;"
+ " in vec2 gl_SamplePosition;"
+ "flat in int gl_SampleMaskIn[];"
+ " out int gl_SampleMask[];"
+ "uniform int gl_NumSamples;"
+ );
+
+ if (version >= 430)
+ stageBuiltins[EShLangFragment].append(
+ "flat in int gl_Layer;"
+ "flat in int gl_ViewportIndex;"
+ );
+
+ if (version >= 450)
+ stageBuiltins[EShLangFragment].append(
+ "in float gl_CullDistance[];"
+ "bool gl_HelperInvocation;" // needs qualifier fixed later
+ );
+ } else {
+ // ES profile
+
+ if (version == 100) {
+ stageBuiltins[EShLangFragment].append(
+ "mediump vec4 gl_FragCoord;" // needs qualifier fixed later
+ " bool gl_FrontFacing;" // needs qualifier fixed later
+ "mediump vec4 gl_FragColor;" // needs qualifier fixed later
+ "mediump vec2 gl_PointCoord;" // needs qualifier fixed later
+ );
+ }
+ if (version >= 300) {
+ stageBuiltins[EShLangFragment].append(
+ "highp vec4 gl_FragCoord;" // needs qualifier fixed later
+ " bool gl_FrontFacing;" // needs qualifier fixed later
+ "mediump vec2 gl_PointCoord;" // needs qualifier fixed later
+ "highp float gl_FragDepth;" // needs qualifier fixed later
+ );
+ }
+ if (version >= 310) {
+ stageBuiltins[EShLangFragment].append(
+ "bool gl_HelperInvocation;" // needs qualifier fixed later
+ "flat in highp int gl_PrimitiveID;" // needs qualifier fixed later
+ "flat in highp int gl_Layer;" // needs qualifier fixed later
+ );
+
+ stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables
+ "flat lowp in int gl_SampleID;"
+ " mediump in vec2 gl_SamplePosition;"
+ "flat highp in int gl_SampleMaskIn[];"
+ " highp out int gl_SampleMask[];"
+ "uniform lowp int gl_NumSamples;"
+ );
+ }
+ stageBuiltins[EShLangFragment].append(
+ "highp float gl_FragDepthEXT;" // GL_EXT_frag_depth
+ );
+ }
+ stageBuiltins[EShLangFragment].append("\n");
+
+ if (version >= 130)
+ add2ndGenerationSamplingImaging(version, profile, spv, vulkan);
+
+ // GL_ARB_shader_ballot
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append(
+ "uniform uint gl_SubGroupSizeARB;"
+
+ "in uint gl_SubGroupInvocationARB;"
+ "in uint64_t gl_SubGroupEqMaskARB;"
+ "in uint64_t gl_SubGroupGeMaskARB;"
+ "in uint64_t gl_SubGroupGtMaskARB;"
+ "in uint64_t gl_SubGroupLeMaskARB;"
+ "in uint64_t gl_SubGroupLtMaskARB;"
+
+ "\n");
+ }
+
+ //printf("%s\n", commonBuiltins.c_str());
+ //printf("%s\n", stageBuiltins[EShLangFragment].c_str());
+}
+
+//
+// Helper function for initialize(), to add the second set of names for texturing,
+// when adding context-independent built-in functions.
+//
+void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, int /*spv*/, int vulkan)
+{
+ //
+ // In this function proper, enumerate the types, then calls the next set of functions
+ // to enumerate all the uses for that type.
+ //
+
+ TBasicType bTypes[3] = { EbtFloat, EbtInt, EbtUint };
+ bool skipBuffer = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 140);
+ bool skipCubeArrayed = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 130);
+
+ // enumerate all the types
+ for (int image = 0; image <= 1; ++image) { // loop over "bool" image vs sampler
+
+ for (int shadow = 0; shadow <= 1; ++shadow) { // loop over "bool" shadow or not
+ for (int ms = 0; ms <=1; ++ms) {
+ if ((ms || image) && shadow)
+ continue;
+ if (ms && profile != EEsProfile && version < 150)
+ continue;
+ if (ms && image && profile == EEsProfile)
+ continue;
+ if (ms && profile == EEsProfile && version < 310)
+ continue;
+
+ for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not
+ for (int dim = Esd1D; dim < EsdNumDims; ++dim) { // 1D, 2D, ..., buffer
+ if (dim == EsdSubpass && vulkan == 0)
+ continue;
+ if (dim == EsdSubpass && (image || shadow || arrayed))
+ continue;
+ if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile)
+ continue;
+ if (dim != Esd2D && dim != EsdSubpass && ms)
+ continue;
+ if ((dim == Esd3D || dim == EsdRect) && arrayed)
+ continue;
+ if (dim == Esd3D && shadow)
+ continue;
+ if (dim == EsdCube && arrayed && skipCubeArrayed)
+ continue;
+ if (dim == EsdBuffer && skipBuffer)
+ continue;
+ if (dim == EsdBuffer && (shadow || arrayed || ms))
+ continue;
+ if (ms && arrayed && profile == EEsProfile && version < 310)
+ continue;
+
+ for (int bType = 0; bType < 3; ++bType) { // float, int, uint results
+
+ if (shadow && bType > 0)
+ continue;
+
+ if (dim == EsdRect && version < 140 && bType > 0)
+ continue;
+
+ //
+ // Now, make all the function prototypes for the type we just built...
+ //
+
+ TSampler sampler;
+ if (dim == EsdSubpass) {
+ sampler.setSubpass(bTypes[bType], ms ? true : false);
+ } else if (image) {
+ sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
+ shadow ? true : false,
+ ms ? true : false);
+ } else {
+ sampler.set(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
+ shadow ? true : false,
+ ms ? true : false);
+ }
+
+ TString typeName = sampler.getString();
+
+ if (dim == EsdSubpass) {
+ addSubpassSampling(sampler, typeName, version, profile);
+ continue;
+ }
+
+ addQueryFunctions(sampler, typeName, version, profile);
+
+ if (image)
+ addImageFunctions(sampler, typeName, version, profile);
+ else {
+ addSamplingFunctions(sampler, typeName, version, profile);
+ addGatherFunctions(sampler, typeName, version, profile);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // sparseTexelsResidentARB()
+ //
+
+ if (profile != EEsProfile && version >= 450) {
+ commonBuiltins.append("bool sparseTexelsResidentARB(int code);\n");
+ }
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the query functions for the given type.
+//
+void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+{
+ if (sampler.image && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
+ return;
+
+ //
+ // textureSize() and imageSize()
+ //
+
+ int sizeDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0) - (sampler.dim == EsdCube ? 1 : 0);
+ if (profile == EEsProfile)
+ commonBuiltins.append("highp ");
+ if (sizeDims == 1)
+ commonBuiltins.append("int");
+ else {
+ commonBuiltins.append("ivec");
+ commonBuiltins.append(postfixes[sizeDims]);
+ }
+ if (sampler.image)
+ commonBuiltins.append(" imageSize(readonly writeonly volatile coherent ");
+ else
+ commonBuiltins.append(" textureSize(");
+ commonBuiltins.append(typeName);
+ if (! sampler.image && sampler.dim != EsdRect && sampler.dim != EsdBuffer && ! sampler.ms)
+ commonBuiltins.append(",int);\n");
+ else
+ commonBuiltins.append(");\n");
+
+ //
+ // textureSamples() and imageSamples()
+ //
+
+ // GL_ARB_shader_texture_image_samples
+ // TODO: spec issue? there are no memory qualifiers; how to query a writeonly/readonly image, etc?
+ if (profile != EEsProfile && version >= 430 && sampler.ms) {
+ commonBuiltins.append("int ");
+ if (sampler.image)
+ commonBuiltins.append("imageSamples(readonly writeonly volatile coherent ");
+ else
+ commonBuiltins.append("textureSamples(");
+ commonBuiltins.append(typeName);
+ commonBuiltins.append(");\n");
+ }
+
+ //
+ // textureQueryLod(), fragment stage only
+ //
+
+ if (profile != EEsProfile && version >= 400 && ! sampler.image && sampler.dim != EsdRect && ! sampler.ms && sampler.dim != EsdBuffer) {
+ stageBuiltins[EShLangFragment].append("vec2 textureQueryLod(");
+ stageBuiltins[EShLangFragment].append(typeName);
+ if (dimMap[sampler.dim] == 1)
+ stageBuiltins[EShLangFragment].append(", float");
+ else {
+ stageBuiltins[EShLangFragment].append(", vec");
+ stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]);
+ }
+ stageBuiltins[EShLangFragment].append(");\n");
+ }
+
+ //
+ // textureQueryLevels()
+ //
+
+ if (profile != EEsProfile && version >= 430 && ! sampler.image && sampler.dim != EsdRect && ! sampler.ms && sampler.dim != EsdBuffer) {
+ commonBuiltins.append("int textureQueryLevels(");
+ commonBuiltins.append(typeName);
+ commonBuiltins.append(");\n");
+ }
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the image access functions for the given type.
+//
+void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+{
+ int dims = dimMap[sampler.dim];
+ // most things with an array add a dimension, except for cubemaps
+ if (sampler.arrayed && sampler.dim != EsdCube)
+ ++dims;
+
+ TString imageParams = typeName;
+ if (dims == 1)
+ imageParams.append(", int");
+ else {
+ imageParams.append(", ivec");
+ imageParams.append(postfixes[dims]);
+ }
+ if (sampler.ms)
+ imageParams.append(", int");
+
+ if (profile == EEsProfile)
+ commonBuiltins.append("highp ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4 imageLoad(readonly volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(");\n");
+
+ commonBuiltins.append("void imageStore(writeonly volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4);\n");
+
+ if (sampler.dim != Esd1D && sampler.dim != EsdBuffer && profile != EEsProfile && version >= 450) {
+ commonBuiltins.append("int sparseImageLoadARB(readonly volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", out ");
+ commonBuiltins.append(prefixes[sampler.type]);
+ commonBuiltins.append("vec4");
+ commonBuiltins.append(");\n");
+ }
+
+ if ( profile != EEsProfile ||
+ (profile == EEsProfile && version >= 310)) {
+ if (sampler.type == EbtInt || sampler.type == EbtUint) {
+ const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint";
+
+ const int numBuiltins = 7;
+
+ static const char* atomicFunc[numBuiltins] = {
+ " imageAtomicAdd(volatile coherent ",
+ " imageAtomicMin(volatile coherent ",
+ " imageAtomicMax(volatile coherent ",
+ " imageAtomicAnd(volatile coherent ",
+ " imageAtomicOr(volatile coherent ",
+ " imageAtomicXor(volatile coherent ",
+ " imageAtomicExchange(volatile coherent "
+ };
+
+ for (size_t i = 0; i < numBuiltins; ++i) {
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(atomicFunc[i]);
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(");\n");
+ }
+
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(" imageAtomicCompSwap(volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(", ");
+ commonBuiltins.append(dataType);
+ commonBuiltins.append(");\n");
+ } else {
+ // not int or uint
+ // GL_ARB_ES3_1_compatibility
+ // TODO: spec issue: are there restrictions on the kind of layout() that can be used? what about dropping memory qualifiers?
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 310)) {
+ commonBuiltins.append("float imageAtomicExchange(volatile coherent ");
+ commonBuiltins.append(imageParams);
+ commonBuiltins.append(", float);\n");
+ }
+ }
+ }
+}
+
+//
+// Helper function for initialize(),
+// when adding context-independent built-in functions.
+//
+// Add all the subpass access functions for the given type.
+//
+void TBuiltIns::addSubpassSampling(TSampler sampler, TString& typeName, int /*version*/, EProfile /*profile*/)
+{
+ stageBuiltins[EShLangFragment].append(prefixes[sampler.type]);
+ stageBuiltins[EShLangFragment].append("vec4 subpassLoad");
+ stageBuiltins[EShLangFragment].append("(");
+ stageBuiltins[EShLangFragment].append(typeName.c_str());
+ if (sampler.ms)
+ stageBuiltins[EShLangFragment].append(", int");
+ stageBuiltins[EShLangFragment].append(");\n");
+}
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the texture lookup functions for the given type.
+//
+void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+{
+ //
+ // texturing
+ //
+ for (int proj = 0; proj <= 1; ++proj) { // loop over "bool" projective or not
+
+ if (proj && (sampler.dim == EsdCube || sampler.dim == EsdBuffer || sampler.arrayed || sampler.ms))
+ continue;
+
+ for (int lod = 0; lod <= 1; ++lod) {
+
+ if (lod && (sampler.dim == EsdBuffer || sampler.dim == EsdRect || sampler.ms))
+ continue;
+ if (lod && sampler.dim == Esd2D && sampler.arrayed && sampler.shadow)
+ continue;
+ if (lod && sampler.dim == EsdCube && sampler.shadow)
+ continue;
+
+ for (int bias = 0; bias <= 1; ++bias) {
+
+ if (bias && (lod || sampler.ms))
+ continue;
+ if (bias && sampler.dim == Esd2D && sampler.shadow && sampler.arrayed)
+ continue;
+ if (bias && (sampler.dim == EsdRect || sampler.dim == EsdBuffer))
+ continue;
+
+ for (int offset = 0; offset <= 1; ++offset) { // loop over "bool" offset or not
+
+ if (proj + offset + bias + lod > 3)
+ continue;
+ if (offset && (sampler.dim == EsdCube || sampler.dim == EsdBuffer || sampler.ms))
+ continue;
+
+ for (int fetch = 0; fetch <= 1; ++fetch) { // loop over "bool" fetch or not
+
+ if (proj + offset + fetch + bias + lod > 3)
+ continue;
+ if (fetch && (lod || bias))
+ continue;
+ if (fetch && (sampler.shadow || sampler.dim == EsdCube))
+ continue;
+ if (fetch == 0 && (sampler.ms || sampler.dim == EsdBuffer))
+ continue;
+
+ for (int grad = 0; grad <= 1; ++grad) { // loop over "bool" grad or not
+
+ if (grad && (lod || bias || sampler.ms))
+ continue;
+ if (grad && sampler.dim == EsdBuffer)
+ continue;
+ if (proj + offset + fetch + grad + bias + lod > 3)
+ continue;
+
+ for (int extraProj = 0; extraProj <= 1; ++extraProj) {
+ bool compare = false;
+ int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
+ // skip dummy unused second component for 1D non-array shadows
+ if (sampler.shadow && totalDims < 2)
+ totalDims = 2;
+ totalDims += (sampler.shadow ? 1 : 0) + proj;
+ if (totalDims > 4 && sampler.shadow) {
+ compare = true;
+ totalDims = 4;
+ }
+ assert(totalDims <= 4);
+
+ if (extraProj && ! proj)
+ continue;
+ if (extraProj && (sampler.dim == Esd3D || sampler.shadow))
+ continue;
+
+ for (int lodClamp = 0; lodClamp <= 1 ;++lodClamp) { // loop over "bool" lod clamp
+
+ if (lodClamp && (profile == EEsProfile || version < 450))
+ continue;
+ if (lodClamp && (proj || lod || fetch))
+ continue;
+
+ for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not
+
+ if (sparse && (profile == EEsProfile || version < 450))
+ continue;
+ // Sparse sampling is not for 1D/1D array texture, buffer texture, and projective texture
+ if (sparse && (sampler.dim == Esd1D || sampler.dim == EsdBuffer || proj))
+ continue;
+
+ TString s;
+
+ // return type
+ if (sparse)
+ s.append("int ");
+ else {
+ if (sampler.shadow)
+ s.append("float ");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+ }
+
+ // name
+ if (sparse) {
+ if (fetch)
+ s.append("sparseTexel");
+ else
+ s.append("sparseTexture");
+ } else {
+ if (fetch)
+ s.append("texel");
+ else
+ s.append("texture");
+ }
+ if (proj)
+ s.append("Proj");
+ if (lod)
+ s.append("Lod");
+ if (grad)
+ s.append("Grad");
+ if (fetch)
+ s.append("Fetch");
+ if (offset)
+ s.append("Offset");
+ if (lodClamp)
+ s.append("Clamp");
+ if (lodClamp || sparse)
+ s.append("ARB");
+ s.append("(");
+
+ // sampler type
+ s.append(typeName);
+
+ // P coordinate
+ if (extraProj)
+ s.append(",vec4");
+ else {
+ s.append(",");
+ TBasicType t = fetch ? EbtInt : EbtFloat;
+ if (totalDims == 1)
+ s.append(TType::getBasicString(t));
+ else {
+ s.append(prefixes[t]);
+ s.append("vec");
+ s.append(postfixes[totalDims]);
+ }
+ }
+
+ if (bias && compare)
+ continue;
+
+ // non-optional lod argument (lod that's not driven by lod loop) or sample
+ if ((fetch && sampler.dim != EsdBuffer && sampler.dim != EsdRect && !sampler.ms) ||
+ (sampler.ms && fetch))
+ s.append(",int");
+
+ // non-optional lod
+ if (lod)
+ s.append(",float");
+
+ // gradient arguments
+ if (grad) {
+ if (dimMap[sampler.dim] == 1)
+ s.append(",float,float");
+ else {
+ s.append(",vec");
+ s.append(postfixes[dimMap[sampler.dim]]);
+ s.append(",vec");
+ s.append(postfixes[dimMap[sampler.dim]]);
+ }
+ }
+
+ // offset
+ if (offset) {
+ if (dimMap[sampler.dim] == 1)
+ s.append(",int");
+ else {
+ s.append(",ivec");
+ s.append(postfixes[dimMap[sampler.dim]]);
+ }
+ }
+
+ // non-optional compare
+ if (compare)
+ s.append(",float");
+
+ // lod clamp
+ if (lodClamp)
+ s.append(",float");
+
+ // texel out (for sparse texture)
+ if (sparse) {
+ s.append(",out ");
+ if (sampler.shadow)
+ s.append("float ");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+ }
+
+ // optional bias
+ if (bias)
+ s.append(",float");
+
+ s.append(");\n");
+
+ // Add to the per-language set of built-ins
+
+ if (bias)
+ stageBuiltins[EShLangFragment].append(s);
+ else
+ commonBuiltins.append(s);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+//
+// Helper function for add2ndGenerationSamplingImaging(),
+// when adding context-independent built-in functions.
+//
+// Add all the texture gather functions for the given type.
+//
+void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+{
+ switch (sampler.dim) {
+ case Esd2D:
+ case EsdRect:
+ case EsdCube:
+ break;
+ default:
+ return;
+ }
+
+ if (sampler.ms)
+ return;
+
+ if (version < 140 && sampler.dim == EsdRect && sampler.type != EbtFloat)
+ return;
+
+ for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets
+
+ for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
+
+ if (comp > 0 && sampler.shadow)
+ continue;
+
+ if (offset > 0 && sampler.dim == EsdCube)
+ continue;
+
+ for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not
+ if (sparse && (profile == EEsProfile || version < 450))
+ continue;
+
+ TString s;
+
+ // return type
+ if (sparse)
+ s.append("int ");
+ else {
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+
+ // name
+ if (sparse)
+ s.append("sparseTextureGather");
+ else
+ s.append("textureGather");
+ switch (offset) {
+ case 1:
+ s.append("Offset");
+ break;
+ case 2:
+ s.append("Offsets");
+ default:
+ break;
+ }
+ if (sparse)
+ s.append("ARB");
+ s.append("(");
+
+ // sampler type argument
+ s.append(typeName);
+
+ // P coordinate argument
+ s.append(",vec");
+ int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
+ s.append(postfixes[totalDims]);
+
+ // refZ argument
+ if (sampler.shadow)
+ s.append(",float");
+
+ // offset argument
+ if (offset > 0) {
+ s.append(",ivec2");
+ if (offset == 2)
+ s.append("[4]");
+ }
+
+ // texel out (for sparse texture)
+ if (sparse) {
+ s.append(",out ");
+ s.append(prefixes[sampler.type]);
+ s.append("vec4 ");
+ }
+
+ // comp argument
+ if (comp)
+ s.append(",int");
+
+ s.append(");\n");
+ commonBuiltins.append(s);
+ }
+ }
+ }
+}
+
+//
+// Add context-dependent built-in functions and variables that are present
+// for the given version and profile. All the results are put into just the
+// commonBuiltins, because it is called for just a specific stage. So,
+// add stage-specific entries to the commonBuiltins, and only if that stage
+// was requested.
+//
+void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, int spv, int vulkan, EShLanguage language)
+{
+ //
+ // Initialize the context-dependent (resource-dependent) built-in strings for parsing.
+ //
+
+ //============================================================================
+ //
+ // Standard Uniforms
+ //
+ //============================================================================
+
+ TString& s = commonBuiltins;
+ const int maxSize = 80;
+ char builtInConstant[maxSize];
+
+ //
+ // Build string of implementation dependent constants.
+ //
+
+ if (profile == EEsProfile) {
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
+ s.append(builtInConstant);
+
+ if (version == 100) {
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors);
+ s.append(builtInConstant);
+ } else {
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexOutputVectors = %d;", resources.maxVertexOutputVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentInputVectors = %d;", resources.maxFragmentInputVectors);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset);
+ s.append(builtInConstant);
+ }
+
+ if (version >= 310) {
+ // geometry
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.maxGeometryAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.maxGeometryAtomicCounterBuffers);
+ s.append(builtInConstant);
+
+ // tessellation
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel);
+ s.append(builtInConstant);
+
+ // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices
+ if (language == EShLangTessControl || language == EShLangTessEvaluation) {
+ s.append(
+ "in gl_PerVertex {"
+ "highp vec4 gl_Position;"
+ "highp float gl_PointSize;"
+ "} gl_in[gl_MaxPatchVertices];"
+ "\n");
+ }
+ }
+
+ } else {
+ // non-ES profile
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxLights = %d;", resources.maxLights);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents);
+ s.append(builtInConstant);
+
+ if (version < 150 || ARBCompatibility) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats);
+ s.append(builtInConstant);
+ }
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents);
+ s.append(builtInConstant);
+
+ if (vulkan == 0 && IncludeLegacy(version, profile, spv)) {
+ //
+ // OpenGL'uniform' state. Page numbers are in reference to version
+ // 1.4 of the OpenGL specification.
+ //
+
+ //
+ // Matrix state. p. 31, 32, 37, 39, 40.
+ //
+ s.append("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];"
+
+ //
+ // Derived matrix state that provides inverse and transposed versions
+ // of the matrices above.
+ //
+ "uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];"
+
+ "uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];"
+
+ "uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];"
+
+ //
+ // Clip planes p. 42.
+ //
+ "uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];"
+
+ //
+ // Light State p 50, 53, 55.
+ //
+ "uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];"
+
+ //
+ // Derived state from products of light.
+ //
+ "uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];"
+ "uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];"
+
+ //
+ // Texture Environment and Generation, p. 152, p. 40-42.
+ //
+ "uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];"
+ "uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];"
+ "uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];"
+ "uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];"
+ "uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];"
+ "uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];");
+ }
+
+ if (version >= 130) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxClipDistances = %d;", resources.maxClipDistances);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingComponents = %d;", resources.maxVaryingComponents);
+ s.append(builtInConstant);
+
+ // GL_ARB_shading_language_420pack
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset);
+ s.append(builtInConstant);
+ }
+
+ // geometry
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryVaryingComponents = %d;", resources.maxGeometryVaryingComponents);
+ s.append(builtInConstant);
+
+ }
+
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexOutputComponents = %d;", resources.maxVertexOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentInputComponents = %d;", resources.maxFragmentInputComponents);
+ s.append(builtInConstant);
+ }
+
+ // tessellation
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices);
+ s.append(builtInConstant);
+
+ // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices
+ if (language == EShLangTessControl || language == EShLangTessEvaluation) {
+ s.append(
+ "in gl_PerVertex {"
+ "vec4 gl_Position;"
+ "float gl_PointSize;"
+ "float gl_ClipDistance[];"
+ );
+ if (profile == ECompatibilityProfile)
+ s.append(
+ "vec4 gl_ClipVertex;"
+ "vec4 gl_FrontColor;"
+ "vec4 gl_BackColor;"
+ "vec4 gl_FrontSecondaryColor;"
+ "vec4 gl_BackSecondaryColor;"
+ "vec4 gl_TexCoord[];"
+ "float gl_FogFragCoord;"
+ );
+ if (profile != EEsProfile && version >= 450)
+ s.append(
+ "float gl_CullDistance[];"
+ );
+ s.append(
+ "} gl_in[gl_MaxPatchVertices];"
+ "\n");
+ }
+ }
+
+ if (version >= 150) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxViewports = %d;", resources.maxViewports);
+ s.append(builtInConstant);
+ }
+
+ // images
+ if (version >= 130) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUnitsAndFragmentOutputs = %d;", resources.maxCombinedImageUnitsAndFragmentOutputs);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxImageSamples = %d;", resources.maxImageSamples);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms);
+ s.append(builtInConstant);
+ }
+
+ // enhanced layouts
+ if (version >= 430) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackBuffers = %d;", resources.maxTransformFeedbackBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackInterleavedComponents = %d;", resources.maxTransformFeedbackInterleavedComponents);
+ s.append(builtInConstant);
+ }
+ }
+
+ // images (some in compute below)
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 130)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxImageUnits = %d;", resources.maxImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedShaderOutputResources = %d;", resources.maxCombinedShaderOutputResources);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexImageUniforms = %d;", resources.maxVertexImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentImageUniforms = %d;", resources.maxFragmentImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUniforms = %d;", resources.maxCombinedImageUniforms);
+ s.append(builtInConstant);
+ }
+
+ // atomic counters (some in compute below)
+ if ((profile == EEsProfile && version >= 310) ||
+ (profile != EEsProfile && version >= 420)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources. maxVertexAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources. maxFragmentAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources. maxCombinedAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources. maxAtomicCounterBindings);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources. maxVertexAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources. maxFragmentAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources. maxCombinedAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources. maxAtomicCounterBufferSize);
+ s.append(builtInConstant);
+ }
+ if (profile != EEsProfile && version >= 420) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources. maxTessControlAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources. maxTessEvaluationAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources. maxGeometryAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources. maxTessControlAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources. maxTessEvaluationAtomicCounterBuffers);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources. maxGeometryAtomicCounterBuffers);
+ s.append(builtInConstant);
+
+ s.append("\n");
+ }
+
+
+ // compute
+ if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) {
+ snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupCountX,
+ resources.maxComputeWorkGroupCountY,
+ resources.maxComputeWorkGroupCountZ);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupSizeX,
+ resources.maxComputeWorkGroupSizeY,
+ resources.maxComputeWorkGroupSizeZ);
+ s.append(builtInConstant);
+
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers);
+ s.append(builtInConstant);
+
+ s.append("\n");
+ }
+
+ // GL_ARB_cull_distance
+ if (profile != EEsProfile && version >= 450) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCullDistances = %d;", resources.maxCullDistances);
+ s.append(builtInConstant);
+ snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedClipAndCullDistances = %d;", resources.maxCombinedClipAndCullDistances);
+ s.append(builtInConstant);
+ }
+
+ // GL_ARB_ES3_1_compatibility
+ if ((profile != EEsProfile && version >= 450) ||
+ (profile == EEsProfile && version >= 310)) {
+ snprintf(builtInConstant, maxSize, "const int gl_MaxSamples = %d;", resources.maxSamples);
+ s.append(builtInConstant);
+ }
+
+ s.append("\n");
+}
+
+//
+// To support special built-ins that have a special qualifier that cannot be declared textually
+// in a shader, like gl_Position.
+//
+// This lets the type of the built-in be declared textually, and then have just its qualifier be
+// updated afterward.
+//
+// Safe to call even if name is not present.
+//
+// Only use this for built-in variables that have a special qualifier in TStorageQualifier.
+// New built-in variables should use a generic (textually declarable) qualifier in
+// TStoraregQualifier and only call BuiltInVariable().
+//
+static void SpecialQualifier(const char* name, TStorageQualifier qualifier, TBuiltInVariable builtIn, TSymbolTable& symbolTable)
+{
+ TSymbol* symbol = symbolTable.find(name);
+ if (symbol) {
+ TQualifier& symQualifier = symbol->getWritableType().getQualifier();
+ symQualifier.storage = qualifier;
+ symQualifier.builtIn = builtIn;
+ }
+}
+
+//
+// To tag built-in variables with their TBuiltInVariable enum. Use this when the
+// normal declaration text already gets the qualifier right, and all that's needed
+// is setting the builtIn field. This should be the normal way for all new
+// built-in variables.
+//
+// If SpecialQualifier() was called, this does not need to be called.
+//
+// Safe to call even if name is not present.
+//
+static void BuiltInVariable(const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable)
+{
+ TSymbol* symbol = symbolTable.find(name);
+ if (! symbol)
+ return;
+
+ TQualifier& symQualifier = symbol->getWritableType().getQualifier();
+ symQualifier.builtIn = builtIn;
+}
+
+//
+// For built-in variables inside a named block.
+// SpecialQualifier() won't ever go inside a block; their member's qualifier come
+// from the qualification of the block.
+//
+// See comments above for other detail.
+//
+static void BuiltInVariable(const char* blockName, const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable)
+{
+ TSymbol* symbol = symbolTable.find(blockName);
+ if (! symbol)
+ return;
+
+ TTypeList& structure = *symbol->getWritableType().getWritableStruct();
+ for (int i = 0; i < (int)structure.size(); ++i) {
+ if (structure[i].type->getFieldName().compare(name) == 0) {
+ structure[i].type->getQualifier().builtIn = builtIn;
+ return;
+ }
+ }
+}
+
+//
+// Finish adding/processing context-independent built-in symbols.
+// 1) Programmatically add symbols that could not be added by simple text strings above.
+// 2) Map built-in functions to operators, for those that will turn into an operation node
+// instead of remaining a function call.
+// 3) Tag extension-related symbols added to their base version with their extensions, so
+// that if an early version has the extension turned off, there is an error reported on use.
+//
+void TBuiltIns::identifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLanguage language, TSymbolTable& symbolTable)
+{
+ //
+ // Tag built-in variables and functions with additional qualifier and extension information
+ // that cannot be declared with the text strings.
+ //
+
+ // N.B.: a symbol should only be tagged once, and this function is called multiple times, once
+ // per stage that's used for this profile. So
+ // - generally, stick common ones in the fragment stage to ensure they are tagged exactly once
+ // - for ES, which has different precisions for different stages, the coarsest-grained tagging
+ // for a built-in used in many stages needs to be once for the fragment stage and once for
+ // the vertex stage
+
+ switch(language) {
+ case EShLangVertex:
+ if (profile != EEsProfile) {
+ symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters);
+ symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters);
+ symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters);
+
+ BuiltInVariable("gl_BaseVertexARB", EbvBaseVertex, symbolTable);
+ BuiltInVariable("gl_BaseInstanceARB", EbvBaseInstance, symbolTable);
+ BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable);
+ }
+
+ if (profile != EEsProfile) {
+ symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot);
+
+ symbolTable.setFunctionExtensions("ballotARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setFunctionExtensions("readInvocationARB", 1, &E_GL_ARB_shader_ballot);
+ symbolTable.setFunctionExtensions("readFirstInvocationARB", 1, &E_GL_ARB_shader_ballot);
+
+ BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable);
+ BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable);
+ BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable);
+ BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable);
+
+ symbolTable.setFunctionExtensions("anyInvocationARB", 1, &E_GL_ARB_shader_group_vote);
+ symbolTable.setFunctionExtensions("allInvocationsARB", 1, &E_GL_ARB_shader_group_vote);
+ symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote);
+ }
+
+ // Compatibility variables, vertex only
+ if (spv == 0) {
+ BuiltInVariable("gl_Color", EbvColor, symbolTable);
+ BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable);
+ BuiltInVariable("gl_Normal", EbvNormal, symbolTable);
+ BuiltInVariable("gl_Vertex", EbvVertex, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord0", EbvMultiTexCoord0, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord1", EbvMultiTexCoord1, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord2", EbvMultiTexCoord2, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord3", EbvMultiTexCoord3, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord4", EbvMultiTexCoord4, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord5", EbvMultiTexCoord5, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord6", EbvMultiTexCoord6, symbolTable);
+ BuiltInVariable("gl_MultiTexCoord7", EbvMultiTexCoord7, symbolTable);
+ BuiltInVariable("gl_FogCoord", EbvFogFragCoord, symbolTable);
+ }
+
+ if (profile == EEsProfile) {
+ if (spv == 0) {
+ symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ }
+ if (version >= 310)
+ symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ }
+
+ if (profile == EEsProfile) {
+ symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
+ }
+
+ if (vulkan == 0) {
+ SpecialQualifier("gl_VertexID", EvqVertexId, EbvVertexId, symbolTable);
+ SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
+ }
+
+ BuiltInVariable("gl_VertexIndex", EbvVertexIndex, symbolTable);
+ BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable);
+
+ // Fall through
+
+ case EShLangTessControl:
+ if (profile == EEsProfile && version >= 310) {
+ symbolTable.setVariableExtensions("gl_BoundingBoxOES", Num_AEP_primitive_bounding_box, AEP_primitive_bounding_box);
+ BuiltInVariable("gl_BoundingBoxOES", EbvBoundingBox, symbolTable);
+ }
+
+ // Fall through
+
+ case EShLangTessEvaluation:
+ case EShLangGeometry:
+ SpecialQualifier("gl_Position", EvqPosition, EbvPosition, symbolTable);
+ SpecialQualifier("gl_PointSize", EvqPointSize, EbvPointSize, symbolTable);
+ SpecialQualifier("gl_ClipVertex", EvqClipVertex, EbvClipVertex, symbolTable);
+
+ BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable);
+ BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ BuiltInVariable("gl_out", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_out", "gl_PointSize", EbvPointSize, symbolTable);
+ BuiltInVariable("gl_out", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_out", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable);
+ BuiltInVariable("gl_PrimitiveIDIn", EbvPrimitiveId, symbolTable);
+ BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable);
+ BuiltInVariable("gl_InvocationID", EbvInvocationId, symbolTable);
+ BuiltInVariable("gl_Layer", EbvLayer, symbolTable);
+ BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable);
+ BuiltInVariable("gl_PatchVerticesIn", EbvPatchVertices, symbolTable);
+ BuiltInVariable("gl_TessLevelOuter", EbvTessLevelOuter, symbolTable);
+ BuiltInVariable("gl_TessLevelInner", EbvTessLevelInner, symbolTable);
+ BuiltInVariable("gl_TessCoord", EbvTessCoord, symbolTable);
+
+ if (version < 410)
+ symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_viewport_array);
+
+ // Compatibility variables
+
+ BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ BuiltInVariable("gl_out", "gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_out", "gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_out", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_out", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ BuiltInVariable("gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+
+ // gl_PointSize, when it needs to be tied to an extension, is always a member of a block.
+ // (Sometimes with an instance name, sometimes anonymous).
+ // However, the current automatic extension scheme does not work per block member,
+ // so for now check when parsing.
+ //
+ //if (profile == EEsProfile) {
+ // if (language == EShLangGeometry)
+ // symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_geometry_point_size, AEP_geometry_point_size);
+ // else if (language == EShLangTessEvaluation || language == EShLangTessControl)
+ // symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size);
+ //}
+
+ break;
+
+ case EShLangFragment:
+ SpecialQualifier("gl_FrontFacing", EvqFace, EbvFace, symbolTable);
+ SpecialQualifier("gl_FragCoord", EvqFragCoord, EbvFragCoord, symbolTable);
+ SpecialQualifier("gl_PointCoord", EvqPointCoord, EbvPointCoord, symbolTable);
+ SpecialQualifier("gl_FragColor", EvqFragColor, EbvFragColor, symbolTable);
+ SpecialQualifier("gl_FragDepth", EvqFragDepth, EbvFragDepth, symbolTable);
+ SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, EbvFragDepth, symbolTable);
+ SpecialQualifier("gl_HelperInvocation", EvqVaryingIn, EbvHelperInvocation, symbolTable);
+
+ BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable);
+ BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable);
+
+ if ((profile != EEsProfile && version >= 400) ||
+ (profile == EEsProfile && version >= 310)) {
+ BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable);
+ BuiltInVariable("gl_SamplePosition", EbvSamplePosition, symbolTable);
+ BuiltInVariable("gl_SampleMaskIn", EbvSampleMask, symbolTable);
+ BuiltInVariable("gl_SampleMask", EbvSampleMask, symbolTable);
+ if (profile == EEsProfile) {
+ symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_SampleMaskIn", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_OES_sample_variables);
+ symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_OES_sample_variables);
+ }
+ }
+
+ BuiltInVariable("gl_Layer", EbvLayer, symbolTable);
+ BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable);
+
+ // Compatibility variables
+
+ BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_Color", EbvColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_SecondaryColor", EbvSecondaryColor, symbolTable);
+
+ BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+ BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_Color", EbvColor, symbolTable);
+ BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable);
+
+ // built-in functions
+
+ if (profile == EEsProfile) {
+ if (spv == 0) {
+ symbolTable.setFunctionExtensions("texture2DLodEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjLodEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeLodEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ }
+ if (version == 100) {
+ symbolTable.setFunctionExtensions("dFdx", 1, &E_GL_OES_standard_derivatives);
+ symbolTable.setFunctionExtensions("dFdy", 1, &E_GL_OES_standard_derivatives);
+ symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_OES_standard_derivatives);
+ }
+ if (version >= 310) {
+ symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5);
+ symbolTable.setFunctionExtensions("interpolateAtCentroid", 1, &E_GL_OES_shader_multisample_interpolation);
+ symbolTable.setFunctionExtensions("interpolateAtSample", 1, &E_GL_OES_shader_multisample_interpolation);
+ symbolTable.setFunctionExtensions("interpolateAtOffset", 1, &E_GL_OES_shader_multisample_interpolation);
+ }
+ } else if (version < 130) {
+ if (spv == 0) {
+ symbolTable.setFunctionExtensions("texture1DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture1DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DProjLod", 1, &E_GL_ARB_shader_texture_lod);
+ }
+ }
+
+ // E_GL_ARB_shader_texture_lod functions usable only with the extension enabled
+ if (profile != EEsProfile && spv == 0) {
+ symbolTable.setFunctionExtensions("texture1DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture3DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("textureCubeGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("texture2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ symbolTable.setFunctionExtensions("shadow2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod);
+ }
+
+ // E_GL_ARB_shader_image_load_store
+ if (profile != EEsProfile && version < 420)
+ symbolTable.setFunctionExtensions("memoryBarrier", 1, &E_GL_ARB_shader_image_load_store);
+ // All the image access functions are protected by checks on the type of the first argument.
+
+ // E_GL_ARB_shader_atomic_counters
+ if (profile != EEsProfile && version < 420) {
+ symbolTable.setFunctionExtensions("atomicCounterIncrement", 1, &E_GL_ARB_shader_atomic_counters);
+ symbolTable.setFunctionExtensions("atomicCounterDecrement", 1, &E_GL_ARB_shader_atomic_counters);
+ symbolTable.setFunctionExtensions("atomicCounter" , 1, &E_GL_ARB_shader_atomic_counters);
+ }
+
+ // E_GL_ARB_derivative_control
+ if (profile != EEsProfile && version < 450) {
+ symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("dFdyFine", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("fwidthFine", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("dFdxCoarse", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_ARB_derivative_control);
+ symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_ARB_derivative_control);
+ }
+
+ // E_GL_ARB_sparse_texture2
+ if (profile != EEsProfile)
+ {
+ symbolTable.setFunctionExtensions("sparseTextureARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureLodARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTexelFetchARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTexelFetchOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureLodOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGradARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGradOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGatherARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGatherOffsetARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTextureGatherOffsetsARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseImageLoadARB", 1, &E_GL_ARB_sparse_texture2);
+ symbolTable.setFunctionExtensions("sparseTexelsResident", 1, &E_GL_ARB_sparse_texture2);
+ }
+
+ // E_GL_ARB_sparse_texture_clamp
+ if (profile != EEsProfile)
+ {
+ symbolTable.setFunctionExtensions("sparseTextureClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("sparseTextureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("sparseTextureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("sparseTextureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ symbolTable.setFunctionExtensions("textureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp);
+ }
+
+ symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
+
+ if (profile == EEsProfile) {
+ symbolTable.setVariableExtensions("gl_PrimitiveID", Num_AEP_geometry_shader, AEP_geometry_shader);
+ symbolTable.setVariableExtensions("gl_Layer", Num_AEP_geometry_shader, AEP_geometry_shader);
+ }
+
+ if (profile == EEsProfile) {
+ symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic);
+ symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
+ }
+ break;
+
+ case EShLangCompute:
+ BuiltInVariable("gl_NumWorkGroups", EbvNumWorkGroups, symbolTable);
+ BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable);
+ BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable);
+ BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable);
+ BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable);
+
+ if (profile != EEsProfile && version < 430) {
+ symbolTable.setVariableExtensions("gl_NumWorkGroups", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_ARB_compute_shader);
+
+ symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupCount", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupSize", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeUniformComponents", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeTextureImageUnits", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeImageUniforms", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounters", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounterBuffers", 1, &E_GL_ARB_compute_shader);
+
+ symbolTable.setFunctionExtensions("barrier", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierAtomicCounter", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierBuffer", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierImage", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_ARB_compute_shader);
+ symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader);
+ }
+ break;
+
+ default:
+ assert(false && "Language not supported");
+ break;
+ }
+
+ //
+ // Next, identify which built-ins have a mapping to an operator.
+ // If PureOperatorBuiltins is false, those that are not identified as such are
+ // expected to be resolved through a library of functions, versus as
+ // operations.
+ //
+ symbolTable.relateToOperator("not", EOpVectorLogicalNot);
+
+ symbolTable.relateToOperator("matrixCompMult", EOpMul);
+ // 120 and 150 are correct for both ES and desktop
+ if (version >= 120) {
+ symbolTable.relateToOperator("outerProduct", EOpOuterProduct);
+ symbolTable.relateToOperator("transpose", EOpTranspose);
+ if (version >= 150) {
+ symbolTable.relateToOperator("determinant", EOpDeterminant);
+ symbolTable.relateToOperator("inverse", EOpMatrixInverse);
+ }
+ }
+
+ symbolTable.relateToOperator("mod", EOpMod);
+ symbolTable.relateToOperator("modf", EOpModf);
+
+ symbolTable.relateToOperator("equal", EOpVectorEqual);
+ symbolTable.relateToOperator("notEqual", EOpVectorNotEqual);
+ symbolTable.relateToOperator("lessThan", EOpLessThan);
+ symbolTable.relateToOperator("greaterThan", EOpGreaterThan);
+ symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual);
+ symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+
+ symbolTable.relateToOperator("radians", EOpRadians);
+ symbolTable.relateToOperator("degrees", EOpDegrees);
+ symbolTable.relateToOperator("sin", EOpSin);
+ symbolTable.relateToOperator("cos", EOpCos);
+ symbolTable.relateToOperator("tan", EOpTan);
+ symbolTable.relateToOperator("asin", EOpAsin);
+ symbolTable.relateToOperator("acos", EOpAcos);
+ symbolTable.relateToOperator("atan", EOpAtan);
+ symbolTable.relateToOperator("sinh", EOpSinh);
+ symbolTable.relateToOperator("cosh", EOpCosh);
+ symbolTable.relateToOperator("tanh", EOpTanh);
+ symbolTable.relateToOperator("asinh", EOpAsinh);
+ symbolTable.relateToOperator("acosh", EOpAcosh);
+ symbolTable.relateToOperator("atanh", EOpAtanh);
+
+ symbolTable.relateToOperator("pow", EOpPow);
+ symbolTable.relateToOperator("exp2", EOpExp2);
+ symbolTable.relateToOperator("log", EOpLog);
+ symbolTable.relateToOperator("exp", EOpExp);
+ symbolTable.relateToOperator("log2", EOpLog2);
+ symbolTable.relateToOperator("sqrt", EOpSqrt);
+ symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt);
+
+ symbolTable.relateToOperator("abs", EOpAbs);
+ symbolTable.relateToOperator("sign", EOpSign);
+ symbolTable.relateToOperator("floor", EOpFloor);
+ symbolTable.relateToOperator("trunc", EOpTrunc);
+ symbolTable.relateToOperator("round", EOpRound);
+ symbolTable.relateToOperator("roundEven", EOpRoundEven);
+ symbolTable.relateToOperator("ceil", EOpCeil);
+ symbolTable.relateToOperator("fract", EOpFract);
+ symbolTable.relateToOperator("min", EOpMin);
+ symbolTable.relateToOperator("max", EOpMax);
+ symbolTable.relateToOperator("clamp", EOpClamp);
+ symbolTable.relateToOperator("mix", EOpMix);
+ symbolTable.relateToOperator("step", EOpStep);
+ symbolTable.relateToOperator("smoothstep", EOpSmoothStep);
+
+ symbolTable.relateToOperator("isnan", EOpIsNan);
+ symbolTable.relateToOperator("isinf", EOpIsInf);
+
+ symbolTable.relateToOperator("floatBitsToInt", EOpFloatBitsToInt);
+ symbolTable.relateToOperator("floatBitsToUint", EOpFloatBitsToUint);
+ symbolTable.relateToOperator("intBitsToFloat", EOpIntBitsToFloat);
+ symbolTable.relateToOperator("uintBitsToFloat", EOpUintBitsToFloat);
+ symbolTable.relateToOperator("doubleBitsToInt64", EOpDoubleBitsToInt64);
+ symbolTable.relateToOperator("doubleBitsToUint64", EOpDoubleBitsToUint64);
+ symbolTable.relateToOperator("int64BitsToDouble", EOpInt64BitsToDouble);
+ symbolTable.relateToOperator("uint64BitsToDouble", EOpUint64BitsToDouble);
+
+ symbolTable.relateToOperator("packSnorm2x16", EOpPackSnorm2x16);
+ symbolTable.relateToOperator("unpackSnorm2x16", EOpUnpackSnorm2x16);
+ symbolTable.relateToOperator("packUnorm2x16", EOpPackUnorm2x16);
+ symbolTable.relateToOperator("unpackUnorm2x16", EOpUnpackUnorm2x16);
+
+ symbolTable.relateToOperator("packSnorm4x8", EOpPackSnorm4x8);
+ symbolTable.relateToOperator("unpackSnorm4x8", EOpUnpackSnorm4x8);
+ symbolTable.relateToOperator("packUnorm4x8", EOpPackUnorm4x8);
+ symbolTable.relateToOperator("unpackUnorm4x8", EOpUnpackUnorm4x8);
+
+ symbolTable.relateToOperator("packDouble2x32", EOpPackDouble2x32);
+ symbolTable.relateToOperator("unpackDouble2x32", EOpUnpackDouble2x32);
+
+ symbolTable.relateToOperator("packHalf2x16", EOpPackHalf2x16);
+ symbolTable.relateToOperator("unpackHalf2x16", EOpUnpackHalf2x16);
+
+ symbolTable.relateToOperator("packInt2x32", EOpPackInt2x32);
+ symbolTable.relateToOperator("unpackInt2x32", EOpUnpackInt2x32);
+ symbolTable.relateToOperator("packUint2x32", EOpPackUint2x32);
+ symbolTable.relateToOperator("unpackUint2x32", EOpUnpackUint2x32);
+
+ symbolTable.relateToOperator("length", EOpLength);
+ symbolTable.relateToOperator("distance", EOpDistance);
+ symbolTable.relateToOperator("dot", EOpDot);
+ symbolTable.relateToOperator("cross", EOpCross);
+ symbolTable.relateToOperator("normalize", EOpNormalize);
+ symbolTable.relateToOperator("faceforward", EOpFaceForward);
+ symbolTable.relateToOperator("reflect", EOpReflect);
+ symbolTable.relateToOperator("refract", EOpRefract);
+
+ symbolTable.relateToOperator("any", EOpAny);
+ symbolTable.relateToOperator("all", EOpAll);
+
+ symbolTable.relateToOperator("barrier", EOpBarrier);
+ symbolTable.relateToOperator("memoryBarrier", EOpMemoryBarrier);
+ symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
+ symbolTable.relateToOperator("memoryBarrierBuffer", EOpMemoryBarrierBuffer);
+ symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage);
+
+ symbolTable.relateToOperator("atomicAdd", EOpAtomicAdd);
+ symbolTable.relateToOperator("atomicMin", EOpAtomicMin);
+ symbolTable.relateToOperator("atomicMax", EOpAtomicMax);
+ symbolTable.relateToOperator("atomicAnd", EOpAtomicAnd);
+ symbolTable.relateToOperator("atomicOr", EOpAtomicOr);
+ symbolTable.relateToOperator("atomicXor", EOpAtomicXor);
+ symbolTable.relateToOperator("atomicExchange", EOpAtomicExchange);
+ symbolTable.relateToOperator("atomicCompSwap", EOpAtomicCompSwap);
+
+ symbolTable.relateToOperator("atomicCounterIncrement", EOpAtomicCounterIncrement);
+ symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
+ symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter);
+
+ symbolTable.relateToOperator("fma", EOpFma);
+ symbolTable.relateToOperator("frexp", EOpFrexp);
+ symbolTable.relateToOperator("ldexp", EOpLdexp);
+ symbolTable.relateToOperator("uaddCarry", EOpAddCarry);
+ symbolTable.relateToOperator("usubBorrow", EOpSubBorrow);
+ symbolTable.relateToOperator("umulExtended", EOpUMulExtended);
+ symbolTable.relateToOperator("imulExtended", EOpIMulExtended);
+ symbolTable.relateToOperator("bitfieldExtract", EOpBitfieldExtract);
+ symbolTable.relateToOperator("bitfieldInsert", EOpBitfieldInsert);
+ symbolTable.relateToOperator("bitfieldReverse", EOpBitFieldReverse);
+ symbolTable.relateToOperator("bitCount", EOpBitCount);
+ symbolTable.relateToOperator("findLSB", EOpFindLSB);
+ symbolTable.relateToOperator("findMSB", EOpFindMSB);
+
+ if (PureOperatorBuiltins) {
+ symbolTable.relateToOperator("imageSize", EOpImageQuerySize);
+ symbolTable.relateToOperator("imageSamples", EOpImageQuerySamples);
+ symbolTable.relateToOperator("imageLoad", EOpImageLoad);
+ symbolTable.relateToOperator("imageStore", EOpImageStore);
+ symbolTable.relateToOperator("imageAtomicAdd", EOpImageAtomicAdd);
+ symbolTable.relateToOperator("imageAtomicMin", EOpImageAtomicMin);
+ symbolTable.relateToOperator("imageAtomicMax", EOpImageAtomicMax);
+ symbolTable.relateToOperator("imageAtomicAnd", EOpImageAtomicAnd);
+ symbolTable.relateToOperator("imageAtomicOr", EOpImageAtomicOr);
+ symbolTable.relateToOperator("imageAtomicXor", EOpImageAtomicXor);
+ symbolTable.relateToOperator("imageAtomicExchange", EOpImageAtomicExchange);
+ symbolTable.relateToOperator("imageAtomicCompSwap", EOpImageAtomicCompSwap);
+
+ symbolTable.relateToOperator("subpassLoad", EOpSubpassLoad);
+ symbolTable.relateToOperator("subpassLoadMS", EOpSubpassLoadMS);
+
+ symbolTable.relateToOperator("textureSize", EOpTextureQuerySize);
+ symbolTable.relateToOperator("textureQueryLod", EOpTextureQueryLod);
+ symbolTable.relateToOperator("textureQueryLevels", EOpTextureQueryLevels);
+ symbolTable.relateToOperator("textureSamples", EOpTextureQuerySamples);
+ symbolTable.relateToOperator("texture", EOpTexture);
+ symbolTable.relateToOperator("textureProj", EOpTextureProj);
+ symbolTable.relateToOperator("textureLod", EOpTextureLod);
+ symbolTable.relateToOperator("textureOffset", EOpTextureOffset);
+ symbolTable.relateToOperator("texelFetch", EOpTextureFetch);
+ symbolTable.relateToOperator("texelFetchOffset", EOpTextureFetchOffset);
+ symbolTable.relateToOperator("textureProjOffset", EOpTextureProjOffset);
+ symbolTable.relateToOperator("textureLodOffset", EOpTextureLodOffset);
+ symbolTable.relateToOperator("textureProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("textureProjLodOffset", EOpTextureProjLodOffset);
+ symbolTable.relateToOperator("textureGrad", EOpTextureGrad);
+ symbolTable.relateToOperator("textureGradOffset", EOpTextureGradOffset);
+ symbolTable.relateToOperator("textureProjGrad", EOpTextureProjGrad);
+ symbolTable.relateToOperator("textureProjGradOffset", EOpTextureProjGradOffset);
+ symbolTable.relateToOperator("textureGather", EOpTextureGather);
+ symbolTable.relateToOperator("textureGatherOffset", EOpTextureGatherOffset);
+ symbolTable.relateToOperator("textureGatherOffsets", EOpTextureGatherOffsets);
+
+ symbolTable.relateToOperator("noise1", EOpNoise);
+ symbolTable.relateToOperator("noise2", EOpNoise);
+ symbolTable.relateToOperator("noise3", EOpNoise);
+ symbolTable.relateToOperator("noise4", EOpNoise);
+
+ if (spv == 0 && (IncludeLegacy(version, profile, spv) || (profile == EEsProfile && version == 100))) {
+ symbolTable.relateToOperator("ftransform", EOpFtransform);
+
+ symbolTable.relateToOperator("texture1D", EOpTexture);
+ symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture1DProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture1DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture1DLod", EOpTextureLod);
+ symbolTable.relateToOperator("texture1DProjLod", EOpTextureProjLod);
+
+ symbolTable.relateToOperator("texture2DRect", EOpTexture);
+ symbolTable.relateToOperator("texture2DRectProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture2DRectGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture2DRectProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("shadow2DRect", EOpTexture);
+ symbolTable.relateToOperator("shadow2DRectProj", EOpTextureProj);
+ symbolTable.relateToOperator("shadow2DRectGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("shadow2DRectProjGradARB", EOpTextureProjGrad);
+
+ symbolTable.relateToOperator("texture2D", EOpTexture);
+ symbolTable.relateToOperator("texture2DProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture2DGradEXT", EOpTextureGrad);
+ symbolTable.relateToOperator("texture2DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture2DProjGradEXT", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture2DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture2DLod", EOpTextureLod);
+ symbolTable.relateToOperator("texture2DLodEXT", EOpTextureLod);
+ symbolTable.relateToOperator("texture2DProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("texture2DProjLodEXT", EOpTextureProjLod);
+
+ symbolTable.relateToOperator("texture3D", EOpTexture);
+ symbolTable.relateToOperator("texture3DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("texture3DProj", EOpTextureProj);
+ symbolTable.relateToOperator("texture3DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("texture3DLod", EOpTextureLod);
+ symbolTable.relateToOperator("texture3DProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("textureCube", EOpTexture);
+ symbolTable.relateToOperator("textureCubeGradEXT", EOpTextureGrad);
+ symbolTable.relateToOperator("textureCubeGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("textureCubeLod", EOpTextureLod);
+ symbolTable.relateToOperator("textureCubeLodEXT", EOpTextureLod);
+ symbolTable.relateToOperator("shadow1D", EOpTexture);
+ symbolTable.relateToOperator("shadow1DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("shadow2D", EOpTexture);
+ symbolTable.relateToOperator("shadow2DGradARB", EOpTextureGrad);
+ symbolTable.relateToOperator("shadow1DProj", EOpTextureProj);
+ symbolTable.relateToOperator("shadow2DProj", EOpTextureProj);
+ symbolTable.relateToOperator("shadow1DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("shadow2DProjGradARB", EOpTextureProjGrad);
+ symbolTable.relateToOperator("shadow1DLod", EOpTextureLod);
+ symbolTable.relateToOperator("shadow2DLod", EOpTextureLod);
+ symbolTable.relateToOperator("shadow1DProjLod", EOpTextureProjLod);
+ symbolTable.relateToOperator("shadow2DProjLod", EOpTextureProjLod);
+ }
+
+ if (profile != EEsProfile) {
+ symbolTable.relateToOperator("sparseTextureARB", EOpSparseTexture);
+ symbolTable.relateToOperator("sparseTextureLodARB", EOpSparseTextureLod);
+ symbolTable.relateToOperator("sparseTextureOffsetARB", EOpSparseTextureOffset);
+ symbolTable.relateToOperator("sparseTexelFetchARB", EOpSparseTextureFetch);
+ symbolTable.relateToOperator("sparseTexelFetchOffsetARB", EOpSparseTextureFetchOffset);
+ symbolTable.relateToOperator("sparseTextureLodOffsetARB", EOpSparseTextureLodOffset);
+ symbolTable.relateToOperator("sparseTextureGradARB", EOpSparseTextureGrad);
+ symbolTable.relateToOperator("sparseTextureGradOffsetARB", EOpSparseTextureGradOffset);
+ symbolTable.relateToOperator("sparseTextureGatherARB", EOpSparseTextureGather);
+ symbolTable.relateToOperator("sparseTextureGatherOffsetARB", EOpSparseTextureGatherOffset);
+ symbolTable.relateToOperator("sparseTextureGatherOffsetsARB", EOpSparseTextureGatherOffsets);
+ symbolTable.relateToOperator("sparseImageLoadARB", EOpSparseImageLoad);
+ symbolTable.relateToOperator("sparseTexelsResidentARB", EOpSparseTexelsResident);
+
+ symbolTable.relateToOperator("sparseTextureClampARB", EOpSparseTextureClamp);
+ symbolTable.relateToOperator("sparseTextureOffsetClampARB", EOpSparseTextureOffsetClamp);
+ symbolTable.relateToOperator("sparseTextureGradClampARB", EOpSparseTextureGradClamp);
+ symbolTable.relateToOperator("sparseTextureGradOffsetClampARB", EOpSparseTextureGradOffsetClamp);
+ symbolTable.relateToOperator("textureClampARB", EOpTextureClamp);
+ symbolTable.relateToOperator("textureOffsetClampARB", EOpTextureOffsetClamp);
+ symbolTable.relateToOperator("textureGradClampARB", EOpTextureGradClamp);
+ symbolTable.relateToOperator("textureGradOffsetClampARB", EOpTextureGradOffsetClamp);
+
+ symbolTable.relateToOperator("ballotARB", EOpBallot);
+ symbolTable.relateToOperator("readInvocationARB", EOpReadInvocation);
+ symbolTable.relateToOperator("readFirstInvocationARB", EOpReadFirstInvocation);
+
+ symbolTable.relateToOperator("anyInvocationARB", EOpAnyInvocation);
+ symbolTable.relateToOperator("allInvocationsARB", EOpAllInvocations);
+ symbolTable.relateToOperator("allInvocationsEqualARB", EOpAllInvocationsEqual);
+ }
+ }
+
+ switch(language) {
+ case EShLangVertex:
+ break;
+
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ break;
+
+ case EShLangGeometry:
+ symbolTable.relateToOperator("EmitStreamVertex", EOpEmitStreamVertex);
+ symbolTable.relateToOperator("EndStreamPrimitive", EOpEndStreamPrimitive);
+ symbolTable.relateToOperator("EmitVertex", EOpEmitVertex);
+ symbolTable.relateToOperator("EndPrimitive", EOpEndPrimitive);
+ break;
+
+ case EShLangFragment:
+ symbolTable.relateToOperator("dFdx", EOpDPdx);
+ symbolTable.relateToOperator("dFdy", EOpDPdy);
+ symbolTable.relateToOperator("fwidth", EOpFwidth);
+ if (profile != EEsProfile && version >= 400) {
+ symbolTable.relateToOperator("dFdxFine", EOpDPdxFine);
+ symbolTable.relateToOperator("dFdyFine", EOpDPdyFine);
+ symbolTable.relateToOperator("fwidthFine", EOpFwidthFine);
+ symbolTable.relateToOperator("dFdxCoarse", EOpDPdxCoarse);
+ symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse);
+ symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse);
+ }
+ symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid);
+ symbolTable.relateToOperator("interpolateAtSample", EOpInterpolateAtSample);
+ symbolTable.relateToOperator("interpolateAtOffset", EOpInterpolateAtOffset);
+ break;
+
+ case EShLangCompute:
+ symbolTable.relateToOperator("memoryBarrierShared", EOpMemoryBarrierShared);
+ symbolTable.relateToOperator("groupMemoryBarrier", EOpGroupMemoryBarrier);
+ break;
+
+ default:
+ assert(false && "Language not supported");
+ }
+}
+
+//
+// Add context-dependent (resource-specific) built-ins not handled by the above. These
+// would be ones that need to be programmatically added because they cannot
+// be added by simple text strings. For these, also
+// 1) Map built-in functions to operators, for those that will turn into an operation node
+// instead of remaining a function call.
+// 2) Tag extension-related symbols added to their base version with their extensions, so
+// that if an early version has the extension turned off, there is an error reported on use.
+//
+void TBuiltIns::identifyBuiltIns(int version, EProfile profile, int spv, int /*vulkan*/, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
+{
+ if (profile != EEsProfile && version >= 430 && version < 440) {
+ symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &E_GL_ARB_enhanced_layouts);
+ symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &E_GL_ARB_enhanced_layouts);
+ }
+ if (profile != EEsProfile && version >= 130 && version < 420) {
+ symbolTable.setVariableExtensions("gl_MinProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack);
+ symbolTable.setVariableExtensions("gl_MaxProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack);
+ }
+ if (profile != EEsProfile && version >= 150 && version < 410)
+ symbolTable.setVariableExtensions("gl_MaxViewports", 1, &E_GL_ARB_viewport_array);
+
+ switch(language) {
+ case EShLangFragment:
+ // Set up gl_FragData based on current array size.
+ if (version == 100 || IncludeLegacy(version, profile, spv) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) {
+ TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone;
+ TType fragData(EbtFloat, EvqFragColor, pq, 4);
+ TArraySizes& arraySizes = *new TArraySizes;
+ arraySizes.addInnerSize(resources.maxDrawBuffers);
+ fragData.newArraySizes(arraySizes);
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
+ SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable);
+ }
+ break;
+
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ // Because of the context-dependent array size (gl_MaxPatchVertices),
+ // these variables were added later than the others and need to be mapped now.
+
+ // standard members
+ BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable);
+ BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable);
+ BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable);
+ BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable);
+
+ // compatibility members
+ BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable);
+ BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable);
+ BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable);
+ break;
+
+ default:
+ break;
+ }
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.h
new file mode 100644
index 00000000000..40551cddcb9
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Initialize.h
@@ -0,0 +1,113 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013-2016 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "../Include/ResourceLimits.h"
+#include "../Include/Common.h"
+#include "../Include/ShHandle.h"
+#include "SymbolTable.h"
+#include "Versions.h"
+
+namespace glslang {
+
+//
+// This is made to hold parseable strings for almost all the built-in
+// functions and variables for one specific combination of version
+// and profile. (Some still need to be added programmatically.)
+// This is a base class for language-specific derivations, which
+// can be used for language independent builtins.
+//
+// The strings are organized by
+// commonBuiltins: intersection of all stages' built-ins, processed just once
+// stageBuiltins[]: anything a stage needs that's not in commonBuiltins
+//
+class TBuiltInParseables {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ TBuiltInParseables();
+ virtual ~TBuiltInParseables();
+ virtual void initialize(int version, EProfile, int spv, int vulkan) = 0;
+ virtual void initialize(const TBuiltInResource& resources, int version, EProfile, int spv, int vulkan, EShLanguage) = 0;
+ virtual const TString& getCommonString() const { return commonBuiltins; }
+ virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; }
+
+ virtual void identifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLanguage language, TSymbolTable& symbolTable) = 0;
+
+ virtual void identifyBuiltIns(int version, EProfile profile, int spv, int /*vulkan*/, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0;
+
+protected:
+ TString commonBuiltins;
+ TString stageBuiltins[EShLangCount];
+};
+
+//
+// This is a GLSL specific derivation of TBuiltInParseables. To present a stable
+// interface and match other similar code, it is called TBuiltIns, rather
+// than TBuiltInParseablesGlsl.
+//
+class TBuiltIns : public TBuiltInParseables {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ TBuiltIns();
+ virtual ~TBuiltIns();
+ void initialize(int version, EProfile, int spv, int vulkan);
+ void initialize(const TBuiltInResource& resources, int version, EProfile, int spv, int vulkan, EShLanguage);
+
+ void identifyBuiltIns(int version, EProfile profile, int spv, int vulkan, EShLanguage language, TSymbolTable& symbolTable);
+
+ void identifyBuiltIns(int version, EProfile profile, int spv, int /*vulkan*/, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources);
+
+protected:
+ void add2ndGenerationSamplingImaging(int version, EProfile profile, int spv, int vulkan);
+ void addSubpassSampling(TSampler, TString& typeName, int version, EProfile profile);
+ void addQueryFunctions(TSampler, TString& typeName, int version, EProfile profile);
+ void addImageFunctions(TSampler, TString& typeName, int version, EProfile profile);
+ void addSamplingFunctions(TSampler, TString& typeName, int version, EProfile profile);
+ void addGatherFunctions(TSampler, TString& typeName, int version, EProfile profile);
+
+ // Helpers for making textual representations of the permutations
+ // of texturing/imaging functions.
+ const char* postfixes[5];
+ const char* prefixes[EbtNumTypes];
+ int dimMap[EsdNumDims];
+};
+
+
+} // end namespace glslang
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/IntermTraverse.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/IntermTraverse.cpp
new file mode 100644
index 00000000000..b910f473883
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/IntermTraverse.cpp
@@ -0,0 +1,302 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//Copyright (c) 2002-2010 The ANGLE Project Authors.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+
+namespace glslang {
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straightforward....
+//
+void TIntermMethod::traverse(TIntermTraverser*)
+{
+ // Tree should always resolve all methods as a non-method.
+}
+
+void TIntermSymbol::traverse(TIntermTraverser *it)
+{
+ it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser *it)
+{
+ it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ //
+ // visit the node before children if pre-visiting.
+ //
+ if (it->preVisit)
+ visit = it->visitBinary(EvPreVisit, this);
+
+ //
+ // Visit the children, in the right order.
+ //
+ if (visit) {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft) {
+ if (right)
+ right->traverse(it);
+
+ if (it->inVisit)
+ visit = it->visitBinary(EvInVisit, this);
+
+ if (visit && left)
+ left->traverse(it);
+ } else {
+ if (left)
+ left->traverse(it);
+
+ if (it->inVisit)
+ visit = it->visitBinary(EvInVisit, this);
+
+ if (visit && right)
+ right->traverse(it);
+ }
+
+ it->decrementDepth();
+ }
+
+ //
+ // Visit the node after the children, if requested and the traversal
+ // hasn't been canceled yet.
+ //
+ if (visit && it->postVisit)
+ it->visitBinary(EvPostVisit, this);
+}
+
+//
+// Traverse a unary node. Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitUnary(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ operand->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitUnary(EvPostVisit, this);
+}
+
+//
+// Traverse an aggregate node. Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitAggregate(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft) {
+ for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
+ (*sit)->traverse(it);
+
+ if (visit && it->inVisit) {
+ if (*sit != sequence.front())
+ visit = it->visitAggregate(EvInVisit, this);
+ }
+ }
+ } else {
+ for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
+ (*sit)->traverse(it);
+
+ if (visit && it->inVisit) {
+ if (*sit != sequence.back())
+ visit = it->visitAggregate(EvInVisit, this);
+ }
+ }
+ }
+
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitAggregate(EvPostVisit, this);
+}
+
+//
+// Traverse a selection node. Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSelection(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ if (it->rightToLeft) {
+ if (falseBlock)
+ falseBlock->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ if (falseBlock)
+ falseBlock->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSelection(EvPostVisit, this);
+}
+
+//
+// Traverse a loop node. Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitLoop(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft) {
+ if (terminal)
+ terminal->traverse(it);
+
+ if (body)
+ body->traverse(it);
+
+ if (test)
+ test->traverse(it);
+ } else {
+ if (test)
+ test->traverse(it);
+
+ if (body)
+ body->traverse(it);
+
+ if (terminal)
+ terminal->traverse(it);
+ }
+
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitLoop(EvPostVisit, this);
+}
+
+//
+// Traverse a branch node. Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitBranch(EvPreVisit, this);
+
+ if (visit && expression) {
+ it->incrementDepth(this);
+ expression->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitBranch(EvPostVisit, this);
+}
+
+//
+// Traverse a switch node.
+//
+void TIntermSwitch::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSwitch(EvPreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ if (it->rightToLeft) {
+ body->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ body->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSwitch(EvPostVisit, this);
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp
new file mode 100644
index 00000000000..02681ac556b
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp
@@ -0,0 +1,1980 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2015 LunarG, Inc.
+//Copyright (C) 2015-2016 Google, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include "localintermediate.h"
+#include "RemoveTree.h"
+#include "SymbolTable.h"
+#include "propagateNoContraction.h"
+
+#include <float.h>
+
+namespace glslang {
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray,
+ TIntermTyped* constSubtree, const TSourceLoc& loc)
+{
+ TIntermSymbol* node = new TIntermSymbol(id, name, type);
+ node->setLoc(loc);
+ node->setConstArray(constArray);
+ node->setConstSubtree(constSubtree);
+
+ return node;
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable)
+{
+ glslang::TSourceLoc loc; // just a null location
+ loc.init();
+
+ return addSymbol(variable, loc);
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc)
+{
+ return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc);
+}
+
+TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc)
+{
+ TConstUnionArray unionArray; // just a null constant
+
+ return addSymbol(0, "", type, unionArray, nullptr, loc);
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
+{
+ // No operations work on blocks
+ if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
+ return 0;
+
+ // Try converting the children's base types to compatible types.
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child)
+ right = child;
+ else {
+ child = addConversion(op, right->getType(), left);
+ if (child)
+ left = child;
+ else
+ return 0;
+ }
+
+ //
+ // Need a new node holding things together. Make
+ // one and promote it to the right type.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ if (loc.line == 0)
+ loc = right->getLoc();
+ node->setLoc(loc);
+
+ node->setLeft(left);
+ node->setRight(right);
+ if (! node->promote())
+ return 0;
+
+ node->updatePrecision();
+
+ //
+ // If they are both (non-specialization) constants, they must be folded.
+ // (Unless it's the sequence (comma) operator, but that's handled in addComma().)
+ //
+ TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+ TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+ if (leftTempConstant && rightTempConstant) {
+ TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant);
+ if (folded)
+ return folded;
+ }
+
+ // If either is a specialization constant, while the other is
+ // a constant (or specialization constant), the result is still
+ // a specialization constant, if the operation is an allowed
+ // specialization-constant operation.
+ if (( left->getType().getQualifier().isSpecConstant() && right->getType().getQualifier().isConstant()) ||
+ (right->getType().getQualifier().isSpecConstant() && left->getType().getQualifier().isConstant()))
+ if (isSpecializationOperation(*node))
+ node->getWritableType().getQualifier().makeSpecConstant();
+
+ return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
+{
+ // No block assignment
+ if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
+ return 0;
+
+ //
+ // Like adding binary math, except the conversion can only go
+ // from right to left.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ if (loc.line == 0)
+ loc = left->getLoc();
+ node->setLoc(loc);
+
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child == 0)
+ return 0;
+
+ node->setLeft(left);
+ node->setRight(child);
+ if (! node->promote())
+ return 0;
+
+ node->updatePrecision();
+
+ return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
+{
+ TIntermBinary* node = new TIntermBinary(op);
+ if (loc.line == 0)
+ loc = index->getLoc();
+ node->setLoc(loc);
+ node->setLeft(base);
+ node->setRight(index);
+
+ // caller should set the type
+
+ return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
+{
+ if (child == 0)
+ return 0;
+
+ if (child->getType().getBasicType() == EbtBlock)
+ return 0;
+
+ switch (op) {
+ case EOpLogicalNot:
+ if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+ return 0;
+ }
+ break;
+
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ case EOpNegative:
+ if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+ return 0;
+ default: break; // some compilers want this
+ }
+
+ //
+ // Do we need to promote the operand?
+ //
+ TBasicType newType = EbtVoid;
+ switch (op) {
+ case EOpConstructInt: newType = EbtInt; break;
+ case EOpConstructUint: newType = EbtUint; break;
+ case EOpConstructInt64: newType = EbtInt64; break;
+ case EOpConstructUint64: newType = EbtUint64; break;
+ case EOpConstructBool: newType = EbtBool; break;
+ case EOpConstructFloat: newType = EbtFloat; break;
+ case EOpConstructDouble: newType = EbtDouble; break;
+ default: break; // some compilers want this
+ }
+
+ if (newType != EbtVoid) {
+ child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(),
+ child->getMatrixCols(),
+ child->getMatrixRows()),
+ child);
+ if (child == 0)
+ return 0;
+ }
+
+ //
+ // For constructors, we are now done, it was all in the conversion.
+ // TODO: but, did this bypass constant folding?
+ //
+ switch (op) {
+ case EOpConstructInt:
+ case EOpConstructUint:
+ case EOpConstructInt64:
+ case EOpConstructUint64:
+ case EOpConstructBool:
+ case EOpConstructFloat:
+ case EOpConstructDouble:
+ return child;
+ default: break; // some compilers want this
+ }
+
+ //
+ // Make a new node for the operator.
+ //
+ TIntermUnary* node = new TIntermUnary(op);
+ if (loc.line == 0)
+ loc = child->getLoc();
+ node->setLoc(loc);
+ node->setOperand(child);
+
+ if (! node->promote())
+ return 0;
+
+ node->updatePrecision();
+
+ // If it's a (non-specialization) constant, it must be folded.
+ if (child->getAsConstantUnion())
+ return child->getAsConstantUnion()->fold(op, node->getType());
+
+ // If it's a specialization constant, the result is too,
+ // if the operation is allowed for specialization constants.
+ if (child->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
+ node->getWritableType().getQualifier().makeSpecConstant();
+
+ return node;
+}
+
+TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOperator op, bool unary, TIntermNode* childNode, const TType& returnType)
+{
+ if (unary) {
+ //
+ // Treat it like a unary operator.
+ // addUnaryMath() should get the type correct on its own;
+ // including constness (which would differ from the prototype).
+ //
+ TIntermTyped* child = childNode->getAsTyped();
+ if (child == 0)
+ return 0;
+
+ if (child->getAsConstantUnion()) {
+ TIntermTyped* folded = child->getAsConstantUnion()->fold(op, returnType);
+ if (folded)
+ return folded;
+ }
+
+ TIntermUnary* node = new TIntermUnary(op);
+ node->setLoc(child->getLoc());
+ node->setOperand(child);
+ node->setType(returnType);
+
+ // propagate precision up from child
+ if (profile == EEsProfile && returnType.getQualifier().precision == EpqNone && returnType.getBasicType() != EbtBool)
+ node->getQualifier().precision = child->getQualifier().precision;
+
+ // propagate precision down to child
+ if (node->getQualifier().precision != EpqNone)
+ child->propagatePrecision(node->getQualifier().precision);
+
+ return node;
+ } else {
+ // setAggregateOperater() calls fold() for constant folding
+ TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
+
+ // if not folded, we'll still have an aggregate node to propagate precision with
+ if (node->getAsAggregate()) {
+ TPrecisionQualifier correctPrecision = returnType.getQualifier().precision;
+ if (correctPrecision == EpqNone && profile == EEsProfile) {
+ // find the maximum precision from the arguments, for the built-in's return precision
+ TIntermSequence& sequence = node->getAsAggregate()->getSequence();
+ for (unsigned int arg = 0; arg < sequence.size(); ++arg)
+ correctPrecision = std::max(correctPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
+ }
+
+ // Propagate precision through this node and its children. That algorithm stops
+ // when a precision is found, so start by clearing this subroot precision
+ node->getQualifier().precision = EpqNone;
+ node->propagatePrecision(correctPrecision);
+ }
+
+ return node;
+ }
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing. Especially for establishing
+// a function call's operation on it's set of parameters. Sequences
+// of instructions are also aggregates, but they just directly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate.
+//
+TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc)
+{
+ TIntermAggregate* aggNode;
+
+ //
+ // Make sure we have an aggregate. If not turn it into one.
+ //
+ if (node) {
+ aggNode = node->getAsAggregate();
+ if (aggNode == 0 || aggNode->getOp() != EOpNull) {
+ //
+ // Make an aggregate containing this node.
+ //
+ aggNode = new TIntermAggregate();
+ aggNode->getSequence().push_back(node);
+ if (loc.line == 0)
+ loc = node->getLoc();
+ }
+ } else
+ aggNode = new TIntermAggregate();
+
+ //
+ // Set the operator.
+ //
+ aggNode->setOperator(op);
+ if (loc.line != 0)
+ aggNode->setLoc(loc);
+
+ aggNode->setType(type);
+
+ return fold(aggNode);
+}
+
+//
+// Convert the node's type to the given type, as allowed by the operation involved: 'op'.
+// For implicit conversions, 'op' is not the requested conversion, it is the explicit
+// operation requiring the implicit conversion.
+//
+// Returns a node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Return 0 if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const
+{
+ //
+ // Does the base type even allow the operation?
+ //
+ switch (node->getBasicType()) {
+ case EbtVoid:
+ return 0;
+ case EbtAtomicUint:
+ case EbtSampler:
+ // opaque types can be passed to functions
+ if (op == EOpFunction)
+ break;
+ // samplers can get assigned via a sampler constructor
+ // (well, not yet, but code in the rest of this function is ready for it)
+ if (node->getBasicType() == EbtSampler && op == EOpAssign &&
+ node->getAsOperator() != nullptr && node->getAsOperator()->getOp() == EOpConstructTextureSampler)
+ break;
+
+ // otherwise, opaque types can't even be operated on, let alone converted
+ return 0;
+ default:
+ break;
+ }
+
+ // Otherwise, if types are identical, no problem
+ if (type == node->getType())
+ return node;
+
+ // If one's a structure, then no conversions.
+ if (type.isStruct() || node->isStruct())
+ return 0;
+
+ // If one's an array, then no conversions.
+ if (type.isArray() || node->getType().isArray())
+ return 0;
+
+ // Note: callers are responsible for other aspects of shape,
+ // like vector and matrix sizes.
+
+ TBasicType promoteTo;
+
+ switch (op) {
+ //
+ // Explicit conversions (unary operations)
+ //
+ case EOpConstructBool:
+ promoteTo = EbtBool;
+ break;
+ case EOpConstructFloat:
+ promoteTo = EbtFloat;
+ break;
+ case EOpConstructDouble:
+ promoteTo = EbtDouble;
+ break;
+ case EOpConstructInt:
+ promoteTo = EbtInt;
+ break;
+ case EOpConstructUint:
+ promoteTo = EbtUint;
+ break;
+ case EOpConstructInt64:
+ promoteTo = EbtInt64;
+ break;
+ case EOpConstructUint64:
+ promoteTo = EbtUint64;
+ break;
+
+ //
+ // List all the binary ops that can implicitly convert one operand to the other's type;
+ // This implements the 'policy' for implicit type conversion.
+ //
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ case EOpEqual:
+ case EOpNotEqual:
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpDiv:
+ case EOpMod:
+
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+
+ case EOpFunctionCall:
+ case EOpReturn:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+
+ case EOpSequence:
+ case EOpConstructStruct:
+
+ if (type.getBasicType() == node->getType().getBasicType())
+ return node;
+
+ if (canImplicitlyPromote(node->getType().getBasicType(), type.getBasicType()))
+ promoteTo = type.getBasicType();
+ else
+ return 0;
+
+ break;
+
+ // Shifts can have mixed types as long as they are integer, without converting.
+ // It's the left operand's type that determines the resulting type, so no issue
+ // with assign shift ops either.
+ case EOpLeftShift:
+ case EOpRightShift:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ if ((type.getBasicType() == EbtInt ||
+ type.getBasicType() == EbtUint ||
+ type.getBasicType() == EbtInt64 ||
+ type.getBasicType() == EbtUint64) &&
+ (node->getType().getBasicType() == EbtInt ||
+ node->getType().getBasicType() == EbtUint ||
+ node->getType().getBasicType() == EbtInt64 ||
+ node->getType().getBasicType() == EbtUint64))
+
+ return node;
+ else
+ return 0;
+
+ default:
+ // default is to require a match; all exceptions should have case statements above
+
+ if (type.getBasicType() == node->getType().getBasicType())
+ return node;
+ else
+ return 0;
+ }
+
+ if (node->getAsConstantUnion())
+ return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
+
+ //
+ // Add a new newNode for the conversion.
+ //
+ TIntermUnary* newNode = 0;
+
+ TOperator newOp = EOpNull;
+
+ // This is 'mechanism' here, it does any conversion told. The policy comes
+ // from the shader or the above code.
+ switch (promoteTo) {
+ case EbtDouble:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToDouble; break;
+ case EbtUint: newOp = EOpConvUintToDouble; break;
+ case EbtBool: newOp = EOpConvBoolToDouble; break;
+ case EbtFloat: newOp = EOpConvFloatToDouble; break;
+ case EbtInt64: newOp = EOpConvInt64ToDouble; break;
+ case EbtUint64: newOp = EOpConvUint64ToDouble; break;
+ default:
+ return 0;
+ }
+ break;
+ case EbtFloat:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToFloat; break;
+ case EbtUint: newOp = EOpConvUintToFloat; break;
+ case EbtBool: newOp = EOpConvBoolToFloat; break;
+ case EbtDouble: newOp = EOpConvDoubleToFloat; break;
+ case EbtInt64: newOp = EOpConvInt64ToFloat; break;
+ case EbtUint64: newOp = EOpConvUint64ToFloat; break;
+ default:
+ return 0;
+ }
+ break;
+ case EbtBool:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToBool; break;
+ case EbtUint: newOp = EOpConvUintToBool; break;
+ case EbtFloat: newOp = EOpConvFloatToBool; break;
+ case EbtDouble: newOp = EOpConvDoubleToBool; break;
+ case EbtInt64: newOp = EOpConvInt64ToBool; break;
+ case EbtUint64: newOp = EOpConvUint64ToBool; break;
+ default:
+ return 0;
+ }
+ break;
+ case EbtInt:
+ switch (node->getBasicType()) {
+ case EbtUint: newOp = EOpConvUintToInt; break;
+ case EbtBool: newOp = EOpConvBoolToInt; break;
+ case EbtFloat: newOp = EOpConvFloatToInt; break;
+ case EbtDouble: newOp = EOpConvDoubleToInt; break;
+ case EbtInt64: newOp = EOpConvInt64ToInt; break;
+ case EbtUint64: newOp = EOpConvUint64ToInt; break;
+ default:
+ return 0;
+ }
+ break;
+ case EbtUint:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToUint; break;
+ case EbtBool: newOp = EOpConvBoolToUint; break;
+ case EbtFloat: newOp = EOpConvFloatToUint; break;
+ case EbtDouble: newOp = EOpConvDoubleToUint; break;
+ case EbtInt64: newOp = EOpConvInt64ToUint; break;
+ case EbtUint64: newOp = EOpConvUint64ToUint; break;
+ default:
+ return 0;
+ }
+ break;
+ case EbtInt64:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToInt64; break;
+ case EbtUint: newOp = EOpConvUintToInt64; break;
+ case EbtBool: newOp = EOpConvBoolToInt64; break;
+ case EbtFloat: newOp = EOpConvFloatToInt64; break;
+ case EbtDouble: newOp = EOpConvDoubleToInt64; break;
+ case EbtUint64: newOp = EOpConvUint64ToInt64; break;
+ default:
+ return 0;
+ }
+ break;
+ case EbtUint64:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToUint64; break;
+ case EbtUint: newOp = EOpConvUintToUint64; break;
+ case EbtBool: newOp = EOpConvBoolToUint64; break;
+ case EbtFloat: newOp = EOpConvFloatToUint64; break;
+ case EbtDouble: newOp = EOpConvDoubleToUint64; break;
+ case EbtInt64: newOp = EOpConvInt64ToUint64; break;
+ default:
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ TType newType(promoteTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
+ newNode = new TIntermUnary(newOp, newType);
+ newNode->setLoc(node->getLoc());
+ newNode->setOperand(node);
+
+ // TODO: it seems that some unary folding operations should occur here, but are not
+
+ // Propagate specialization-constant-ness, if allowed
+ if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode))
+ newNode->getWritableType().getQualifier().makeSpecConstant();
+
+ return newNode;
+}
+
+//
+// See if the 'from' type is allowed to be implicitly converted to the
+// 'to' type. This is not about vector/array/struct, only about basic type.
+//
+bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to) const
+{
+ if (profile == EEsProfile || version == 110)
+ return false;
+
+ switch (to) {
+ case EbtDouble:
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ case EbtFloat:
+ case EbtDouble:
+ return true;
+ default:
+ return false;
+ }
+ case EbtFloat:
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ case EbtFloat:
+ return true;
+ default:
+ return false;
+ }
+ case EbtUint:
+ switch (from) {
+ case EbtInt:
+ return version >= 400;
+ case EbtUint:
+ return true;
+ default:
+ return false;
+ }
+ case EbtInt:
+ switch (from) {
+ case EbtInt:
+ return true;
+ default:
+ return false;
+ }
+ case EbtUint64:
+ switch (from) {
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ return true;
+ default:
+ return false;
+ }
+ case EbtInt64:
+ switch (from) {
+ case EbtInt:
+ case EbtInt64:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+//
+// Safe way to combine two nodes into an aggregate. Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right)
+{
+ if (left == 0 && right == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = 0;
+ if (left)
+ aggNode = left->getAsAggregate();
+ if (! aggNode || aggNode->getOp() != EOpNull) {
+ aggNode = new TIntermAggregate;
+ if (left)
+ aggNode->getSequence().push_back(left);
+ }
+
+ if (right)
+ aggNode->getSequence().push_back(right);
+
+ return aggNode;
+}
+
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc)
+{
+ TIntermAggregate* aggNode = growAggregate(left, right);
+ if (aggNode)
+ aggNode->setLoc(loc);
+
+ return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless 0 was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->getSequence().push_back(node);
+ aggNode->setLoc(node->getLoc());
+
+ return aggNode;
+}
+
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& loc)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->getSequence().push_back(node);
+ aggNode->setLoc(loc);
+
+ return aggNode;
+}
+
+//
+// For "if" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc)
+{
+ //
+ // Don't prune the false path for compile-time constants; it's needed
+ // for static access analysis.
+ //
+
+ TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+ node->setLoc(loc);
+
+ return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
+{
+ // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators
+ // ... are not included in the operators that can create a constant expression.
+ //
+ //if (left->getType().getQualifier().storage == EvqConst &&
+ // right->getType().getQualifier().storage == EvqConst) {
+
+ // return right;
+ //}
+
+ TIntermTyped *commaAggregate = growAggregate(left, right, loc);
+ commaAggregate->getAsAggregate()->setOperator(EOpComma);
+ commaAggregate->setType(right->getType());
+ commaAggregate->getWritableType().getQualifier().makeTemporary();
+
+ return commaAggregate;
+}
+
+TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, const TString* name, const TSourceLoc& loc)
+{
+ TIntermMethod* method = new TIntermMethod(object, type, *name);
+ method->setLoc(loc);
+
+ return method;
+}
+
+//
+// For "?:" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc)
+{
+ //
+ // Get compatible types.
+ //
+ TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
+ if (child)
+ falseBlock = child;
+ else {
+ child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
+ if (child)
+ trueBlock = child;
+ else
+ return 0;
+ }
+
+ // After conversion, types have to match.
+ if (falseBlock->getType() != trueBlock->getType())
+ return 0;
+
+ //
+ // See if all the operands are constant, then fold it otherwise not.
+ //
+
+ if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
+ if (cond->getAsConstantUnion()->getConstArray()[0].getBConst())
+ return trueBlock;
+ else
+ return falseBlock;
+ }
+
+ //
+ // Make a selection node.
+ //
+ TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+ node->getQualifier().makeTemporary();
+ node->setLoc(loc);
+ node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision);
+
+ return node;
+}
+
+//
+// Constant terminal nodes. Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const
+{
+ TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
+ node->getQualifier().storage = EvqConst;
+ node->setLoc(loc);
+ if (literal)
+ node->setLiteral();
+
+ return node;
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(int i, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setIConst(i);
+
+ return addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned int u, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setUConst(u);
+
+ return addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(long long i64, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setI64Const(i64);
+
+ return addConstantUnion(unionArray, TType(EbtInt64, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setU64Const(u64);
+
+ return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const
+{
+ TConstUnionArray unionArray(1);
+ unionArray[0].setBConst(b);
+
+ return addConstantUnion(unionArray, TType(EbtBool, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const
+{
+ assert(baseType == EbtFloat || baseType == EbtDouble);
+
+ TConstUnionArray unionArray(1);
+ unionArray[0].setDConst(d);
+
+ return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal);
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& loc)
+{
+ TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+ node->setLoc(loc);
+ TIntermConstantUnion* constIntNode;
+ TIntermSequence &sequenceVector = node->getSequence();
+
+ for (int i = 0; i < fields.num; i++) {
+ constIntNode = addConstantUnion(fields.offsets[i], loc);
+ sequenceVector.push_back(constIntNode);
+ }
+
+ return node;
+}
+
+//
+// Follow the left branches down to the root of an l-value
+// expression (just "." and []).
+//
+// Return the base of the l-value (where following indexing quits working).
+// Return nullptr if a chain following dereferences cannot be followed.
+//
+// 'swizzleOkay' says whether or not it is okay to consider a swizzle
+// a valid part of the dereference chain.
+//
+const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay)
+{
+ do {
+ const TIntermBinary* binary = node->getAsBinaryNode();
+ if (binary == nullptr)
+ return node;
+ TOperator op = binary->getOp();
+ if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle)
+ return nullptr;
+ if (! swizzleOkay) {
+ if (op == EOpVectorSwizzle)
+ return nullptr;
+ if ((op == EOpIndexDirect || op == EOpIndexIndirect) &&
+ (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) &&
+ ! binary->getLeft()->getType().isArray())
+ return nullptr;
+ }
+ node = node->getAsBinaryNode()->getLeft();
+ } while (true);
+}
+
+//
+// Create while and do-while loop nodes.
+//
+TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
+{
+ TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
+ node->setLoc(loc);
+
+ return node;
+}
+
+//
+// Create a for-loop sequence.
+//
+TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
+{
+ TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
+ node->setLoc(loc);
+
+ // make a sequence of the initializer and statement
+ TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
+ loopSequence = growAggregate(loopSequence, node);
+ loopSequence->setOperator(EOpSequence);
+
+ return loopSequence;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& loc)
+{
+ return addBranch(branchOp, 0, loc);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& loc)
+{
+ TIntermBranch* node = new TIntermBranch(branchOp, expression);
+ node->setLoc(loc);
+
+ return node;
+}
+
+//
+// This is to be executed after the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
+{
+ if (root == 0)
+ return true;
+
+ // Finish off the top-level sequence
+ TIntermAggregate* aggRoot = root->getAsAggregate();
+ if (aggRoot && aggRoot->getOp() == EOpNull)
+ aggRoot->setOperator(EOpSequence);
+
+ // Propagate 'noContraction' label in backward from 'precise' variables.
+ glslang::PropagateNoContraction(*this);
+
+ return true;
+}
+
+void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable)
+{
+ // Add top-level nodes for declarations that must be checked cross
+ // compilation unit by a linker, yet might not have been referenced
+ // by the AST.
+ //
+ // Almost entirely, translation of symbols is driven by what's present
+ // in the AST traversal, not by translating the symbol table.
+ //
+ // However, there are some special cases:
+ // - From the specification: "Special built-in inputs gl_VertexID and
+ // gl_InstanceID are also considered active vertex attributes."
+ // - Linker-based type mismatch error reporting needs to see all
+ // uniforms/ins/outs variables and blocks.
+ // - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active.
+ //
+
+ //if (ftransformUsed) {
+ // TODO: 1.1 lowering functionality: track ftransform() usage
+ // addSymbolLinkageNode(root, symbolTable, "gl_Vertex");
+ // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix");
+ //}
+
+ if (language == EShLangVertex) {
+ // the names won't be found in the symbol table unless the versions are right,
+ // so version logic does not need to be repeated here
+ addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID");
+ addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID");
+ }
+
+ // Add a child to the root node for the linker objects
+ linkage->setOperator(EOpLinkerObjects);
+ treeRoot = growAggregate(treeRoot, linkage);
+}
+
+//
+// Add the given name or symbol to the list of nodes at the end of the tree used
+// for link-time checking and external linkage.
+//
+
+void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name)
+{
+ TSymbol* symbol = symbolTable.find(name);
+ if (symbol)
+ addSymbolLinkageNode(linkage, *symbol->getAsVariable());
+}
+
+void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol& symbol)
+{
+ const TVariable* variable = symbol.getAsVariable();
+ if (! variable) {
+ // This must be a member of an anonymous block, and we need to add the whole block
+ const TAnonMember* anon = symbol.getAsAnonMember();
+ variable = &anon->getAnonContainer();
+ }
+ TIntermSymbol* node = addSymbol(*variable);
+ linkage = growAggregate(linkage, node);
+}
+
+//
+// Add a caller->callee relationship to the call graph.
+// Assumes the strings are unique per signature.
+//
+void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& caller, const TString& callee)
+{
+ // Duplicates are okay, but faster to not keep them, and they come grouped by caller,
+ // as long as new ones are push on the same end we check on for duplicates
+ for (TGraph::const_iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (call->caller != caller)
+ break;
+ if (call->callee == callee)
+ return;
+ }
+
+ callGraph.push_front(TCall(caller, callee));
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::removeTree()
+{
+ if (treeRoot)
+ RemoveAllTreeNodes(treeRoot);
+}
+
+//
+// Implement the part of KHR_vulkan_glsl that lists the set of operations
+// that can result in a specialization constant operation.
+//
+// "5.x Specialization Constant Operations"
+//
+// Only some operations discussed in this section may be applied to a
+// specialization constant and still yield a result that is as
+// specialization constant. The operations allowed are listed below.
+// When a specialization constant is operated on with one of these
+// operators and with another constant or specialization constant, the
+// result is implicitly a specialization constant.
+//
+// - int(), uint(), and bool() constructors for type conversions
+// from any of the following types to any of the following types:
+// * int
+// * uint
+// * bool
+// - vector versions of the above conversion constructors
+// - allowed implicit conversions of the above
+// - swizzles (e.g., foo.yx)
+// - The following when applied to integer or unsigned integer types:
+// * unary negative ( - )
+// * binary operations ( + , - , * , / , % )
+// * shift ( <<, >> )
+// * bitwise operations ( & , | , ^ )
+// - The following when applied to integer or unsigned integer scalar types:
+// * comparison ( == , != , > , >= , < , <= )
+// - The following when applied to the Boolean scalar type:
+// * not ( ! )
+// * logical operations ( && , || , ^^ )
+// * comparison ( == , != )"
+//
+// This function just handles binary and unary nodes. Construction
+// rules are handled in construction paths that are not covered by the unary
+// and binary paths, while required conversions will still show up here
+// as unary converters in the from a construction operator.
+//
+bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
+{
+ // The operations resulting in floating point are quite limited
+ // (However, some floating-point operations result in bool, like ">",
+ // so are handled later.)
+ if (node.getType().isFloatingDomain()) {
+ switch (node.getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // Check for floating-point arguments
+ if (const TIntermBinary* bin = node.getAsBinaryNode())
+ if (bin->getLeft() ->getType().isFloatingDomain() ||
+ bin->getRight()->getType().isFloatingDomain())
+ return false;
+
+ // So, for now, we can assume everything left is non-floating-point...
+
+ // Now check for integer/bool-based operations
+ switch (node.getOp()) {
+
+ // dereference/swizzle
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+
+ // conversion constructors
+ case EOpConvIntToBool:
+ case EOpConvUintToBool:
+ case EOpConvUintToInt:
+ case EOpConvBoolToInt:
+ case EOpConvIntToUint:
+ case EOpConvBoolToUint:
+
+ // unary operations
+ case EOpNegative:
+ case EOpLogicalNot:
+ case EOpBitwiseNot:
+
+ // binary operations
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpDiv:
+ case EOpMod:
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ return true;
+ default:
+ return false;
+ }
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+// Returns true if state is modified.
+//
+bool TIntermOperator::modifiesState() const
+{
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+ return op > EOpConstructGuardStart && op < EOpConstructGuardEnd;
+}
+
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote()
+{
+ switch (op) {
+ case EOpLogicalNot:
+ if (operand->getBasicType() != EbtBool)
+
+ return false;
+ break;
+ case EOpBitwiseNot:
+ if (operand->getBasicType() != EbtInt &&
+ operand->getBasicType() != EbtUint &&
+ operand->getBasicType() != EbtInt64 &&
+ operand->getBasicType() != EbtUint64)
+
+ return false;
+ break;
+ case EOpNegative:
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ if (operand->getBasicType() != EbtInt &&
+ operand->getBasicType() != EbtUint &&
+ operand->getBasicType() != EbtInt64 &&
+ operand->getBasicType() != EbtUint64 &&
+ operand->getBasicType() != EbtFloat &&
+ operand->getBasicType() != EbtDouble)
+
+ return false;
+ break;
+
+ default:
+ if (operand->getBasicType() != EbtFloat)
+
+ return false;
+ }
+
+ setType(operand->getType());
+ getWritableType().getQualifier().makeTemporary();
+
+ return true;
+}
+
+void TIntermUnary::updatePrecision()
+{
+ if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat) {
+ if (operand->getQualifier().precision > getQualifier().precision)
+ getQualifier().precision = operand->getQualifier().precision;
+ }
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote()
+{
+ // Arrays and structures have to be exact matches.
+ if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct)
+ && left->getType() != right->getType())
+ return false;
+
+ // Base assumption: just make the type the same as the left
+ // operand. Only deviations from this will be coded.
+ setType(left->getType());
+ type.getQualifier().clear();
+
+ // Composite and opaque types don't having pending operator changes, e.g.,
+ // array, structure, and samplers. Just establish final type and correctness.
+ if (left->isArray() || left->getBasicType() == EbtStruct || left->getBasicType() == EbtSampler) {
+ switch (op) {
+ case EOpEqual:
+ case EOpNotEqual:
+ if (left->getBasicType() == EbtSampler) {
+ // can't compare samplers
+ return false;
+ } else {
+ // Promote to conditional
+ setType(TType(EbtBool));
+ }
+
+ return true;
+
+ case EOpAssign:
+ // Keep type from above
+
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ //
+ // We now have only scalars, vectors, and matrices to worry about.
+ //
+
+ // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that)
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ // Relational comparisons need matching numeric types and will promote to scalar Boolean.
+ if (left->getBasicType() == EbtBool || left->getType().isVector() || left->getType().isMatrix())
+ return false;
+
+ // Fall through
+
+ case EOpEqual:
+ case EOpNotEqual:
+ // All the above comparisons result in a bool (but not the vector compares)
+ setType(TType(EbtBool));
+ break;
+
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ // logical ops operate only on scalar Booleans and will promote to scalar Boolean.
+ if (left->getBasicType() != EbtBool || left->isVector() || left->isMatrix())
+ return false;
+
+ setType(TType(EbtBool));
+ break;
+
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpRightShiftAssign:
+ case EOpLeftShiftAssign:
+
+ case EOpMod:
+ case EOpModAssign:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ // Check for integer-only operands.
+ if ((left->getBasicType() != EbtInt && left->getBasicType() != EbtUint &&
+ left->getBasicType() != EbtInt64 && left->getBasicType() != EbtUint64) ||
+ (right->getBasicType() != EbtInt && right->getBasicType() != EbtUint &&
+ right->getBasicType() != EbtInt64 && right->getBasicType() != EbtUint64))
+ return false;
+ if (left->isMatrix() || right->isMatrix())
+ return false;
+
+ break;
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpDivAssign:
+ // check for non-Boolean operands
+ if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)
+ return false;
+
+ default:
+ break;
+ }
+
+ // Compare left and right, and finish with the cases where the operand types must match
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+
+ case EOpEqual:
+ case EOpNotEqual:
+
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ return left->getType() == right->getType();
+
+ // no shifts: they can mix types (scalar int can shift a vector uint, etc.)
+
+ case EOpMod:
+ case EOpModAssign:
+
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ // Quick out in case the types do match
+ if (left->getType() == right->getType())
+ return true;
+
+ // Fall through
+
+ case EOpMul:
+ case EOpMulAssign:
+ // At least the basic type has to match
+ if (left->getBasicType() != right->getBasicType())
+ return false;
+
+ default:
+ break;
+ }
+
+ // Finish handling the case, for all ops, where both operands are scalars.
+ if (left->isScalar() && right->isScalar())
+ return true;
+
+ // Finish handling the case, for all ops, where there are two vectors of different sizes
+ if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
+ return false;
+
+ //
+ // We now have a mix of scalars, vectors, or matrices, for non-relational operations.
+ //
+
+ // Can these two operands be combined, what is the resulting type?
+ TBasicType basicType = left->getBasicType();
+ switch (op) {
+ case EOpMul:
+ if (!left->isMatrix() && right->isMatrix()) {
+ if (left->isVector()) {
+ if (left->getVectorSize() != right->getMatrixRows())
+ return false;
+ op = EOpVectorTimesMatrix;
+ setType(TType(basicType, EvqTemporary, right->getMatrixCols()));
+ } else {
+ op = EOpMatrixTimesScalar;
+ setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows()));
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ if (left->getMatrixCols() != right->getVectorSize())
+ return false;
+ op = EOpMatrixTimesVector;
+ setType(TType(basicType, EvqTemporary, left->getMatrixRows()));
+ } else {
+ op = EOpMatrixTimesScalar;
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ if (left->getMatrixCols() != right->getMatrixRows())
+ return false;
+ op = EOpMatrixTimesMatrix;
+ setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows()));
+ } else if (! left->isMatrix() && ! right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ ; // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ op = EOpVectorTimesScalar;
+ if (right->isVector())
+ setType(TType(basicType, EvqTemporary, right->getVectorSize()));
+ }
+ } else {
+ return false;
+ }
+ break;
+ case EOpMulAssign:
+ if (! left->isMatrix() && right->isMatrix()) {
+ if (left->isVector()) {
+ if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols())
+ return false;
+ op = EOpVectorTimesMatrixAssign;
+ } else {
+ return false;
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ return false;
+ } else {
+ op = EOpMatrixTimesScalarAssign;
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ if (left->getMatrixCols() != left->getMatrixRows() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows())
+ return false;
+ op = EOpMatrixTimesMatrixAssign;
+ } else if (!left->isMatrix() && !right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ if (! left->isVector())
+ return false;
+ op = EOpVectorTimesScalarAssign;
+ }
+ } else {
+ return false;
+ }
+ break;
+
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpRightShiftAssign:
+ case EOpLeftShiftAssign:
+ if (right->isVector() && (! left->isVector() || right->getVectorSize() != left->getVectorSize()))
+ return false;
+ break;
+
+ case EOpAssign:
+ if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows())
+ return false;
+ // fall through
+
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMod:
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ if ((left->isMatrix() && right->isVector()) ||
+ (left->isVector() && right->isMatrix()) ||
+ left->getBasicType() != right->getBasicType())
+ return false;
+ if (left->isMatrix() && right->isMatrix() && (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()))
+ return false;
+ if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
+ return false;
+ if (right->isVector() || right->isMatrix()) {
+ type.shallowCopy(right->getType());
+ type.getQualifier().makeTemporary();
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ //
+ // One more check for assignment.
+ //
+ switch (op) {
+ // The resulting type has to match the left operand.
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ if (getType() != left->getType())
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void TIntermBinary::updatePrecision()
+{
+ if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat) {
+ getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
+ if (getQualifier().precision != EpqNone) {
+ left->propagatePrecision(getQualifier().precision);
+ right->propagatePrecision(getQualifier().precision);
+ }
+ }
+}
+
+void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
+{
+ if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat))
+ return;
+
+ getQualifier().precision = newPrecision;
+
+ TIntermBinary* binaryNode = getAsBinaryNode();
+ if (binaryNode) {
+ binaryNode->getLeft()->propagatePrecision(newPrecision);
+ binaryNode->getRight()->propagatePrecision(newPrecision);
+
+ return;
+ }
+
+ TIntermUnary* unaryNode = getAsUnaryNode();
+ if (unaryNode) {
+ unaryNode->getOperand()->propagatePrecision(newPrecision);
+
+ return;
+ }
+
+ TIntermAggregate* aggregateNode = getAsAggregate();
+ if (aggregateNode) {
+ TIntermSequence operands = aggregateNode->getSequence();
+ for (unsigned int i = 0; i < operands.size(); ++i) {
+ TIntermTyped* typedNode = operands[i]->getAsTyped();
+ if (! typedNode)
+ break;
+ typedNode->propagatePrecision(newPrecision);
+ }
+
+ return;
+ }
+
+ TIntermSelection* selectionNode = getAsSelectionNode();
+ if (selectionNode) {
+ TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped();
+ if (typedNode) {
+ typedNode->propagatePrecision(newPrecision);
+ typedNode = selectionNode->getFalseBlock()->getAsTyped();
+ if (typedNode)
+ typedNode->propagatePrecision(newPrecision);
+ }
+
+ return;
+ }
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const
+{
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ int size = node->getType().computeNumComponents();
+
+ TConstUnionArray leftUnionArray(size);
+
+ for (int i=0; i < size; i++) {
+ switch (promoteTo) {
+ case EbtFloat:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst()));
+ break;
+ case EbtUint:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst()));
+ break;
+ case EbtInt64:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const()));
+ break;
+ case EbtUint64:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const()));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst()));
+ break;
+ case EbtFloat:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ case EbtDouble:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getDConst()));
+ break;
+ default:
+ return node;
+ }
+ break;
+ case EbtDouble:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst()));
+ break;
+ case EbtUint:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst()));
+ break;
+ case EbtInt64:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const()));
+ break;
+ case EbtUint64:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const()));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst()));
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ default:
+ return node;
+ }
+ break;
+ case EbtInt:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ case EbtUint:
+ leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getUConst()));
+ break;
+ case EbtInt64:
+ leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getI64Const()));
+ break;
+ case EbtUint64:
+ leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getU64Const()));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getDConst()));
+ break;
+ default:
+ return node;
+ }
+ break;
+ case EbtUint:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getIConst()));
+ break;
+ case EbtUint:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ case EbtInt64:
+ leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getI64Const()));
+ break;
+ case EbtUint64:
+ leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getU64Const()));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getBConst()));
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getDConst()));
+ break;
+ default:
+ return node;
+ }
+ break;
+ case EbtBool:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
+ break;
+ case EbtUint:
+ leftUnionArray[i].setBConst(rightUnionArray[i].getUConst() != 0);
+ break;
+ case EbtInt64:
+ leftUnionArray[i].setBConst(rightUnionArray[i].getI64Const() != 0);
+ break;
+ case EbtUint64:
+ leftUnionArray[i].setBConst(rightUnionArray[i].getU64Const() != 0);
+ break;
+ case EbtBool:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ leftUnionArray[i].setBConst(rightUnionArray[i].getDConst() != 0.0);
+ break;
+ default:
+ return node;
+ }
+ break;
+ case EbtInt64:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getIConst()));
+ break;
+ case EbtUint:
+ leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getUConst()));
+ break;
+ case EbtInt64:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ case EbtUint64:
+ leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getU64Const()));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getBConst()));
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getDConst()));
+ break;
+ default:
+ return node;
+ }
+ break;
+ case EbtUint64:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getIConst()));
+ break;
+ case EbtUint:
+ leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getUConst()));
+ break;
+ case EbtInt64:
+ leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getI64Const()));
+ break;
+ case EbtUint64:
+ leftUnionArray[i] = rightUnionArray[i];
+ break;
+ case EbtBool:
+ leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getBConst()));
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getDConst()));
+ break;
+ default:
+ return node;
+ }
+ break;
+ default:
+ return node;
+ }
+ }
+
+ const TType& t = node->getType();
+
+ return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()),
+ node->getLoc());
+}
+
+void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
+{
+ assert(!pragmaTable);
+ pragmaTable = new TPragmaTable();
+ *pragmaTable = pTable;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp
new file mode 100644
index 00000000000..eb9100bd05c
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp
@@ -0,0 +1,6164 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2015 LunarG, Inc.
+//Copyright (C) 2015-2016 Google, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "ParseHelper.h"
+#include "Scan.h"
+
+#include "../OSDependent/osinclude.h"
+#include <stdarg.h>
+#include <algorithm>
+
+#include "preprocessor/PpContext.h"
+
+extern int yyparse(glslang::TParseContext*);
+
+namespace glslang {
+
+TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
+ int version, EProfile profile, int spv, int vulkan, EShLanguage language,
+ TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) :
+ TParseContextBase(symbolTable, interm, version, profile, spv, vulkan, language, infoSink, forwardCompatible, messages),
+ contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0),
+ inMain(false), postMainReturn(false), currentFunctionType(nullptr), blockName(nullptr),
+ limits(resources.limits), parsingBuiltins(parsingBuiltins),
+ afterEOF(false),
+ atomicUintOffsets(nullptr), anyIndexLimits(false)
+{
+ // ensure we always have a linkage node, even if empty, to simplify tree topology algorithms
+ linkage = new TIntermAggregate;
+
+ // 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 precision defaults for those that have them
+ if (profile == EEsProfile) {
+ TSampler sampler;
+ sampler.set(EbtFloat, Esd2D);
+ defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
+ sampler.set(EbtFloat, EsdCube);
+ defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
+ sampler.set(EbtFloat, Esd2D);
+ sampler.external = true;
+ defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow;
+
+ // If we are parsing built-in computational variables/functions, it is meaningful to record
+ // whether the built-in has no precision qualifier, as that ambiguity
+ // is used to resolve the precision from the supplied arguments/operands instead.
+ // So, we don't actually want to replace EpqNone with a default precision for built-ins.
+ if (! parsingBuiltins) {
+ switch (language) {
+ case EShLangFragment:
+ defaultPrecision[EbtInt] = EpqMedium;
+ defaultPrecision[EbtUint] = EpqMedium;
+ break;
+ default:
+ defaultPrecision[EbtInt] = EpqHigh;
+ defaultPrecision[EbtUint] = EpqHigh;
+ defaultPrecision[EbtFloat] = EpqHigh;
+ break;
+ }
+ }
+
+ defaultPrecision[EbtSampler] = EpqLow;
+ defaultPrecision[EbtAtomicUint] = EpqHigh;
+ }
+
+ globalUniformDefaults.clear();
+ globalUniformDefaults.layoutMatrix = ElmColumnMajor;
+ globalUniformDefaults.layoutPacking = vulkan > 0 ? ElpStd140 : ElpShared;
+
+ globalBufferDefaults.clear();
+ globalBufferDefaults.layoutMatrix = ElmColumnMajor;
+ globalBufferDefaults.layoutPacking = vulkan > 0 ? ElpStd430 : ElpShared;
+
+ globalInputDefaults.clear();
+ globalOutputDefaults.clear();
+
+ // "Shaders in the transform
+ // feedback capturing mode have an initial global default of
+ // layout(xfb_buffer = 0) out;"
+ if (language == EShLangVertex ||
+ language == EShLangTessControl ||
+ language == EShLangTessEvaluation ||
+ language == EShLangGeometry)
+ globalOutputDefaults.layoutXfbBuffer = 0;
+
+ if (language == EShLangGeometry)
+ globalOutputDefaults.layoutStream = 0;
+}
+
+TParseContext::~TParseContext()
+{
+ delete [] atomicUintOffsets;
+}
+
+void TParseContext::setLimits(const TBuiltInResource& r)
+{
+ resources = r;
+
+ anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing ||
+ ! limits.generalConstantMatrixVectorIndexing ||
+ ! limits.generalSamplerIndexing ||
+ ! limits.generalUniformIndexing ||
+ ! limits.generalVariableIndexing ||
+ ! limits.generalVaryingIndexing;
+
+ intermediate.setLimits(resources);
+
+ // "Each binding point tracks its own current default offset for
+ // inheritance of subsequent variables using the same binding. The initial state of compilation is that all
+ // binding points have an offset of 0."
+ atomicUintOffsets = new int[resources.maxAtomicCounterBindings];
+ for (int b = 0; b < resources.maxAtomicCounterBindings; ++b)
+ atomicUintOffsets[b] = 0;
+}
+
+//
+// Parse an array of strings using yyparse, going through the
+// preprocessor to tokenize the shader strings, then through
+// the GLSL scanner.
+//
+// Returns true for successful acceptance of the shader, false if any errors.
+//
+bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError)
+{
+ currentScanner = &input;
+ ppContext.setInput(input, versionWillBeError);
+ yyparse(this);
+ if (! parsingBuiltins)
+ finalErrorCheck();
+
+ return numErrors == 0;
+}
+
+// This is called from bison when it has a parse (syntax) error
+void TParseContext::parserError(const char* s)
+{
+ if (afterEOF) {
+ if (tokensBeforeEOF == 1)
+ error(getCurrentLoc(), "", "premature end of input", s, "");
+ } else
+ error(getCurrentLoc(), "", "", s, "");
+}
+
+void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
+{
+ if (pragmaCallback)
+ pragmaCallback(loc.line, tokens);
+
+ if (tokens.size() == 0)
+ return;
+
+ if (tokens[0].compare("optimize") == 0) {
+ if (tokens.size() != 4) {
+ error(loc, "optimize pragma syntax is incorrect", "#pragma", "");
+ return;
+ }
+
+ if (tokens[1].compare("(") != 0) {
+ error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", "");
+ return;
+ }
+
+ if (tokens[2].compare("on") == 0)
+ contextPragma.optimize = true;
+ else if (tokens[2].compare("off") == 0)
+ contextPragma.optimize = false;
+ else {
+ error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
+ return;
+ }
+
+ if (tokens[3].compare(")") != 0) {
+ error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", "");
+ return;
+ }
+ } else if (tokens[0].compare("debug") == 0) {
+ if (tokens.size() != 4) {
+ error(loc, "debug pragma syntax is incorrect", "#pragma", "");
+ return;
+ }
+
+ if (tokens[1].compare("(") != 0) {
+ error(loc, "\"(\" expected after 'debug' keyword", "#pragma", "");
+ return;
+ }
+
+ if (tokens[2].compare("on") == 0)
+ contextPragma.debug = true;
+ else if (tokens[2].compare("off") == 0)
+ contextPragma.debug = false;
+ else {
+ error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
+ return;
+ }
+
+ if (tokens[3].compare(")") != 0) {
+ error(loc, "\")\" expected to end 'debug' pragma", "#pragma", "");
+ return;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector or scalar
+//
+// Returns true if there is no error.
+//
+bool TParseContext::parseVectorFields(const TSourceLoc& loc, const TString& compString, int vecSize, TVectorFields& fields)
+{
+ fields.num = (int) compString.size();
+ if (fields.num > 4) {
+ error(loc, "illegal vector field selection", compString.c_str(), "");
+ return false;
+ }
+
+ enum {
+ exyzw,
+ ergba,
+ estpq,
+ } fieldSet[4];
+
+ for (int i = 0; i < fields.num; ++i) {
+ switch (compString[i]) {
+ case 'x':
+ fields.offsets[i] = 0;
+ fieldSet[i] = exyzw;
+ break;
+ case 'r':
+ fields.offsets[i] = 0;
+ fieldSet[i] = ergba;
+ break;
+ case 's':
+ fields.offsets[i] = 0;
+ fieldSet[i] = estpq;
+ break;
+ case 'y':
+ fields.offsets[i] = 1;
+ fieldSet[i] = exyzw;
+ break;
+ case 'g':
+ fields.offsets[i] = 1;
+ fieldSet[i] = ergba;
+ break;
+ case 't':
+ fields.offsets[i] = 1;
+ fieldSet[i] = estpq;
+ break;
+ case 'z':
+ fields.offsets[i] = 2;
+ fieldSet[i] = exyzw;
+ break;
+ case 'b':
+ fields.offsets[i] = 2;
+ fieldSet[i] = ergba;
+ break;
+ case 'p':
+ fields.offsets[i] = 2;
+ fieldSet[i] = estpq;
+ break;
+
+ case 'w':
+ fields.offsets[i] = 3;
+ fieldSet[i] = exyzw;
+ break;
+ case 'a':
+ fields.offsets[i] = 3;
+ fieldSet[i] = ergba;
+ break;
+ case 'q':
+ fields.offsets[i] = 3;
+ fieldSet[i] = estpq;
+ break;
+ default:
+ error(loc, "illegal vector field selection", compString.c_str(), "");
+ return false;
+ }
+ }
+
+ for (int i = 0; i < fields.num; ++i) {
+ if (fields.offsets[i] >= vecSize) {
+ error(loc, "vector field selection out of range", compString.c_str(), "");
+ return false;
+ }
+
+ if (i > 0) {
+ if (fieldSet[i] != fieldSet[i-1]) {
+ error(loc, "illegal - vector component fields not from the same set", compString.c_str(), "");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Used to output syntax, parsing, and semantic errors.
+//
+
+void TParseContext::outputMessage(const TSourceLoc& loc, const char* szReason,
+ const char* szToken,
+ const char* szExtraInfoFormat,
+ TPrefixType prefix, va_list args)
+{
+ const int maxSize = MaxTokenLength + 200;
+ char szExtraInfo[maxSize];
+
+ safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
+
+ infoSink.info.prefix(prefix);
+ infoSink.info.location(loc);
+ infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
+
+ if (prefix == EPrefixError) {
+ ++numErrors;
+ }
+}
+
+void C_DECL TParseContext::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ if (messages & EShMsgOnlyPreprocessor)
+ return;
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
+ va_end(args);
+}
+
+void C_DECL TParseContext::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ if (suppressWarnings())
+ return;
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
+ va_end(args);
+}
+
+void C_DECL TParseContext::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
+ va_end(args);
+}
+
+void C_DECL TParseContext::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...)
+{
+ va_list args;
+ va_start(args, szExtraInfoFormat);
+ outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
+ va_end(args);
+}
+
+//
+// Handle seeing a variable identifier in the grammar.
+//
+TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string)
+{
+ TIntermTyped* node = nullptr;
+
+ // Error check for requiring specific extensions present.
+ if (symbol && symbol->getNumExtensions())
+ requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str());
+
+ if (symbol && symbol->isReadOnly()) {
+ // All shared things containing an implicitly sized array must be copied up
+ // on first use, so that all future references will share its array structure,
+ // so that editing the implicit size will effect all nodes consuming it,
+ // and so that editing the implicit size won't change the shared one.
+ //
+ // If this is a variable or a block, check it and all it contains, but if this
+ // is a member of an anonymous block, check the whole block, as the whole block
+ // will need to be copied up if it contains an implicitly-sized array.
+ if (symbol->getType().containsImplicitlySizedArray() || (symbol->getAsAnonMember() && symbol->getAsAnonMember()->getAnonContainer().getType().containsImplicitlySizedArray()))
+ makeEditable(symbol);
+ }
+
+ const TVariable* variable;
+ const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr;
+ if (anon) {
+ // It was a member of an anonymous container.
+
+ // The "getNumExtensions()" mechanism above doesn't yet work for block members
+ blockMemberExtensionCheck(loc, nullptr, *string);
+
+ // Create a subtree for its dereference.
+ variable = anon->getAnonContainer().getAsVariable();
+ TIntermTyped* container = intermediate.addSymbol(*variable, loc);
+ TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc);
+ node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc);
+
+ node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);
+ if (node->getType().hiddenMember())
+ error(loc, "member of nameless block was not redeclared", string->c_str(), "");
+ } else {
+ // Not a member of an anonymous container.
+
+ // The symbol table search was done in the lexical phase.
+ // See if it was a variable.
+ variable = symbol ? symbol->getAsVariable() : nullptr;
+ if (variable) {
+ if ((variable->getType().getBasicType() == EbtBlock ||
+ variable->getType().getBasicType() == EbtStruct) && variable->getType().getStruct() == nullptr) {
+ error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), "");
+ variable = nullptr;
+ }
+ } else {
+ if (symbol)
+ error(loc, "variable name expected", string->c_str(), "");
+ }
+
+ // Recovery, if it wasn't found or was not a variable.
+ if (! variable)
+ variable = new TVariable(string, TType(EbtVoid));
+
+ if (variable->getType().getQualifier().isFrontEndConstant())
+ node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc);
+ else
+ node = intermediate.addSymbol(*variable, loc);
+ }
+
+ if (variable->getType().getQualifier().isIo())
+ intermediate.addIoAccessed(*string);
+
+ return node;
+}
+
+//
+// Handle seeing a base[index] dereference in the grammar.
+//
+TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index)
+{
+ TIntermTyped* result = nullptr;
+
+ int indexValue = 0;
+ if (index->getQualifier().isFrontEndConstant()) {
+ indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
+ checkIndex(loc, base->getType(), indexValue);
+ }
+
+ variableCheck(base);
+ if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) {
+ if (base->getAsSymbolNode())
+ error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
+ else
+ error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+ } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant())
+ return intermediate.foldDereference(base, indexValue, loc);
+ else {
+ // at least one of base and index is variable...
+
+ if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
+ handleIoResizeArrayAccess(loc, base);
+
+ if (index->getQualifier().isFrontEndConstant()) {
+ if (base->getType().isImplicitlySizedArray())
+ updateImplicitArraySize(loc, base, indexValue);
+ result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
+ } else {
+ if (base->getType().isImplicitlySizedArray()) {
+ if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
+ error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
+ else
+ error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
+ }
+ if (base->getBasicType() == EbtBlock) {
+ if (base->getQualifier().storage == EvqBuffer)
+ requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array");
+ else if (base->getQualifier().storage == EvqUniform)
+ profileRequires(base->getLoc(), EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "variable indexing uniform block array");
+ else {
+ // input/output blocks either don't exist or can be variable indexed
+ }
+ } else if (language == EShLangFragment && base->getQualifier().isPipeOutput())
+ requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader ouput array");
+ else if (base->getBasicType() == EbtSampler && version >= 130) {
+ const char* explanation = "variable indexing sampler array";
+ requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation);
+ profileRequires(base->getLoc(), EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation);
+ profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation);
+ }
+
+ result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
+ }
+ }
+
+ if (result == nullptr) {
+ // Insert dummy error-recovery result
+ result = intermediate.addConstantUnion(0.0, EbtFloat, loc);
+ } else {
+ // Insert valid dereferenced result
+ TType newType(base->getType(), 0); // dereferenced type
+ if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) {
+ newType.getQualifier().storage = EvqConst;
+ // If base or index is a specialization constant, the result should also be a specialization constant.
+ if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) {
+ newType.getQualifier().makeSpecConstant();
+ }
+ } else {
+ newType.getQualifier().makePartialTemporary();
+ }
+ result->setType(newType);
+
+ if (anyIndexLimits)
+ handleIndexLimits(loc, base, index);
+ }
+
+ return result;
+}
+
+void TParseContext::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
+{
+ if (index < 0) {
+ error(loc, "", "[", "index out of range '%d'", index);
+ index = 0;
+ } else if (type.isArray()) {
+ if (type.isExplicitlySizedArray() && index >= type.getOuterArraySize()) {
+ error(loc, "", "[", "array index out of range '%d'", index);
+ index = type.getOuterArraySize() - 1;
+ }
+ } else if (type.isVector()) {
+ if (index >= type.getVectorSize()) {
+ error(loc, "", "[", "vector index out of range '%d'", index);
+ index = type.getVectorSize() - 1;
+ }
+ } else if (type.isMatrix()) {
+ if (index >= type.getMatrixCols()) {
+ error(loc, "", "[", "matrix index out of range '%d'", index);
+ index = type.getMatrixCols() - 1;
+ }
+ }
+}
+
+// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
+void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index)
+{
+ if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) ||
+ (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) ||
+ (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) ||
+ (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) ||
+ (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() &&
+ ! base->getType().getQualifier().isPipeInput() &&
+ ! base->getType().getQualifier().isPipeOutput() &&
+ ! base->getType().getQualifier().isConstant()) ||
+ (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() ||
+ base->getType().getQualifier().isPipeOutput()))) {
+ // it's too early to know what the inductive variables are, save it for post processing
+ needsIndexLimitationChecking.push_back(index);
+ }
+}
+
+// Make a shared symbol have a non-shared version that can be edited by the current
+// compile, such that editing its type will not change the shared version and will
+// effect all nodes sharing it.
+void TParseContext::makeEditable(TSymbol*& symbol)
+{
+ // copyUp() does a deep copy of the type.
+ symbol = symbolTable.copyUp(symbol);
+
+ // Also, see if it's tied to IO resizing
+ if (isIoResizeArray(symbol->getType()))
+ ioArraySymbolResizeList.push_back(symbol);
+
+ // Also, save it in the AST for linker use.
+ intermediate.addSymbolLinkageNode(linkage, *symbol);
+}
+
+// Return a writable version of the variable 'name'.
+//
+// Return nullptr if 'name' is not found. This should mean
+// something is seriously wrong (e.g., compiler asking self for
+// built-in that doesn't exist).
+TVariable* TParseContext::getEditableVariable(const char* name)
+{
+ bool builtIn;
+ TSymbol* symbol = symbolTable.find(name, &builtIn);
+
+ assert(symbol != nullptr);
+ if (symbol == nullptr)
+ return nullptr;
+
+ if (builtIn)
+ makeEditable(symbol);
+
+ return symbol->getAsVariable();
+}
+
+// Return true if this is a geometry shader input array or tessellation control output array.
+bool TParseContext::isIoResizeArray(const TType& type) const
+{
+ return type.isArray() &&
+ ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) ||
+ (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch));
+}
+
+// If an array is not isIoResizeArray() but is an io array, make sure it has the right size
+void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type)
+{
+ if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel())
+ return;
+
+ assert(! isIoResizeArray(type));
+
+ if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch)
+ return;
+
+ if (language == EShLangTessControl || language == EShLangTessEvaluation) {
+ if (type.getOuterArraySize() != resources.maxPatchVertices) {
+ if (type.isExplicitlySizedArray())
+ error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", "");
+ type.changeOuterArraySize(resources.maxPatchVertices);
+ }
+ }
+}
+
+// Issue any errors if the non-array object is missing arrayness WRT
+// shader I/O that has array requirements.
+// All arrayness checking is handled in array paths, this is for
+void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+{
+ if (! type.isArray() && ! symbolTable.atBuiltInLevel()) {
+ if (type.getQualifier().isArrayedIo(language))
+ error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str());
+ }
+}
+
+// Handle a dereference of a geometry shader input array or tessellation control output array.
+// See ioArraySymbolResizeList comment in ParseHelper.h.
+//
+void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base)
+{
+ TIntermSymbol* symbolNode = base->getAsSymbolNode();
+ assert(symbolNode);
+ if (! symbolNode)
+ return;
+
+ // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing)
+ if (symbolNode->getType().isImplicitlySizedArray()) {
+ int newSize = getIoArrayImplicitSize();
+ if (newSize > 0)
+ symbolNode->getWritableType().changeOuterArraySize(newSize);
+ }
+}
+
+// If there has been an input primitive declaration (geometry shader) or an output
+// number of vertices declaration(tessellation shader), make sure all input array types
+// match it in size. Types come either from nodes in the AST or symbols in the
+// symbol table.
+//
+// Types without an array size will be given one.
+// Types already having a size that is wrong will get an error.
+//
+void TParseContext::checkIoArraysConsistency(const TSourceLoc& loc, bool tailOnly)
+{
+ int requiredSize = getIoArrayImplicitSize();
+ if (requiredSize == 0)
+ return;
+
+ const char* feature;
+ if (language == EShLangGeometry)
+ feature = TQualifier::getGeometryString(intermediate.getInputPrimitive());
+ else if (language == EShLangTessControl)
+ feature = "vertices";
+ else
+ feature = "unknown";
+
+ if (tailOnly) {
+ checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName());
+ return;
+ }
+
+ for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i)
+ checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName());
+}
+
+int TParseContext::getIoArrayImplicitSize() const
+{
+ if (language == EShLangGeometry)
+ return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive());
+ else if (language == EShLangTessControl)
+ return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0;
+ else
+ return 0;
+}
+
+void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name)
+{
+ if (type.isImplicitlySizedArray())
+ type.changeOuterArraySize(requiredSize);
+ else if (type.getOuterArraySize() != requiredSize) {
+ if (language == EShLangGeometry)
+ error(loc, "inconsistent input primitive for array size of", feature, name.c_str());
+ else if (language == EShLangTessControl)
+ error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str());
+ else
+ assert(0);
+ }
+}
+
+// Handle seeing a binary node with a math operation.
+TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right)
+{
+ rValueErrorCheck(loc, str, left->getAsTyped());
+ rValueErrorCheck(loc, str, right->getAsTyped());
+
+ TIntermTyped* result = intermediate.addBinaryMath(op, left, right, loc);
+ if (! result)
+ binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
+
+ return result;
+}
+
+// Handle seeing a unary node with a math operation.
+TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode)
+{
+ rValueErrorCheck(loc, str, childNode);
+
+ TIntermTyped* result = intermediate.addUnaryMath(op, childNode, loc);
+
+ if (result)
+ return result;
+ else
+ unaryOpError(loc, str, childNode->getCompleteString());
+
+ return childNode;
+}
+
+//
+// Handle seeing a base.field dereference in the grammar.
+//
+TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
+{
+ variableCheck(base);
+
+ //
+ // .length() can't be resolved until we later see the function-calling syntax.
+ // Save away the name in the AST for now. Processing is completed in
+ // handleLengthMethod().
+ //
+ if (field == "length") {
+ if (base->isArray()) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length");
+ profileRequires(loc, EEsProfile, 300, nullptr, ".length");
+ } else if (base->isVector() || base->isMatrix()) {
+ const char* feature = ".length() on vectors and matrices";
+ requireProfile(loc, ~EEsProfile, feature);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
+ } else {
+ error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str());
+
+ return base;
+ }
+
+ return intermediate.addMethod(base, TType(EbtInt), &field, loc);
+ }
+
+ // It's not .length() if we get to here.
+
+ if (base->isArray()) {
+ error(loc, "cannot apply to an array:", ".", field.c_str());
+
+ return base;
+ }
+
+ // It's neither an array nor .length() if we get here,
+ // leaving swizzles and struct/block dereferences.
+
+ TIntermTyped* result = base;
+ if (base->isVector() || base->isScalar()) {
+ if (base->isScalar()) {
+ const char* dotFeature = "scalar swizzle";
+ requireProfile(loc, ~EEsProfile, dotFeature);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
+ }
+
+ TVectorFields fields;
+ if (! parseVectorFields(loc, field, base->getVectorSize(), fields)) {
+ fields.num = 1;
+ fields.offsets[0] = 0;
+ }
+
+ if (base->isScalar()) {
+ if (fields.num == 1)
+ return result;
+ else {
+ TType type(base->getBasicType(), EvqTemporary, fields.num);
+ // Swizzle operations propagate specialization-constantness
+ if (base->getQualifier().isSpecConstant())
+ type.getQualifier().makeSpecConstant();
+ return addConstructor(loc, base, type, mapTypeToConstructorOp(type));
+ }
+ }
+
+ if (base->getType().getQualifier().isFrontEndConstant())
+ result = intermediate.foldSwizzle(base, fields, loc);
+ else {
+ if (fields.num == 1) {
+ TIntermTyped* index = intermediate.addConstantUnion(fields.offsets[0], loc);
+ result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
+ result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
+ } else {
+ TString vectorString = field;
+ TIntermTyped* index = intermediate.addSwizzle(fields, loc);
+ result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
+ result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, (int) vectorString.size()));
+ }
+ // Swizzle operations propagate specialization-constantness
+ if (base->getType().getQualifier().isSpecConstant())
+ result->getWritableType().getQualifier().makeSpecConstant();
+ }
+ } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) {
+ const TTypeList* fields = base->getType().getStruct();
+ bool fieldFound = false;
+ int member;
+ for (member = 0; member < (int)fields->size(); ++member) {
+ if ((*fields)[member].type->getFieldName() == field) {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound) {
+ if (base->getType().getQualifier().isFrontEndConstant())
+ result = intermediate.foldDereference(base, member, loc);
+ else {
+ blockMemberExtensionCheck(loc, base, field);
+ TIntermTyped* index = intermediate.addConstantUnion(member, loc);
+ result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
+ result->setType(*(*fields)[member].type);
+ }
+ } else
+ error(loc, "no such field in structure", field.c_str(), "");
+ } else
+ error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str());
+
+ // Propagate noContraction up the dereference chain
+ if (base->getQualifier().noContraction)
+ result->getWritableType().getQualifier().noContraction = true;
+
+ return result;
+}
+
+void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* /*base*/, const TString& field)
+{
+ if (profile == EEsProfile && field == "gl_PointSize") {
+ if (language == EShLangGeometry)
+ requireExtensions(loc, Num_AEP_geometry_point_size, AEP_geometry_point_size, "gl_PointSize");
+ else if (language == EShLangTessControl || language == EShLangTessEvaluation)
+ requireExtensions(loc, Num_AEP_tessellation_point_size, AEP_tessellation_point_size, "gl_PointSize");
+ }
+}
+
+//
+// Handle seeing a function declarator in the grammar. This is the precursor
+// to recognizing a function prototype or function definition.
+//
+TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype)
+{
+ // ES can't declare prototypes inside functions
+ if (! symbolTable.atGlobalLevel())
+ requireProfile(loc, ~EEsProfile, "local function declaration");
+
+ //
+ // Multiple declarations of the same function name are allowed.
+ //
+ // If this is a definition, the definition production code will check for redefinitions
+ // (we don't know at this point if it's a definition or not).
+ //
+ // Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match.
+ // - except ES 100, which only allows a single prototype
+ //
+ // ES 100 does not allow redefining, but does allow overloading of built-in functions.
+ // ES 300 does not allow redefining or overloading of built-in functions.
+ //
+ bool builtIn;
+ TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
+ if (symbol && symbol->getAsFunction() && builtIn)
+ requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
+ const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
+ if (prevDec) {
+ if (prevDec->isPrototyped() && prototype)
+ profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function");
+ if (prevDec->getType() != function.getType())
+ error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), "");
+ for (int i = 0; i < prevDec->getParamCount(); ++i) {
+ if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
+ error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
+
+ if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision)
+ error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1);
+ }
+ }
+
+ arrayObjectCheck(loc, function.getType(), "array in function return type");
+
+ if (prototype) {
+ // All built-in functions are defined, even though they don't have a body.
+ // Count their prototype as a definition instead.
+ if (symbolTable.atBuiltInLevel())
+ function.setDefined();
+ else {
+ if (prevDec && ! builtIn)
+ symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const
+ function.setPrototyped();
+ }
+ }
+
+ // This insert won't actually insert it if it's a duplicate signature, but it will still check for
+ // other forms of name collisions.
+ if (! symbolTable.insert(function))
+ error(loc, "function name is redeclaration of existing name", function.getName().c_str(), "");
+
+ //
+ // If this is a redeclaration, it could also be a definition,
+ // in which case, we need to use the parameter names from this one, and not the one that's
+ // being redeclared. So, pass back this declaration, not the one in the symbol table.
+ //
+ return &function;
+}
+
+//
+// Handle seeing the function prototype in front of a function definition in the grammar.
+// The body is handled after this function returns.
+//
+TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function)
+{
+ currentCaller = function.getMangledName();
+ TSymbol* symbol = symbolTable.find(function.getMangledName());
+ TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr;
+
+ if (! prevDec)
+ error(loc, "can't find function", function.getName().c_str(), "");
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function
+ // as it would have just been put in the symbol table. Otherwise, we're looking up
+ // an earlier occurance.
+
+ if (prevDec && prevDec->isDefined()) {
+ // Then this function already has a body.
+ error(loc, "function already has a body", function.getName().c_str(), "");
+ }
+ if (prevDec && ! prevDec->isDefined()) {
+ prevDec->setDefined();
+
+ // Remember the return type for later checking for RETURN statements.
+ currentFunctionType = &(prevDec->getType());
+ } else
+ currentFunctionType = new TType(EbtVoid);
+ functionReturnsValue = false;
+
+ //
+ // Raise error message if main function takes any parameters or returns anything other than void
+ //
+ if (function.getName() == intermediate.getEntryPoint().c_str()) {
+ if (function.getParamCount() > 0)
+ error(loc, "function cannot take any parameter(s)", function.getName().c_str(), "");
+ if (function.getType().getBasicType() != EbtVoid)
+ error(loc, "", function.getType().getBasicTypeString().c_str(), "main function cannot return a value");
+ intermediate.addMainCount();
+ inMain = true;
+ } else
+ inMain = false;
+
+ //
+ // New symbol table scope for body of function plus its arguments
+ //
+ symbolTable.push();
+
+ //
+ // Insert parameters into the symbol table.
+ // If the parameter has no name, it's not an error, just don't insert it
+ // (could be used for unused args).
+ //
+ // Also, accumulate the list of parameters into the HIL, so lower level code
+ // knows where to find parameters.
+ //
+ TIntermAggregate* paramNodes = new TIntermAggregate;
+ for (int i = 0; i < function.getParamCount(); i++) {
+ TParameter& param = function[i];
+ if (param.name != nullptr) {
+ TVariable *variable = new TVariable(param.name, *param.type);
+
+ // Insert the parameters with name in the symbol table.
+ if (! symbolTable.insert(*variable))
+ error(loc, "redefinition", variable->getName().c_str(), "");
+ else {
+ // Transfer ownership of name pointer to symbol table.
+ param.name = nullptr;
+
+ // Add the parameter to the HIL
+ paramNodes = intermediate.growAggregate(paramNodes,
+ intermediate.addSymbol(*variable, loc),
+ loc);
+ }
+ } else
+ paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
+ }
+ intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
+ loopNestingLevel = 0;
+ statementNestingLevel = 0;
+ controlFlowNestingLevel = 0;
+ postMainReturn = false;
+
+ return paramNodes;
+}
+
+//
+// Handle seeing function call syntax in the grammar, which could be any of
+// - .length() method
+// - constructor
+// - a call to a built-in function mapped to an operator
+// - a call to a built-in function that will remain a function call (e.g., texturing)
+// - user function
+// - subroutine call (not implemented yet)
+//
+TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments)
+{
+ TIntermTyped* result = nullptr;
+
+ TOperator op = function->getBuiltInOp();
+ if (op == EOpArrayLength)
+ result = handleLengthMethod(loc, function, arguments);
+ else if (op != EOpNull) {
+ //
+ // Then this should be a constructor.
+ // Don't go through the symbol table for constructors.
+ // Their parameters will be verified algorithmically.
+ //
+ TType type(EbtVoid); // use this to get the type back
+ if (! constructorError(loc, arguments, *function, op, type)) {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ result = addConstructor(loc, arguments, type, op);
+ if (result == nullptr)
+ error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
+ }
+ } else {
+ //
+ // Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = findFunction(loc, *function, builtIn);
+ if (fnCandidate) {
+ // This is a declared function that might map to
+ // - a built-in operator,
+ // - a built-in function not mapped to an operator, or
+ // - a user function.
+
+ // Error check for a function requiring specific extensions present.
+ if (builtIn && fnCandidate->getNumExtensions())
+ requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
+
+ if (arguments) {
+ // Make sure qualifications work for these arguments.
+ TIntermAggregate* aggregate = arguments->getAsAggregate();
+ for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+ // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
+ // is the single argument itself or its children are the arguments. Only one argument
+ // means take 'arguments' itself as the one argument.
+ TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments);
+ TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier();
+ if (formalQualifier.storage == EvqOut || formalQualifier.storage == EvqInOut) {
+ if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped()))
+ error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", "");
+ }
+ TQualifier& argQualifier = arg->getAsTyped()->getQualifier();
+ if (argQualifier.isMemory()) {
+ const char* message = "argument cannot drop memory qualifier when passed to formal parameter";
+ if (argQualifier.volatil && ! formalQualifier.volatil)
+ error(arguments->getLoc(), message, "volatile", "");
+ if (argQualifier.coherent && ! formalQualifier.coherent)
+ error(arguments->getLoc(), message, "coherent", "");
+ if (argQualifier.readonly && ! formalQualifier.readonly)
+ error(arguments->getLoc(), message, "readonly", "");
+ if (argQualifier.writeonly && ! formalQualifier.writeonly)
+ error(arguments->getLoc(), message, "writeonly", "");
+ }
+ // TODO 4.5 functionality: A shader will fail to compile
+ // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or
+ // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the
+ // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or
+ // shared variable.
+ }
+
+ // Convert 'in' arguments
+ addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node
+ }
+
+ op = fnCandidate->getBuiltInOp();
+ if (builtIn && op != EOpNull) {
+ // A function call mapped to a built-in operation.
+ checkLocation(loc, op);
+ result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments, fnCandidate->getType());
+ if (result == nullptr) {
+ error(arguments->getLoc(), " wrong operand type", "Internal Error",
+ "built in unary operator function. Type: %s",
+ static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
+ } else if (result->getAsOperator()) {
+ builtInOpCheck(loc, *fnCandidate, *result->getAsOperator());
+ }
+ } else {
+ // This is a function call not mapped to built-in operator.
+ // It could still be a built-in function, but only if PureOperatorBuiltins == false.
+ result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc);
+ TIntermAggregate* call = result->getAsAggregate();
+ call->setName(fnCandidate->getMangledName());
+
+ // this is how we know whether the given function is a built-in function or a user-defined function
+ // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also
+ // if builtIn == true, it's definitely a built-in function with EOpNull
+ if (! builtIn) {
+ call->setUserDefined();
+ if (symbolTable.atGlobalLevel())
+ error(loc, "can't call user function from global scope", fnCandidate->getName().c_str(), "");
+ else
+ intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
+ }
+
+ if (builtIn)
+ nonOpBuiltInCheck(loc, *fnCandidate, *call);
+ }
+
+ // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore.
+ // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output.
+ // Also, build the qualifier list for user function calls, which are always called with an aggregate.
+ if (result->getAsAggregate()) {
+ TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList();
+ for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+ TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage;
+ qualifierList.push_back(qual);
+ }
+ result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate());
+ }
+ }
+ }
+
+ // generic error recovery
+ // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades
+ if (result == nullptr)
+ result = intermediate.addConstantUnion(0.0, EbtFloat, loc);
+
+ return result;
+}
+
+// See if the operation is being done in an illegal location.
+void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
+{
+ switch (op) {
+ case EOpBarrier:
+ if (language == EShLangTessControl) {
+ if (controlFlowNestingLevel > 0)
+ error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
+ if (! inMain)
+ error(loc, "tessellation control barrier() must be in main()", "", "");
+ else if (postMainReturn)
+ error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Finish processing object.length(). This started earlier in handleDotDereference(), where
+// the ".length" part was recognized and semantically checked, and finished here where the
+// function syntax "()" is recognized.
+//
+// Return resulting tree node.
+TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode)
+{
+ int length = 0;
+
+ if (function->getParamCount() > 0)
+ error(loc, "method does not accept any arguments", function->getName().c_str(), "");
+ else {
+ const TType& type = intermNode->getAsTyped()->getType();
+ if (type.isArray()) {
+ if (type.isRuntimeSizedArray()) {
+ // Create a unary op and let the back end handle it
+ return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
+ } else if (type.isImplicitlySizedArray()) {
+ if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) {
+ // We could be between a layout declaration that gives a built-in io array implicit size and
+ // a user redeclaration of that array, meaning we have to substitute its implicit size here
+ // without actually redeclaring the array. (It is an error to use a member before the
+ // redeclaration, but not an error to use the array name itself.)
+ const TString& name = intermNode->getAsSymbolNode()->getName();
+ if (name == "gl_in" || name == "gl_out")
+ length = getIoArrayImplicitSize();
+ }
+ if (length == 0) {
+ if (intermNode->getAsSymbolNode() && isIoResizeArray(type))
+ error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
+ else
+ error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
+ }
+ } else if (type.getOuterArrayNode()) {
+ // If the array's outer size is specified by an intermediate node, it means the array's length
+ // was specified by a specialization constant. In such a case, we should return the node of the
+ // specialization constants to represent the length.
+ return type.getOuterArrayNode();
+ } else
+ length = type.getOuterArraySize();
+ } else if (type.isMatrix())
+ length = type.getMatrixCols();
+ else if (type.isVector())
+ length = type.getVectorSize();
+ else {
+ // we should not get here, because earlier semantic checking should have prevented this path
+ error(loc, ".length()", "unexpected use of .length()", "");
+ }
+ }
+
+ if (length == 0)
+ length = 1;
+
+ return intermediate.addConstantUnion(length, loc);
+}
+
+//
+// Add any needed implicit conversions for function-call arguments to input parameters.
+//
+void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const
+{
+ TIntermAggregate* aggregate = arguments->getAsAggregate();
+
+ // Process each argument's conversion
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
+ // is the single argument itself or its children are the arguments. Only one argument
+ // means take 'arguments' itself as the one argument.
+ TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped());
+ if (*function[i].type != arg->getType()) {
+ if (function[i].type->getQualifier().isParamInput()) {
+ // In-qualified arguments just need an extra node added above the argument to
+ // convert to the correct type.
+ arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg);
+ if (arg) {
+ if (function.getParamCount() == 1)
+ arguments = arg;
+ else {
+ if (aggregate)
+ aggregate->getSequence()[i] = arg;
+ else
+ arguments = arg;
+ }
+ }
+ }
+ }
+ }
+}
+
+//
+// Add any needed implicit output conversions for function-call arguments. This
+// can require a new tree topology, complicated further by whether the function
+// has a return value.
+//
+// Returns a node of a subtree that evaluates to the return value of the function.
+//
+TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const
+{
+ TIntermSequence& arguments = intermNode.getSequence();
+
+ // Will there be any output conversions?
+ bool outputConversions = false;
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().storage == EvqOut) {
+ outputConversions = true;
+ break;
+ }
+ }
+
+ if (! outputConversions)
+ return &intermNode;
+
+ // Setup for the new tree, if needed:
+ //
+ // Output conversions need a different tree topology.
+ // Out-qualified arguments need a temporary of the correct type, with the call
+ // followed by an assignment of the temporary to the original argument:
+ // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...)
+ // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet)
+ // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment.
+ TIntermTyped* conversionTree = nullptr;
+ TVariable* tempRet = nullptr;
+ if (intermNode.getBasicType() != EbtVoid) {
+ // do the "tempRet = function(...), " bit from above
+ tempRet = makeInternalVariable("tempReturn", intermNode.getType());
+ TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
+ conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc());
+ } else
+ conversionTree = &intermNode;
+
+ conversionTree = intermediate.makeAggregate(conversionTree);
+
+ // Process each argument's conversion
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ if (*function[i].type != arguments[i]->getAsTyped()->getType()) {
+ if (function[i].type->getQualifier().isParamOutput()) {
+ // Out-qualified arguments need to use the topology set up above.
+ // do the " ...(tempArg, ...), arg = tempArg" bit from above
+ TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type);
+ tempArg->getWritableType().getQualifier().makeTemporary();
+ TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc());
+ TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc());
+ conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc());
+ // replace the argument with another node for the same tempArg variable
+ arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc());
+ }
+ }
+ }
+
+ // Finalize the tree topology (see bigger comment above).
+ if (tempRet) {
+ // do the "..., tempRet" bit from above
+ TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
+ conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc());
+ }
+ conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc());
+
+ return conversionTree;
+}
+
+//
+// Do additional checking of built-in function calls that is not caught
+// by normal semantic checks on argument type, extension tagging, etc.
+//
+// Assumes there has been a semantically correct match to a built-in function prototype.
+//
+void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode)
+{
+ // Set up convenience accessors to the argument(s). There is almost always
+ // multiple arguments for the cases below, but when there might be one,
+ // check the unaryArg first.
+ const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference
+ const TIntermTyped* unaryArg = nullptr;
+ const TIntermTyped* arg0 = nullptr;
+ if (callNode.getAsAggregate()) {
+ argp = &callNode.getAsAggregate()->getSequence();
+ if (argp->size() > 0)
+ arg0 = (*argp)[0]->getAsTyped();
+ } else {
+ assert(callNode.getAsUnaryNode());
+ unaryArg = callNode.getAsUnaryNode()->getOperand();
+ arg0 = unaryArg;
+ }
+ const TIntermSequence& aggArgs = *argp; // only valid when unaryArg is nullptr
+
+ // built-in texturing functions get their return value precision from the precision of the sampler
+ if (fnCandidate.getType().getQualifier().precision == EpqNone &&
+ fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
+ callNode.getQualifier().precision = arg0->getQualifier().precision;
+
+ switch (callNode.getOp()) {
+ case EOpTextureGather:
+ case EOpTextureGatherOffset:
+ case EOpTextureGatherOffsets:
+ {
+ // Figure out which variants are allowed by what extensions,
+ // and what arguments must be constant for which situations.
+
+ TString featureString = fnCandidate.getName() + "(...)";
+ const char* feature = featureString.c_str();
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ int compArg = -1; // track which argument, if any, is the constant component argument
+ switch (callNode.getOp()) {
+ case EOpTextureGather:
+ // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
+ // otherwise, need GL_ARB_texture_gather.
+ if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 2;
+ } else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ break;
+ case EOpTextureGatherOffset:
+ // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
+ if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! aggArgs[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
+ profileRequires(loc, EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "non-constant offset argument");
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ break;
+ case EOpTextureGatherOffsets:
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ // check for constant offsets
+ if (! aggArgs[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
+ error(loc, "must be a compile-time constant:", feature, "offsets argument");
+ break;
+ default:
+ break;
+ }
+
+ if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
+ if (aggArgs[compArg]->getAsConstantUnion()) {
+ int value = aggArgs[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (value < 0 || value > 3)
+ error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
+ } else
+ error(loc, "must be a compile-time constant:", feature, "component argument");
+ }
+
+ break;
+ }
+
+ case EOpTextureOffset:
+ case EOpTextureFetchOffset:
+ case EOpTextureProjOffset:
+ case EOpTextureLodOffset:
+ case EOpTextureProjLodOffset:
+ case EOpTextureGradOffset:
+ case EOpTextureProjGradOffset:
+ {
+ // Handle texture-offset limits checking
+ // Pick which argument has to hold constant offsets
+ int arg = -1;
+ switch (callNode.getOp()) {
+ case EOpTextureOffset: arg = 2; break;
+ case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().dim != EsdRect) ? 3 : 2; break;
+ case EOpTextureProjOffset: arg = 2; break;
+ case EOpTextureLodOffset: arg = 3; break;
+ case EOpTextureProjLodOffset: arg = 3; break;
+ case EOpTextureGradOffset: arg = 4; break;
+ case EOpTextureProjGradOffset: arg = 4; break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (arg > 0) {
+ if (! aggArgs[arg]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "texel offset", "");
+ else {
+ const TType& type = aggArgs[arg]->getAsTyped()->getType();
+ for (int c = 0; c < type.getVectorSize(); ++c) {
+ int offset = aggArgs[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
+ if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
+ error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
+ }
+ }
+ }
+
+ break;
+ }
+
+ case EOpTextureQuerySamples:
+ case EOpImageQuerySamples:
+ // GL_ARB_shader_texture_image_samples
+ profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
+ break;
+
+ case EOpImageAtomicAdd:
+ case EOpImageAtomicMin:
+ case EOpImageAtomicMax:
+ case EOpImageAtomicAnd:
+ case EOpImageAtomicOr:
+ case EOpImageAtomicXor:
+ case EOpImageAtomicExchange:
+ case EOpImageAtomicCompSwap:
+ {
+ // Make sure the image types have the correct layout() format and correct argument types
+ const TType& imageType = arg0->getType();
+ if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
+ if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui)
+ error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
+ } else {
+ if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
+ error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
+ else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile)
+ error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
+ }
+
+ break;
+ }
+
+ case EOpInterpolateAtCentroid:
+ case EOpInterpolateAtSample:
+ case EOpInterpolateAtOffset:
+ // "For the interpolateAt* functions, the call will return a precision
+ // qualification matching the precision of the 'interpolant' argument to
+ // the function call."
+ callNode.getQualifier().precision = arg0->getQualifier().precision;
+
+ // Make sure the first argument is an interpolant, or an array element of an interpolant
+ if (arg0->getType().getQualifier().storage != EvqVaryingIn) {
+ // It might still be an array element.
+ //
+ // We could check more, but the semantics of the first argument are already met; the
+ // only way to turn an array into a float/vec* is array dereference and swizzle.
+ //
+ // ES and desktop 4.3 and earlier: swizzles may not be used
+ // desktop 4.4 and later: swizzles may be used
+ bool swizzleOkay = (profile != EEsProfile) && (version >= 440);
+ const TIntermTyped* base = TIntermediate::findLValueBase(arg0, swizzleOkay);
+ if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn)
+ error(loc, "first argument must be an interpolant, or interpolant-array element", fnCandidate.getName().c_str(), "");
+ }
+ break;
+
+ case EOpEmitStreamVertex:
+ case EOpEndStreamPrimitive:
+ intermediate.setMultiStream();
+ break;
+
+ default:
+ break;
+ }
+}
+
+extern bool PureOperatorBuiltins;
+
+// Deprecated! Use PureOperatorBuiltins == true instead, in which case this
+// functionality is handled in builtInOpCheck() instead of here.
+//
+// Do additional checking of built-in function calls that were not mapped
+// to built-in operations (e.g., texturing functions).
+//
+// Assumes there has been a semantically correct match to a built-in function.
+//
+void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode)
+{
+ // Further maintenance of this function is deprecated, because the "correct"
+ // future-oriented design is to not have to do string compares on function names.
+
+ // If PureOperatorBuiltins == true, then all built-ins should be mapped
+ // to a TOperator, and this function would then never get called.
+
+ assert(PureOperatorBuiltins == false);
+
+ // built-in texturing functions get their return value precision from the precision of the sampler
+ if (fnCandidate.getType().getQualifier().precision == EpqNone &&
+ fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
+ callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision;
+
+ if (fnCandidate.getName().compare(0, 7, "texture") == 0) {
+ if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
+ TString featureString = fnCandidate.getName() + "(...)";
+ const char* feature = featureString.c_str();
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+
+ int compArg = -1; // track which argument, if any, is the constant component argument
+ if (fnCandidate.getName().compare("textureGatherOffset") == 0) {
+ // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
+ if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
+ if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
+ profileRequires(loc, EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "non-constant offset argument");
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) {
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 3;
+ // check for constant offsets
+ int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2;
+ if (! callNode.getSequence()[offsetArg]->getAsConstantUnion())
+ error(loc, "must be a compile-time constant:", feature, "offsets argument");
+ } else if (fnCandidate.getName().compare("textureGather") == 0) {
+ // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
+ // otherwise, need GL_ARB_texture_gather.
+ if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
+ if (! fnCandidate[0].type->getSampler().shadow)
+ compArg = 2;
+ } else
+ profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
+ }
+
+ if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
+ if (callNode.getSequence()[compArg]->getAsConstantUnion()) {
+ int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (value < 0 || value > 3)
+ error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
+ } else
+ error(loc, "must be a compile-time constant:", feature, "component argument");
+ }
+ } else {
+ // this is only for functions not starting "textureGather"...
+ if (fnCandidate.getName().find("Offset") != TString::npos) {
+
+ // Handle texture-offset limits checking
+ int arg = -1;
+ if (fnCandidate.getName().compare("textureOffset") == 0)
+ arg = 2;
+ else if (fnCandidate.getName().compare("texelFetchOffset") == 0)
+ arg = 3;
+ else if (fnCandidate.getName().compare("textureProjOffset") == 0)
+ arg = 2;
+ else if (fnCandidate.getName().compare("textureLodOffset") == 0)
+ arg = 3;
+ else if (fnCandidate.getName().compare("textureProjLodOffset") == 0)
+ arg = 3;
+ else if (fnCandidate.getName().compare("textureGradOffset") == 0)
+ arg = 4;
+ else if (fnCandidate.getName().compare("textureProjGradOffset") == 0)
+ arg = 4;
+
+ if (arg > 0) {
+ if (! callNode.getSequence()[arg]->getAsConstantUnion())
+ error(loc, "argument must be compile-time constant", "texel offset", "");
+ else {
+ const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType();
+ for (int c = 0; c < type.getVectorSize(); ++c) {
+ int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
+ if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
+ error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // GL_ARB_shader_texture_image_samples
+ if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0)
+ profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
+
+ if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) {
+ const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType();
+ if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
+ if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui)
+ error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
+ } else {
+ if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
+ error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
+ else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile)
+ error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
+ }
+ }
+}
+
+//
+// Handle seeing a built-in constructor in a grammar production.
+//
+TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType)
+{
+ TType type(publicType);
+ type.getQualifier().precision = EpqNone;
+
+ if (type.isArray()) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor");
+ profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor");
+ }
+
+ TOperator op = mapTypeToConstructorOp(type);
+
+ if (op == EOpNull) {
+ error(loc, "cannot construct this type", type.getBasicString(), "");
+ op = EOpConstructFloat;
+ TType errorType(EbtFloat);
+ type.shallowCopy(errorType);
+ }
+
+ TString empty("");
+
+ return new TFunction(&empty, type, op);
+}
+
+//
+// Given a type, find what operation would fully construct it.
+//
+TOperator TParseContext::mapTypeToConstructorOp(const TType& type) const
+{
+ TOperator op = EOpNull;
+
+ switch (type.getBasicType()) {
+ case EbtStruct:
+ op = EOpConstructStruct;
+ break;
+ case EbtSampler:
+ if (type.getSampler().combined)
+ op = EOpConstructTextureSampler;
+ break;
+ case EbtFloat:
+ if (type.isMatrix()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructMat2x2; break;
+ case 3: op = EOpConstructMat2x3; break;
+ case 4: op = EOpConstructMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructMat3x2; break;
+ case 3: op = EOpConstructMat3x3; break;
+ case 4: op = EOpConstructMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructMat4x2; break;
+ case 3: op = EOpConstructMat4x3; break;
+ case 4: op = EOpConstructMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ default: break; // some compilers want this
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtDouble:
+ if (type.getMatrixCols()) {
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructDMat2x2; break;
+ case 3: op = EOpConstructDMat2x3; break;
+ case 4: op = EOpConstructDMat2x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructDMat3x2; break;
+ case 3: op = EOpConstructDMat3x3; break;
+ case 4: op = EOpConstructDMat3x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: op = EOpConstructDMat4x2; break;
+ case 3: op = EOpConstructDMat4x3; break;
+ case 4: op = EOpConstructDMat4x4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ }
+ } else {
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructDouble; break;
+ case 2: op = EOpConstructDVec2; break;
+ case 3: op = EOpConstructDVec3; break;
+ case 4: op = EOpConstructDVec4; break;
+ default: break; // some compilers want this
+ }
+ }
+ break;
+ case EbtInt:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructInt; break;
+ case 2: op = EOpConstructIVec2; break;
+ case 3: op = EOpConstructIVec3; break;
+ case 4: op = EOpConstructIVec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtUint:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructUint; break;
+ case 2: op = EOpConstructUVec2; break;
+ case 3: op = EOpConstructUVec3; break;
+ case 4: op = EOpConstructUVec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtInt64:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructInt64; break;
+ case 2: op = EOpConstructI64Vec2; break;
+ case 3: op = EOpConstructI64Vec3; break;
+ case 4: op = EOpConstructI64Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtUint64:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructUint64; break;
+ case 2: op = EOpConstructU64Vec2; break;
+ case 3: op = EOpConstructU64Vec3; break;
+ case 4: op = EOpConstructU64Vec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ case EbtBool:
+ switch(type.getVectorSize()) {
+ case 1: op = EOpConstructBool; break;
+ case 2: op = EOpConstructBVec2; break;
+ case 3: op = EOpConstructBVec3; break;
+ case 4: op = EOpConstructBVec4; break;
+ default: break; // some compilers want this
+ }
+ break;
+ default:
+ break;
+ }
+
+ return op;
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right)
+{
+ error(loc, "", op, "cannot convert from '%s' to '%s'",
+ right.c_str(), left.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand)
+{
+ error(loc, " wrong operand type", op,
+ "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
+ op, operand.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right)
+{
+ error(loc, " wrong operand types:", op,
+ "no operation '%s' exists that takes a left-hand operand of type '%s' and "
+ "a right operand of type '%s' (or there is no acceptable conversion)",
+ op, left.c_str(), right.c_str());
+}
+
+//
+// A basic type of EbtVoid is a key that the name string was seen in the source, but
+// it was not found as a variable in the symbol table. If so, give the error
+// message and insert a dummy variable in the symbol table to prevent future errors.
+//
+void TParseContext::variableCheck(TIntermTyped*& nodePtr)
+{
+ TIntermSymbol* symbol = nodePtr->getAsSymbolNode();
+ if (! symbol)
+ return;
+
+ if (symbol->getType().getBasicType() == EbtVoid) {
+ error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), "");
+
+ // Add to symbol table to prevent future error messages on the same name
+ if (symbol->getName().size() > 0) {
+ TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat));
+ symbolTable.insert(*fakeVariable);
+
+ // substitute a symbol node for this new variable
+ nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc());
+ }
+ } else {
+ switch (symbol->getQualifier().storage) {
+ case EvqPointCoord:
+ profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord");
+ break;
+ default: break; // some compilers want this
+ }
+ }
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
+{
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+ if (binaryNode) {
+ bool errorReturn;
+
+ switch(binaryNode->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ // ... tessellation control shader ...
+ // If a per-vertex output variable is used as an l-value, it is a
+ // compile-time or link-time error if the expression indicating the
+ // vertex index is not the identifier gl_InvocationID.
+ if (language == EShLangTessControl) {
+ const TType& leftType = binaryNode->getLeft()->getType();
+ if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) {
+ // we have a per-vertex output
+ const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode();
+ if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId)
+ error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", "");
+ }
+ }
+
+ // fall through
+ case EOpIndexDirectStruct:
+ return lValueErrorCheck(loc, op, binaryNode->getLeft());
+ case EOpVectorSwizzle:
+ errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft());
+ if (!errorReturn) {
+ int offset[4] = {0,0,0,0};
+
+ TIntermTyped* rightNode = binaryNode->getRight();
+ TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+
+ for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
+ p != aggrNode->getSequence().end(); p++) {
+ int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ offset[value]++;
+ if (offset[value] > 1) {
+ error(loc, " l-value of swizzle cannot have duplicate components", op, "", "");
+
+ return true;
+ }
+ }
+ }
+
+ return errorReturn;
+ default:
+ break;
+ }
+ error(loc, " l-value required", op, "", "");
+
+ return true;
+ }
+
+
+ const char* symbol = nullptr;
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ if (symNode != nullptr)
+ symbol = symNode->getName().c_str();
+
+ const char* message = nullptr;
+ switch (node->getQualifier().storage) {
+ case EvqConst: message = "can't modify a const"; break;
+ case EvqConstReadOnly: message = "can't modify a const"; break;
+ case EvqVaryingIn: message = "can't modify shader input"; break;
+ case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
+ case EvqVertexId: message = "can't modify gl_VertexID"; break;
+ case EvqFace: message = "can't modify gl_FrontFace"; break;
+ case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
+ case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
+ case EvqUniform: message = "can't modify a uniform"; break;
+ case EvqBuffer:
+ if (node->getQualifier().readonly)
+ message = "can't modify a readonly buffer";
+ break;
+ case EvqFragDepth:
+ intermediate.setDepthReplacing();
+ // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader."
+ if (profile == EEsProfile && intermediate.getEarlyFragmentTests())
+ message = "can't modify gl_FragDepth if using early_fragment_tests";
+ break;
+
+ default:
+ //
+ // Type that can't be written to?
+ //
+ switch (node->getBasicType()) {
+ case EbtSampler:
+ message = "can't modify a sampler";
+ break;
+ case EbtAtomicUint:
+ message = "can't modify an atomic_uint";
+ break;
+ case EbtVoid:
+ message = "can't modify void";
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
+ error(loc, " l-value required", op, "", "");
+
+ return true;
+ }
+
+
+ //
+ // Everything else is okay, no error.
+ //
+ if (message == nullptr)
+ return false;
+
+ //
+ // If we get here, we have an error and a message.
+ //
+ if (symNode)
+ error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
+ else
+ error(loc, " l-value required", op, "(%s)", message);
+
+ return true;
+}
+
+// Test for and give an error if the node can't be read from.
+void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
+{
+ if (! node)
+ return;
+
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+ if (binaryNode) {
+ switch(binaryNode->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpVectorSwizzle:
+ rValueErrorCheck(loc, op, binaryNode->getLeft());
+ default:
+ break;
+ }
+
+ return;
+ }
+
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ if (symNode && symNode->getQualifier().writeonly)
+ error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+void TParseContext::constantValueCheck(TIntermTyped* node, const char* token)
+{
+ if (! node->getQualifier().isConstant())
+ error(node->getLoc(), "constant expression required", token, "");
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+void TParseContext::integerCheck(const TIntermTyped* node, const char* token)
+{
+ if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar())
+ return;
+
+ error(node->getLoc(), "scalar integer expression required", token, "");
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+void TParseContext::globalCheck(const TSourceLoc& loc, const char* token)
+{
+ if (! symbolTable.atGlobalLevel())
+ error(loc, "not allowed in nested scope", token, "");
+}
+
+//
+// Reserved errors for GLSL.
+//
+void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier)
+{
+ // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be
+ // declared in a shader; this results in a compile-time error."
+ if (! symbolTable.atBuiltInLevel()) {
+ if (builtInName(identifier))
+ error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), "");
+
+ // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification:
+ // "In addition, all identifiers containing two consecutive underscores (__) are
+ // reserved; using such a name does not itself result in an error, but may result
+ // in undefined behavior."
+ // however, before that, ES tests required an error.
+ if (identifier.find("__") != TString::npos) {
+ if (profile == EEsProfile && version <= 300)
+ error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version <= 300", identifier.c_str(), "");
+ else
+ warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), "");
+ }
+ }
+}
+
+//
+// Reserved errors for the preprocessor.
+//
+void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op)
+{
+ // "__" are not supposed to be an error. ES 310 (and desktop) added the clarification:
+ // "All macro names containing two consecutive underscores ( __ ) are reserved;
+ // defining such a name does not itself result in an error, but may result in
+ // undefined behavior. All macro names prefixed with "GL_" ("GL" followed by a
+ // single underscore) are also reserved, and defining such a name results in a
+ // compile-time error."
+ // however, before that, ES tests required an error.
+ if (strncmp(identifier, "GL_", 3) == 0)
+ ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier);
+ else if (strncmp(identifier, "defined", 8) == 0)
+ ppError(loc, "\"defined\" can't be (un)defined:", op, identifier);
+ else if (strstr(identifier, "__") != 0) {
+ if (profile == EEsProfile && version >= 300 &&
+ (strcmp(identifier, "__LINE__") == 0 ||
+ strcmp(identifier, "__FILE__") == 0 ||
+ strcmp(identifier, "__VERSION__") == 0))
+ ppError(loc, "predefined names can't be (un)defined:", op, identifier);
+ else {
+ if (profile == EEsProfile && version <= 300)
+ ppError(loc, "names containing consecutive underscores are reserved, and an error if version <= 300:", op, identifier);
+ else
+ ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier);
+ }
+ }
+}
+
+//
+// See if this version/profile allows use of the line-continuation character '\'.
+//
+// Returns true if a line continuation should be done.
+//
+bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment)
+{
+ const char* message = "line continuation";
+
+ bool lineContinuationAllowed = (profile == EEsProfile && version >= 300) ||
+ (profile != EEsProfile && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack)));
+
+ if (endOfComment) {
+ if (lineContinuationAllowed)
+ warn(loc, "used at end of comment; the following line is still part of the comment", message, "");
+ else
+ warn(loc, "used at end of comment, but this version does not provide line continuation", message, "");
+
+ return lineContinuationAllowed;
+ }
+
+ if (relaxedErrors()) {
+ if (! lineContinuationAllowed)
+ warn(loc, "not allowed in this version", message, "");
+ return true;
+ } else {
+ profileRequires(loc, EEsProfile, 300, nullptr, message);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message);
+ }
+
+ return lineContinuationAllowed;
+}
+
+bool TParseContext::builtInName(const TString& identifier)
+{
+ return identifier.compare(0, 3, "gl_") == 0;
+}
+
+//
+// Make sure there is enough data and not too many arguments provided to the
+// constructor to build something of the type of the constructor. Also returns
+// the type of the constructor.
+//
+// Part of establishing type is establishing specialization-constness.
+// We don't yet know "top down" whether type is a specialization constant,
+// but a const constructor can becomes a specialization constant if any of
+// its children are, subject to KHR_vulkan_glsl rules:
+//
+// - int(), uint(), and bool() constructors for type conversions
+// from any of the following types to any of the following types:
+// * int
+// * uint
+// * bool
+// - vector versions of the above conversion constructors
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type)
+{
+ type.shallowCopy(function.getType());
+
+ bool constructingMatrix = false;
+ switch(op) {
+ case EOpConstructTextureSampler:
+ return constructorTextureSamplerError(loc, function);
+ case EOpConstructMat2x2:
+ case EOpConstructMat2x3:
+ case EOpConstructMat2x4:
+ case EOpConstructMat3x2:
+ case EOpConstructMat3x3:
+ case EOpConstructMat3x4:
+ case EOpConstructMat4x2:
+ case EOpConstructMat4x3:
+ case EOpConstructMat4x4:
+ case EOpConstructDMat2x2:
+ case EOpConstructDMat2x3:
+ case EOpConstructDMat2x4:
+ case EOpConstructDMat3x2:
+ case EOpConstructDMat3x3:
+ case EOpConstructDMat3x4:
+ case EOpConstructDMat4x2:
+ case EOpConstructDMat4x3:
+ case EOpConstructDMat4x4:
+ constructingMatrix = true;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Walk the arguments for first-pass checks and collection of information.
+ //
+
+ int size = 0;
+ bool constType = true;
+ bool specConstType = false; // value is only valid if constType is true
+ bool full = false;
+ bool overFull = false;
+ bool matrixInMatrix = false;
+ bool arrayArg = false;
+ bool floatArgument = false;
+ for (int arg = 0; arg < function.getParamCount(); ++arg) {
+ if (function[arg].type->isArray()) {
+ if (! function[arg].type->isExplicitlySizedArray()) {
+ // Can't construct from an unsized array.
+ error(loc, "array argument must be sized", "constructor", "");
+ return true;
+ }
+ arrayArg = true;
+ }
+ if (constructingMatrix && function[arg].type->isMatrix())
+ matrixInMatrix = true;
+
+ // 'full' will go to true when enough args have been seen. If we loop
+ // again, there is an extra argument.
+ if (full) {
+ // For vectors and matrices, it's okay to have too many components
+ // available, but not okay to have unused arguments.
+ overFull = true;
+ }
+
+ size += function[arg].type->computeNumComponents();
+ if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents())
+ full = true;
+
+ if (! function[arg].type->getQualifier().isConstant())
+ constType = false;
+ if (function[arg].type->getQualifier().isSpecConstant())
+ specConstType = true;
+ if (function[arg].type->isFloatingDomain())
+ floatArgument = true;
+ }
+
+ // inherit constness from children
+ if (constType) {
+ bool makeSpecConst;
+ // Finish pinning down spec-const semantics
+ if (specConstType) {
+ switch (op) {
+ case EOpConstructInt:
+ case EOpConstructUint:
+ case EOpConstructInt64:
+ case EOpConstructUint64:
+ case EOpConstructBool:
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructUVec2:
+ case EOpConstructUVec3:
+ case EOpConstructUVec4:
+ case EOpConstructI64Vec2:
+ case EOpConstructI64Vec3:
+ case EOpConstructI64Vec4:
+ case EOpConstructU64Vec2:
+ case EOpConstructU64Vec3:
+ case EOpConstructU64Vec4:
+ // This was the list of valid ones, if they aren't converting from float
+ // and aren't making an array.
+ makeSpecConst = ! floatArgument && ! type.isArray();
+ break;
+ default:
+ // anything else wasn't white-listed in the spec as a conversion
+ makeSpecConst = false;
+ break;
+ }
+ } else
+ makeSpecConst = false;
+
+ if (makeSpecConst)
+ type.getQualifier().makeSpecConstant();
+ else if (specConstType)
+ type.getQualifier().makeTemporary();
+ else
+ type.getQualifier().storage = EvqConst;
+ }
+
+ if (type.isArray()) {
+ if (function.getParamCount() == 0) {
+ error(loc, "array constructor must have at least one argument", "constructor", "");
+ return true;
+ }
+
+ if (type.isImplicitlySizedArray()) {
+ // auto adapt the constructor type to the number of arguments
+ type.changeOuterArraySize(function.getParamCount());
+ } else if (type.getOuterArraySize() != function.getParamCount()) {
+ error(loc, "array constructor needs one argument per array element", "constructor", "");
+ return true;
+ }
+
+ if (type.isArrayOfArrays()) {
+ // Types have to match, but we're still making the type.
+ // Finish making the type, and the comparison is done later
+ // when checking for conversion.
+ TArraySizes& arraySizes = type.getArraySizes();
+
+ // At least the dimensionalities have to match.
+ if (! function[0].type->isArray() || arraySizes.getNumDims() != function[0].type->getArraySizes().getNumDims() + 1) {
+ error(loc, "array constructor argument not correct type to construct array element", "constructior", "");
+ return true;
+ }
+
+ if (arraySizes.isInnerImplicit()) {
+ // "Arrays of arrays ..., and the size for any dimension is optional"
+ // That means we need to adopt (from the first argument) the other array sizes into the type.
+ for (int d = 1; d < arraySizes.getNumDims(); ++d) {
+ if (arraySizes.getDimSize(d) == UnsizedArraySize) {
+ arraySizes.setDimSize(d, function[0].type->getArraySizes().getDimSize(d - 1));
+ }
+ }
+ }
+ }
+ }
+
+ if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) {
+ error(loc, "constructing non-array constituent from array argument", "constructor", "");
+ return true;
+ }
+
+ if (matrixInMatrix && ! type.isArray()) {
+ profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix");
+
+ // "If a matrix argument is given to a matrix constructor,
+ // it is a compile-time error to have any other arguments."
+ if (function.getParamCount() != 1)
+ error(loc, "matrix constructed from matrix can only have one argument", "constructor", "");
+ return false;
+ }
+
+ if (overFull) {
+ error(loc, "too many arguments", "constructor", "");
+ return true;
+ }
+
+ if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) {
+ error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+ return true;
+ }
+
+ if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) ||
+ (op == EOpConstructStruct && size < type.computeNumComponents())) {
+ error(loc, "not enough data provided for construction", "constructor", "");
+ return true;
+ }
+
+ TIntermTyped* typed = node->getAsTyped();
+ if (typed == nullptr) {
+ error(loc, "constructor argument does not have a type", "constructor", "");
+ return true;
+ }
+ if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) {
+ error(loc, "cannot convert a sampler", "constructor", "");
+ return true;
+ }
+ if (op != EOpConstructStruct && typed->getBasicType() == EbtAtomicUint) {
+ error(loc, "cannot convert an atomic_uint", "constructor", "");
+ return true;
+ }
+ if (typed->getBasicType() == EbtVoid) {
+ error(loc, "cannot convert a void", "constructor", "");
+ return true;
+ }
+
+ return false;
+}
+
+// Verify all the correct semantics for constructing a combined texture/sampler.
+// Return true if the semantics are incorrect.
+bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function)
+{
+ TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change
+ const char* token = constructorName.c_str();
+
+ // exactly two arguments needed
+ if (function.getParamCount() != 2) {
+ error(loc, "sampler-constructor requires two arguments", token, "");
+ return true;
+ }
+
+ // For now, not allowing arrayed constructors, the rest of this function
+ // is set up to allow them, if this test is removed:
+ if (function.getType().isArray()) {
+ error(loc, "sampler-constructor cannot make an array of samplers", token, "");
+ return true;
+ }
+
+ // first argument
+ // * the constructor's first argument must be a texture type
+ // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array)
+ // of the texture type must match that of the constructed sampler type
+ // (that is, the suffixes of the type of the first argument and the
+ // type of the constructor will be spelled the same way)
+ if (function[0].type->getBasicType() != EbtSampler ||
+ ! function[0].type->getSampler().isTexture() ||
+ function[0].type->isArray()) {
+ error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, "");
+ return true;
+ }
+ // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=()
+ TSampler texture = function.getType().getSampler();
+ texture.combined = false;
+ texture.shadow = false;
+ if (texture != function[0].type->getSampler()) {
+ error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, "");
+ return true;
+ }
+
+ // second argument
+ // * the constructor's second argument must be a scalar of type
+ // *sampler* or *samplerShadow*
+ // * the presence or absence of depth comparison (Shadow) must match
+ // between the constructed sampler type and the type of the second argument
+ if ( function[1].type->getBasicType() != EbtSampler ||
+ ! function[1].type->getSampler().isPureSampler() ||
+ function[1].type->isArray()) {
+ error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, "");
+ return true;
+ }
+ if (function.getType().getSampler().shadow != function[1].type->getSampler().shadow) {
+ error(loc, "sampler-constructor second argument presence of shadow must match constructor presence of shadow", token, "");
+ return true;
+ }
+
+ return false;
+}
+
+// Checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType)
+{
+ if (basicType == EbtVoid) {
+ error(loc, "illegal use of type 'void'", identifier.c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+// Checks to see if the node (for the expression) contains a scalar boolean expression or not
+void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type)
+{
+ if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
+ error(loc, "boolean expression expected", "", "");
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType)
+{
+ if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1))
+ error(loc, "boolean expression expected", "", "");
+}
+
+void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/)
+{
+ if (type.getQualifier().storage == EvqUniform)
+ return;
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler))
+ error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
+ else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) {
+ // non-uniform sampler
+ // not yet: okay if it has an initializer
+ // if (! initializer)
+ error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
+ }
+}
+
+void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+{
+ if (type.getQualifier().storage == EvqUniform)
+ return;
+
+ if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint))
+ error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str());
+ else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform)
+ error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
+}
+
+void TParseContext::transparentCheck(const TSourceLoc& loc, const TType& type, const TString& /*identifier*/)
+{
+ // double standard due to gl_NumSamples
+ if (parsingBuiltins)
+ return;
+
+ // Vulkan doesn't allow transparent uniforms outside of blocks
+ if (vulkan == 0 || type.getQualifier().storage != EvqUniform)
+ return;
+ if (type.containsNonOpaque())
+ vulkanRemoved(loc, "non-opaque uniforms outside a block");
+}
+
+//
+// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
+//
+void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
+{
+ // move from parameter/unknown qualifiers to pipeline in/out qualifiers
+ switch (qualifier.storage) {
+ case EvqIn:
+ profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs");
+ profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs");
+ qualifier.storage = EvqVaryingIn;
+ break;
+ case EvqOut:
+ profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs");
+ profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs");
+ qualifier.storage = EvqVaryingOut;
+ break;
+ case EvqInOut:
+ qualifier.storage = EvqVaryingIn;
+ error(loc, "cannot use 'inout' at global scope", "", "");
+ break;
+ default:
+ break;
+ }
+
+ invariantCheck(loc, qualifier);
+}
+
+//
+// Check a full qualifier and type (no variable yet) at global level.
+//
+void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType)
+{
+ if (! symbolTable.atGlobalLevel())
+ return;
+
+ if (qualifier.isMemory() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer)
+ error(loc, "memory qualifiers cannot be used on this type", "", "");
+
+ if (qualifier.storage == EvqBuffer && publicType.basicType != EbtBlock)
+ error(loc, "buffers can be declared only as blocks", "buffer", "");
+
+ if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
+ return;
+
+ if (publicType.shaderQualifiers.blendEquation)
+ error(loc, "can only be applied to a standalone 'out'", "blend equation", "");
+
+ // now, knowing it is a shader in/out, do all the in/out semantic checks
+
+ if (publicType.basicType == EbtBool) {
+ error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+
+ if (publicType.basicType == EbtInt || publicType.basicType == EbtUint ||
+ publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 ||
+ publicType.basicType == EbtDouble)
+ profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
+
+ if (! qualifier.flat) {
+ if (publicType.basicType == EbtInt || publicType.basicType == EbtUint ||
+ publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 ||
+ publicType.basicType == EbtDouble ||
+ (publicType.userDef && (publicType.userDef->containsBasicType(EbtInt) ||
+ publicType.userDef->containsBasicType(EbtUint) ||
+ publicType.userDef->containsBasicType(EbtInt64) ||
+ publicType.userDef->containsBasicType(EbtUint64) ||
+ publicType.userDef->containsBasicType(EbtDouble)))) {
+ if (qualifier.storage == EvqVaryingIn && language == EShLangFragment)
+ error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage));
+ else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300)
+ error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage));
+ }
+ }
+
+ if (qualifier.patch && qualifier.isInterpolation())
+ error(loc, "cannot use interpolation qualifiers with patch", "patch", "");
+
+ if (qualifier.storage == EvqVaryingIn) {
+ switch (language) {
+ case EShLangVertex:
+ if (publicType.basicType == EbtStruct) {
+ error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+ if (publicType.arraySizes) {
+ requireProfile(loc, ~EEsProfile, "vertex input arrays");
+ profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
+ }
+ if (publicType.basicType == EbtDouble)
+ profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input");
+ if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)
+ error(loc, "vertex input cannot be further qualified", "", "");
+ break;
+
+ case EShLangTessControl:
+ if (qualifier.patch)
+ error(loc, "can only use on output in tessellation-control shader", "patch", "");
+ break;
+
+ case EShLangTessEvaluation:
+ break;
+
+ case EShLangGeometry:
+ break;
+
+ case EShLangFragment:
+ if (publicType.userDef) {
+ profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input");
+ profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input");
+ if (publicType.userDef->containsStructure())
+ requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure");
+ if (publicType.userDef->containsArray())
+ requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array");
+ }
+ break;
+
+ case EShLangCompute:
+ if (! symbolTable.atBuiltInLevel())
+ error(loc, "global storage input qualifier cannot be used in a compute shader", "in", "");
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ // qualifier.storage == EvqVaryingOut
+ switch (language) {
+ case EShLangVertex:
+ if (publicType.userDef) {
+ profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output");
+ profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output");
+ if (publicType.userDef->containsStructure())
+ requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure");
+ if (publicType.userDef->containsArray())
+ requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array");
+ }
+
+ break;
+
+ case EShLangTessControl:
+ break;
+
+ case EShLangTessEvaluation:
+ if (qualifier.patch)
+ error(loc, "can only use on input in tessellation-evaluation shader", "patch", "");
+ break;
+
+ case EShLangGeometry:
+ break;
+
+ case EShLangFragment:
+ profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output");
+ if (publicType.basicType == EbtStruct) {
+ error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+ if (publicType.matrixRows > 0) {
+ error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), "");
+ return;
+ }
+ if (qualifier.isAuxiliary())
+ error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", "");
+ if (qualifier.isInterpolation())
+ error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", "");
+ if (publicType.basicType == EbtDouble)
+ error(loc, "cannot contain a double", GetStorageQualifierString(qualifier.storage), "");
+ break;
+
+ case EShLangCompute:
+ error(loc, "global storage output qualifier cannot be used in a compute shader", "out", "");
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+//
+// Merge characteristics of the 'src' qualifier into the 'dst'.
+// If there is duplication, issue error messages, unless 'force'
+// is specified, which means to just override default settings.
+//
+// Also, when force is false, it will be assumed that 'src' follows
+// 'dst', for the purpose of error checking order for versions
+// that require specific orderings of qualifiers.
+//
+void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force)
+{
+ // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers')
+ if (src.isAuxiliary() && dst.isAuxiliary())
+ error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", "");
+
+ // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers')
+ if (src.isInterpolation() && dst.isInterpolation())
+ error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", "");
+
+ // Ordering
+ if (! force && ((profile != EEsProfile && version < 420) ||
+ (profile == EEsProfile && version < 310))
+ && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) {
+ // non-function parameters
+ if (src.noContraction && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "precise qualifier must appear first", "", "");
+ if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", "");
+ else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", "");
+ else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone))
+ error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", "");
+ else if (src.storage != EvqTemporary && (dst.precision != EpqNone))
+ error(loc, "precision qualifier must appear as last qualifier", "", "");
+
+ // function parameters
+ if (src.noContraction && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut))
+ error(loc, "precise qualifier must appear first", "", "");
+ if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut))
+ error(loc, "in/out must appear before const", "", "");
+ }
+
+ // Storage qualification
+ if (dst.storage == EvqTemporary || dst.storage == EvqGlobal)
+ dst.storage = src.storage;
+ else if ((dst.storage == EvqIn && src.storage == EvqOut) ||
+ (dst.storage == EvqOut && src.storage == EvqIn))
+ dst.storage = EvqInOut;
+ else if ((dst.storage == EvqIn && src.storage == EvqConst) ||
+ (dst.storage == EvqConst && src.storage == EvqIn))
+ dst.storage = EvqConstReadOnly;
+ else if (src.storage != EvqTemporary &&
+ src.storage != EvqGlobal)
+ error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), "");
+
+ // Precision qualifiers
+ if (! force && src.precision != EpqNone && dst.precision != EpqNone)
+ error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), "");
+ if (dst.precision == EpqNone || (force && src.precision != EpqNone))
+ dst.precision = src.precision;
+
+ // Layout qualifiers
+ mergeObjectLayoutQualifiers(dst, src, false);
+
+ // individual qualifiers
+ bool repeated = false;
+ #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field;
+ MERGE_SINGLETON(invariant);
+ MERGE_SINGLETON(noContraction);
+ MERGE_SINGLETON(centroid);
+ MERGE_SINGLETON(smooth);
+ MERGE_SINGLETON(flat);
+ MERGE_SINGLETON(nopersp);
+ MERGE_SINGLETON(patch);
+ MERGE_SINGLETON(sample);
+ MERGE_SINGLETON(coherent);
+ MERGE_SINGLETON(volatil);
+ MERGE_SINGLETON(restrict);
+ MERGE_SINGLETON(readonly);
+ MERGE_SINGLETON(writeonly);
+ MERGE_SINGLETON(specConstant);
+
+ if (repeated)
+ error(loc, "replicated qualifiers", "", "");
+}
+
+void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier)
+{
+ TBasicType basicType = publicType.basicType;
+
+ if (basicType == EbtSampler) {
+ defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier;
+
+ return; // all is well
+ }
+
+ if (basicType == EbtInt || basicType == EbtFloat) {
+ if (publicType.isScalar()) {
+ defaultPrecision[basicType] = qualifier;
+ if (basicType == EbtInt)
+ defaultPrecision[EbtUint] = qualifier;
+
+ return; // all is well
+ }
+ }
+
+ if (basicType == EbtAtomicUint) {
+ if (qualifier != EpqHigh)
+ error(loc, "can only apply highp to atomic_uint", "precision", "");
+
+ return;
+ }
+
+ error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), "");
+}
+
+// used to flatten the sampler type space into a single dimension
+// correlates with the declaration of defaultSamplerPrecision[]
+int TParseContext::computeSamplerTypeIndex(TSampler& sampler)
+{
+ int arrayIndex = sampler.arrayed ? 1 : 0;
+ int shadowIndex = sampler.shadow ? 1 : 0;
+ int externalIndex = sampler.external ? 1 : 0;
+
+ return EsdNumDims * (EbtNumTypes * (2 * (2 * arrayIndex + shadowIndex) + externalIndex) + sampler.type) + sampler.dim;
+}
+
+TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType)
+{
+ if (publicType.basicType == EbtSampler)
+ return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)];
+ else
+ return defaultPrecision[publicType.basicType];
+}
+
+void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier)
+{
+ // Built-in symbols are allowed some ambiguous precisions, to be pinned down
+ // later by context.
+ if (profile != EEsProfile || parsingBuiltins)
+ return;
+
+ if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh)
+ error(loc, "atomic counters can only be highp", "atomic_uint", "");
+
+ if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) {
+ if (qualifier.precision == EpqNone) {
+ if (relaxedErrors())
+ warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'");
+ else
+ error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "");
+ qualifier.precision = EpqMedium;
+ defaultPrecision[baseType] = EpqMedium;
+ }
+ } else if (qualifier.precision != EpqNone)
+ error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), "");
+}
+
+void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type)
+{
+ if ((qualifier == EvqOut || qualifier == EvqInOut) && (type.getBasicType() == EbtSampler || type.getBasicType() == EbtAtomicUint))
+ error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), "");
+}
+
+bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType)
+{
+ if (type.getBasicType() == basicType)
+ return true;
+
+ if (type.getBasicType() == EbtStruct) {
+ const TTypeList& structure = *type.getStruct();
+ for (unsigned int i = 0; i < structure.size(); ++i) {
+ if (containsFieldWithBasicType(*structure[i].type, basicType))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//
+// Do size checking for an array type's size.
+//
+void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair)
+{
+ bool isConst = false;
+ sizePair.node = nullptr;
+
+ int size = 1;
+
+ TIntermConstantUnion* constant = expr->getAsConstantUnion();
+ if (constant) {
+ // handle true (non-specialization) constant
+ size = constant->getConstArray()[0].getIConst();
+ isConst = true;
+ } else {
+ // see if it's a specialization constant instead
+ if (expr->getQualifier().isSpecConstant()) {
+ isConst = true;
+ sizePair.node = expr;
+ TIntermSymbol* symbol = expr->getAsSymbolNode();
+ if (symbol && symbol->getConstArray().size() > 0)
+ size = symbol->getConstArray()[0].getIConst();
+ }
+ }
+
+ sizePair.size = size;
+
+ if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) {
+ error(loc, "array size must be a constant integer expression", "", "");
+ return;
+ }
+
+ if (size <= 0) {
+ error(loc, "array size must be a positive integer", "", "");
+ return;
+ }
+}
+
+//
+// See if this qualifier can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ if (qualifier.storage == EvqConst) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array");
+ profileRequires(loc, EEsProfile, 300, nullptr, "const array");
+ }
+
+ if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) {
+ requireProfile(loc, ~EEsProfile, "vertex input arrays");
+ profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
+ }
+
+ return false;
+}
+
+//
+// See if this qualifier and type combination can be an array.
+// Assumes arrayQualifierError() was also called to catch the type-invariant tests.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type)
+{
+ if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) {
+ if (type.isArrayOfArrays())
+ requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output");
+ else if (type.isStruct())
+ requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output");
+ }
+ if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) {
+ if (type.isArrayOfArrays())
+ requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input");
+ else if (type.isStruct())
+ requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input");
+ }
+ if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) {
+ if (type.isArrayOfArrays())
+ requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output");
+ }
+
+ return false;
+}
+
+//
+// Require array to be completely sized
+//
+void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes)
+{
+ if (arraySizes.isImplicit())
+ error(loc, "array size required", "", "");
+}
+
+void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type)
+{
+ const TTypeList& structure = *type.getStruct();
+ for (int m = 0; m < (int)structure.size(); ++m) {
+ const TType& member = *structure[m].type;
+ if (member.isArray())
+ arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes());
+ }
+}
+
+void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember)
+{
+ assert(arraySizes);
+
+ // always allow special built-in ins/outs sized to topologies
+ if (parsingBuiltins)
+ return;
+
+ // always allow an initializer to set any unknown array sizes
+ if (initializer)
+ return;
+
+ // No environment lets any non-outer-dimension that's to be implicitly sized
+ if (arraySizes->isInnerImplicit())
+ error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
+
+ // desktop always allows outer-dimension-unsized variable arrays,
+ if (profile != EEsProfile)
+ return;
+
+ // for ES, if size isn't coming from an initializer, it has to be explicitly declared now,
+ // with very few exceptions
+
+ // last member of ssbo block exception:
+ if (qualifier.storage == EvqBuffer && lastMember)
+ return;
+
+ // implicitly-sized io exceptions:
+ switch (language) {
+ case EShLangGeometry:
+ if (qualifier.storage == EvqVaryingIn)
+ if (extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader))
+ return;
+ break;
+ case EShLangTessControl:
+ if ( qualifier.storage == EvqVaryingIn ||
+ (qualifier.storage == EvqVaryingOut && ! qualifier.patch))
+ if (extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
+ return;
+ break;
+ case EShLangTessEvaluation:
+ if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) ||
+ qualifier.storage == EvqVaryingOut)
+ if (extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))
+ return;
+ break;
+ default:
+ break;
+ }
+
+ arraySizeRequiredCheck(loc, *arraySizes);
+}
+
+void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc)
+{
+ const char* feature = "arrays of arrays";
+
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature);
+}
+
+void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TArraySizes* sizes1, const TArraySizes* sizes2)
+{
+ if ((sizes1 && sizes2) ||
+ (sizes1 && sizes1->getNumDims() > 1) ||
+ (sizes2 && sizes2->getNumDims() > 1))
+ arrayOfArrayVersionCheck(loc);
+}
+
+void TParseContext::arrayDimCheck(const TSourceLoc& loc, const TType* type, const TArraySizes* sizes2)
+{
+ // skip checking for multiple dimensions on the type; it was caught earlier
+ if ((type && type->isArray() && sizes2) ||
+ (sizes2 && sizes2->getNumDims() > 1))
+ arrayOfArrayVersionCheck(loc);
+}
+
+// Merge array dimensions listed in 'sizes' onto the type's array dimensions.
+//
+// From the spec: "vec4[2] a[3]; // size-3 array of size-2 array of vec4"
+//
+// That means, the 'sizes' go in front of the 'type' as outermost sizes.
+// 'type' is the type part of the declaration (to the left)
+// 'sizes' is the arrayness tagged on the identifier (to the right)
+//
+void TParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
+{
+ if (sizes)
+ type.addArrayOuterSizes(*sizes);
+}
+
+//
+// Do all the semantic checking for declaring or redeclaring an array, with and
+// without a size, and make the right changes to the symbol table.
+//
+void TParseContext::declareArray(const TSourceLoc& loc, TString& identifier, const TType& type, TSymbol*& symbol, bool& newDeclaration)
+{
+ if (! symbol) {
+ bool currentScope;
+ symbol = symbolTable.find(identifier, nullptr, &currentScope);
+
+ if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) {
+ // bad shader (errors already reported) trying to redeclare a built-in name as an array
+ return;
+ }
+ if (symbol == nullptr || ! currentScope) {
+ //
+ // Successfully process a new definition.
+ // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations)
+ //
+ symbol = new TVariable(&identifier, type);
+ symbolTable.insert(*symbol);
+ newDeclaration = true;
+
+ if (! symbolTable.atBuiltInLevel()) {
+ if (isIoResizeArray(type)) {
+ ioArraySymbolResizeList.push_back(symbol);
+ checkIoArraysConsistency(loc, true);
+ } else
+ fixIoArraySize(loc, symbol->getWritableType());
+ }
+
+ return;
+ }
+ if (symbol->getAsAnonMember()) {
+ error(loc, "cannot redeclare a user-block member array", identifier.c_str(), "");
+ symbol = nullptr;
+ return;
+ }
+ }
+
+ //
+ // Process a redeclaration.
+ //
+
+ if (! symbol) {
+ error(loc, "array variable name expected", identifier.c_str(), "");
+ return;
+ }
+
+ // redeclareBuiltinVariable() should have already done the copyUp()
+ TType& existingType = symbol->getWritableType();
+
+ if (! existingType.isArray()) {
+ error(loc, "redeclaring non-array as array", identifier.c_str(), "");
+ return;
+ }
+
+ if (! existingType.sameElementType(type)) {
+ error(loc, "redeclaration of array with a different element type", identifier.c_str(), "");
+ return;
+ }
+
+ if (! existingType.sameInnerArrayness(type)) {
+ error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), "");
+ return;
+ }
+
+ if (existingType.isExplicitlySizedArray()) {
+ // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
+ if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize()))
+ error(loc, "redeclaration of array with size", identifier.c_str(), "");
+ return;
+ }
+
+ arrayLimitCheck(loc, identifier, type.getOuterArraySize());
+
+ existingType.updateArraySizes(type);
+
+ if (isIoResizeArray(type))
+ checkIoArraysConsistency(loc);
+}
+
+void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode *node, int index)
+{
+ // maybe there is nothing to do...
+ TIntermTyped* typedNode = node->getAsTyped();
+ if (typedNode->getType().getImplicitArraySize() > index)
+ return;
+
+ // something to do...
+
+ // Figure out what symbol to lookup, as we will use its type to edit for the size change,
+ // as that type will be shared through shallow copies for future references.
+ TSymbol* symbol = nullptr;
+ int blockIndex = -1;
+ const TString* lookupName = nullptr;
+ if (node->getAsSymbolNode())
+ lookupName = &node->getAsSymbolNode()->getName();
+ else if (node->getAsBinaryNode()) {
+ const TIntermBinary* deref = node->getAsBinaryNode();
+ // This has to be the result of a block dereference, unless it's bad shader code
+ // If it's a uniform block, then an error will be issued elsewhere, but
+ // return early now to avoid crashing later in this function.
+ if (deref->getLeft()->getBasicType() != EbtBlock ||
+ deref->getLeft()->getType().getQualifier().storage == EvqUniform ||
+ deref->getRight()->getAsConstantUnion() == nullptr)
+ return;
+
+ const TIntermTyped* left = deref->getLeft();
+ const TIntermTyped* right = deref->getRight();
+
+ if (left->getAsBinaryNode()) {
+ left = left->getAsBinaryNode()->getLeft(); // Block array access
+ assert(left->isArray());
+ }
+
+ if (! left->getAsSymbolNode())
+ return;
+
+ blockIndex = right->getAsConstantUnion()->getConstArray()[0].getIConst();
+
+ lookupName = &left->getAsSymbolNode()->getName();
+ if (IsAnonymous(*lookupName))
+ lookupName = &(*left->getType().getStruct())[blockIndex].type->getFieldName();
+ }
+
+ // Lookup the symbol, should only fail if shader code is incorrect
+ symbol = symbolTable.find(*lookupName);
+ if (symbol == nullptr)
+ return;
+
+ if (symbol->getAsFunction()) {
+ error(loc, "array variable name expected", symbol->getName().c_str(), "");
+ return;
+ }
+
+ if (symbol->getType().isStruct() && blockIndex != -1)
+ (*symbol->getWritableType().getStruct())[blockIndex].type->setImplicitArraySize(index + 1);
+ else
+ symbol->getWritableType().setImplicitArraySize(index + 1);
+}
+
+// Returns true if the first argument to the #line directive is the line number for the next line.
+//
+// Desktop, pre-version 3.30: "After processing this directive
+// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and
+// source string number source-string-number."
+//
+// Desktop, version 3.30 and later, and ES: "After processing this directive
+// (including its new-line), the implementation will behave as if it is compiling at line number line and
+// source string number source-string-number.
+bool TParseContext::lineDirectiveShouldSetNextLine() const
+{
+ return profile == EEsProfile || version >= 330;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type)
+{
+ //
+ // Make the qualifier make sense, given that there is an initializer.
+ //
+ if (type.getQualifier().storage == EvqConst ||
+ type.getQualifier().storage == EvqConstReadOnly) {
+ type.getQualifier().makeTemporary();
+ error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
+ }
+}
+
+//
+// See if the identifier is a built-in symbol that can be redeclared, and if so,
+// copy the symbol table's read-only built-in variable to the current
+// global level, where it can be modified based on the passed in type.
+//
+// Returns nullptr if no redeclaration took place; meaning a normal declaration still
+// needs to occur for it, not necessarily an error.
+//
+// Returns a redeclared and type-modified variable if a redeclarated occurred.
+//
+TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier, const TQualifier& qualifier, const TShaderQualifiers& publicType, bool& newDeclaration)
+{
+ if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel())
+ return nullptr;
+
+ bool nonEsRedecls = (profile != EEsProfile && (version >= 130 || identifier == "gl_TexCoord"));
+ bool esRedecls = (profile == EEsProfile && extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks));
+ if (! esRedecls && ! nonEsRedecls)
+ return nullptr;
+
+ // Special case when using GL_ARB_separate_shader_objects
+ bool ssoPre150 = false; // means the only reason this variable is redeclared is due to this combination
+ if (profile != EEsProfile && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) {
+ if (identifier == "gl_Position" ||
+ identifier == "gl_PointSize" ||
+ identifier == "gl_ClipVertex" ||
+ identifier == "gl_FogFragCoord")
+ ssoPre150 = true;
+ }
+
+ // Potentially redeclaring a built-in variable...
+
+ if (ssoPre150 ||
+ (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) ||
+ (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) ||
+ identifier == "gl_ClipDistance" ||
+ identifier == "gl_CullDistance" ||
+ identifier == "gl_FrontColor" ||
+ identifier == "gl_BackColor" ||
+ identifier == "gl_FrontSecondaryColor" ||
+ identifier == "gl_BackSecondaryColor" ||
+ identifier == "gl_SecondaryColor" ||
+ (identifier == "gl_Color" && language == EShLangFragment) ||
+ identifier == "gl_TexCoord") {
+
+ // Find the existing symbol, if any.
+ bool builtIn;
+ TSymbol* symbol = symbolTable.find(identifier, &builtIn);
+
+ // If the symbol was not found, this must be a version/profile/stage
+ // that doesn't have it.
+ if (! symbol)
+ return nullptr;
+
+ // If it wasn't at a built-in level, then it's already been redeclared;
+ // that is, this is a redeclaration of a redeclaration; reuse that initial
+ // redeclaration. Otherwise, make the new one.
+ if (builtIn) {
+ // Copy the symbol up to make a writable version
+ makeEditable(symbol);
+ newDeclaration = true;
+ }
+
+ // Now, modify the type of the copy, as per the type of the current redeclaration.
+
+ TQualifier& symbolQualifier = symbol->getWritableType().getQualifier();
+ if (ssoPre150) {
+ if (intermediate.inIoAccessed(identifier))
+ error(loc, "cannot redeclare after use", identifier.c_str(), "");
+ if (qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
+ if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex && qualifier.storage != EvqVaryingOut) ||
+ (language == EShLangFragment && qualifier.storage != EvqVaryingIn))
+ error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str());
+ if (! qualifier.smooth)
+ error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str());
+ } else if (identifier == "gl_FrontColor" ||
+ identifier == "gl_BackColor" ||
+ identifier == "gl_FrontSecondaryColor" ||
+ identifier == "gl_BackSecondaryColor" ||
+ identifier == "gl_SecondaryColor" ||
+ identifier == "gl_Color") {
+ symbolQualifier.flat = qualifier.flat;
+ symbolQualifier.smooth = qualifier.smooth;
+ symbolQualifier.nopersp = qualifier.nopersp;
+ if (qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str());
+ if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage)
+ error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str());
+ } else if (identifier == "gl_TexCoord" ||
+ identifier == "gl_ClipDistance" ||
+ identifier == "gl_CullDistance") {
+ if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() ||
+ qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
+ symbolQualifier.storage != qualifier.storage)
+ error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str());
+ } else if (identifier == "gl_FragCoord") {
+ if (intermediate.inIoAccessed("gl_FragCoord"))
+ error(loc, "cannot redeclare after use", "gl_FragCoord", "");
+ if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
+ qualifier.isMemory() || qualifier.isAuxiliary())
+ error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
+ if (qualifier.storage != EvqVaryingIn)
+ error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str());
+ if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() ||
+ publicType.originUpperLeft != intermediate.getOriginUpperLeft()))
+ error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str());
+ if (publicType.pixelCenterInteger)
+ intermediate.setPixelCenterInteger();
+ if (publicType.originUpperLeft)
+ intermediate.setOriginUpperLeft();
+ } else if (identifier == "gl_FragDepth") {
+ if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat ||
+ qualifier.isMemory() || qualifier.isAuxiliary())
+ error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str());
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str());
+ if (publicType.layoutDepth != EldNone) {
+ if (intermediate.inIoAccessed("gl_FragDepth"))
+ error(loc, "cannot redeclare after use", "gl_FragDepth", "");
+ if (! intermediate.setDepth(publicType.layoutDepth))
+ error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str());
+ }
+
+ }
+ // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above
+
+ return symbol;
+ }
+
+ return nullptr;
+}
+
+//
+// Either redeclare the requested block, or give an error message why it can't be done.
+//
+// TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size
+void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
+{
+ const char* feature = "built-in block redeclaration";
+ profileRequires(loc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
+ profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
+
+ if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment") {
+ error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str());
+ return;
+ }
+
+ // Redeclaring a built-in block...
+
+ if (instanceName && ! builtInName(*instanceName)) {
+ error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
+ return;
+ }
+
+ // Blocks with instance names are easy to find, lookup the instance name,
+ // Anonymous blocks need to be found via a member.
+ bool builtIn;
+ TSymbol* block;
+ if (instanceName)
+ block = symbolTable.find(*instanceName, &builtIn);
+ else
+ block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn);
+
+ // If the block was not found, this must be a version/profile/stage
+ // that doesn't have it, or the instance name is wrong.
+ const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str();
+ if (! block) {
+ error(loc, "no declaration found for redeclaration", errorName, "");
+ return;
+ }
+ // Built-in blocks cannot be redeclared more than once, which if happened,
+ // we'd be finding the already redeclared one here, rather than the built in.
+ if (! builtIn) {
+ error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), "");
+ return;
+ }
+
+ // Copy the block to make a writable version, to insert into the block table after editing.
+ block = symbolTable.copyUpDeferredInsert(block);
+
+ if (block->getType().getBasicType() != EbtBlock) {
+ error(loc, "cannot redeclare a non block as a block", errorName, "");
+ return;
+ }
+
+ // Edit and error check the container against the redeclaration
+ // - remove unused members
+ // - ensure remaining qualifiers/types match
+ TType& type = block->getWritableType();
+ TTypeList::iterator member = type.getWritableStruct()->begin();
+ size_t numOriginalMembersFound = 0;
+ while (member != type.getStruct()->end()) {
+ // look for match
+ bool found = false;
+ TTypeList::const_iterator newMember;
+ TSourceLoc memberLoc;
+ memberLoc.init();
+ for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) {
+ if (member->type->getFieldName() == newMember->type->getFieldName()) {
+ found = true;
+ memberLoc = newMember->loc;
+ break;
+ }
+ }
+
+ if (found) {
+ ++numOriginalMembersFound;
+ // - ensure match between redeclared members' types
+ // - check for things that can't be changed
+ // - update things that can be changed
+ TType& oldType = *member->type;
+ const TType& newType = *newMember->type;
+ if (! newType.sameElementType(oldType))
+ error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), "");
+ if (oldType.isArray() != newType.isArray())
+ error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (! oldType.sameArrayness(newType) && oldType.isExplicitlySizedArray())
+ error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), "");
+ else if (newType.isArray())
+ arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize());
+ if (newType.getQualifier().isMemory())
+ error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
+ if (newType.getQualifier().hasLayout())
+ error(memberLoc, "cannot add layout to redeclared block member", member->type->getFieldName().c_str(), "");
+ if (newType.getQualifier().patch)
+ error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), "");
+ oldType.getQualifier().centroid = newType.getQualifier().centroid;
+ oldType.getQualifier().sample = newType.getQualifier().sample;
+ oldType.getQualifier().invariant = newType.getQualifier().invariant;
+ oldType.getQualifier().noContraction = newType.getQualifier().noContraction;
+ oldType.getQualifier().smooth = newType.getQualifier().smooth;
+ oldType.getQualifier().flat = newType.getQualifier().flat;
+ oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
+
+ if (oldType.isImplicitlySizedArray() && newType.isExplicitlySizedArray())
+ oldType.changeOuterArraySize(newType.getOuterArraySize());
+
+ // go to next member
+ ++member;
+ } else {
+ // For missing members of anonymous blocks that have been redeclared,
+ // hide the original (shared) declaration.
+ // Instance-named blocks can just have the member removed.
+ if (instanceName)
+ member = type.getWritableStruct()->erase(member);
+ else {
+ member->type->hideMember();
+ ++member;
+ }
+ }
+ }
+
+ if (numOriginalMembersFound < newTypeList.size())
+ error(loc, "block redeclaration has extra members", blockName.c_str(), "");
+ if (type.isArray() != (arraySizes != nullptr))
+ error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), "");
+ else if (type.isArray()) {
+ if (type.isExplicitlySizedArray() && arraySizes->getOuterSize() == UnsizedArraySize)
+ error(loc, "block already declared with size, can't redeclare as implicitly-sized", blockName.c_str(), "");
+ else if (type.isExplicitlySizedArray() && type.getArraySizes() != *arraySizes)
+ error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
+ else if (type.isImplicitlySizedArray() && arraySizes->getOuterSize() != UnsizedArraySize)
+ type.changeOuterArraySize(arraySizes->getOuterSize());
+ }
+
+ symbolTable.insert(*block);
+
+ // Check for general layout qualifier errors
+ layoutObjectCheck(loc, *block);
+
+ // Tracking for implicit sizing of array
+ if (isIoResizeArray(block->getType())) {
+ ioArraySymbolResizeList.push_back(block);
+ checkIoArraysConsistency(loc, true);
+ } else if (block->getType().isArray())
+ fixIoArraySize(loc, block->getWritableType());
+
+ // Save it in the AST for linker use.
+ intermediate.addSymbolLinkageNode(linkage, *block);
+}
+
+void TParseContext::paramCheckFix(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type)
+{
+ switch (qualifier) {
+ case EvqConst:
+ case EvqConstReadOnly:
+ type.getQualifier().storage = EvqConstReadOnly;
+ break;
+ case EvqIn:
+ case EvqOut:
+ case EvqInOut:
+ type.getQualifier().storage = qualifier;
+ break;
+ case EvqGlobal:
+ case EvqTemporary:
+ type.getQualifier().storage = EvqIn;
+ break;
+ default:
+ type.getQualifier().storage = EvqIn;
+ error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), "");
+ break;
+ }
+}
+
+void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type)
+{
+ if (qualifier.isMemory()) {
+ type.getQualifier().volatil = qualifier.volatil;
+ type.getQualifier().coherent = qualifier.coherent;
+ type.getQualifier().readonly = qualifier.readonly;
+ type.getQualifier().writeonly = qualifier.writeonly;
+ type.getQualifier().restrict = qualifier.restrict;
+ }
+
+ if (qualifier.isAuxiliary() ||
+ qualifier.isInterpolation())
+ error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", "");
+ if (qualifier.hasLayout())
+ error(loc, "cannot use layout qualifiers on a function parameter", "", "");
+ if (qualifier.invariant)
+ error(loc, "cannot use invariant qualifier on a function parameter", "", "");
+ if (qualifier.noContraction) {
+ if (qualifier.storage == EvqOut || qualifier.storage == EvqInOut)
+ type.getQualifier().noContraction = true;
+ else
+ warn(loc, "qualifier has no effect on non-output parameters", "precise", "");
+ }
+
+ paramCheckFix(loc, qualifier.storage, type);
+}
+
+void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
+{
+ if (structNestingLevel > 0)
+ error(loc, "cannot nest a block definition inside a structure or block", "", "");
+ ++structNestingLevel;
+}
+
+void TParseContext::nestedStructCheck(const TSourceLoc& loc)
+{
+ if (structNestingLevel > 0)
+ error(loc, "cannot nest a structure definition inside a structure or block", "", "");
+ ++structNestingLevel;
+}
+
+void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+ // Some versions don't allow comparing arrays or structures containing arrays
+ if (type.containsArray()) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op);
+ profileRequires(loc, EEsProfile, 300, nullptr, op);
+ }
+}
+
+void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+ if (containsFieldWithBasicType(type, EbtSampler))
+ error(loc, "can't use with samplers or structs containing samplers", op, "");
+}
+
+void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op)
+{
+ if (type.containsSpecializationSize())
+ error(loc, "can't use with types containing arrays sized with a specialization constant", op, "");
+}
+
+void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType)
+{
+ const TTypeList& typeList = *publicType.userDef->getStruct();
+
+ // fix and check for member storage qualifiers and types that don't belong within a structure
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ if (memberQualifier.isAuxiliary() ||
+ memberQualifier.isInterpolation() ||
+ (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal))
+ error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.isMemory())
+ error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.hasLayout()) {
+ error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
+ memberQualifier.clearLayout();
+ }
+ if (memberQualifier.invariant)
+ error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), "");
+ }
+}
+
+//
+// See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A:
+//
+// "The loop index has type int or float.
+//
+// "The for statement has the form:
+// for ( init-declaration ; condition ; expression )
+// init-declaration has the form: type-specifier identifier = constant-expression
+// condition has the form: loop-index relational_operator constant-expression
+// where relational_operator is one of: > >= < <= == or !=
+// expression [sic] has one of the following forms:
+// loop-index++
+// loop-index--
+// loop-index += constant-expression
+// loop-index -= constant-expression
+//
+// The body is handled in an AST traversal.
+//
+void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop)
+{
+ // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration
+ bool badInit = false;
+ if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1)
+ badInit = true;
+ TIntermBinary* binaryInit = 0;
+ if (! badInit) {
+ // get the declaration assignment
+ binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode();
+ if (! binaryInit)
+ badInit = true;
+ }
+ if (badInit) {
+ error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // loop index must be type int or float
+ if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) {
+ error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", "");
+ return;
+ }
+
+ // init is the form "loop-index = constant"
+ if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) {
+ error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // get the unique id of the loop index
+ int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
+ inductiveLoopIds.insert(loopIndex);
+
+ // condition's form must be "loop-index relational-operator constant-expression"
+ bool badCond = ! loop->getTest();
+ if (! badCond) {
+ TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode();
+ badCond = ! binaryCond;
+ if (! badCond) {
+ switch (binaryCond->getOp()) {
+ case EOpGreaterThan:
+ case EOpGreaterThanEqual:
+ case EOpLessThan:
+ case EOpLessThanEqual:
+ case EOpEqual:
+ case EOpNotEqual:
+ break;
+ default:
+ badCond = true;
+ }
+ }
+ if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() ||
+ binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
+ ! binaryCond->getRight()->getAsConstantUnion()))
+ badCond = true;
+ }
+ if (badCond) {
+ error(loc, "inductive-loop condition requires the form \"loop-index <comparison-op> constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // loop-index++
+ // loop-index--
+ // loop-index += constant-expression
+ // loop-index -= constant-expression
+ bool badTerminal = ! loop->getTerminal();
+ if (! badTerminal) {
+ TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode();
+ TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode();
+ if (unaryTerminal || binaryTerminal) {
+ switch(loop->getTerminal()->getAsOperator()->getOp()) {
+ case EOpPostDecrement:
+ case EOpPostIncrement:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ break;
+ default:
+ badTerminal = true;
+ }
+ } else
+ badTerminal = true;
+ if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() ||
+ binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
+ ! binaryTerminal->getRight()->getAsConstantUnion()))
+ badTerminal = true;
+ if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() ||
+ unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex))
+ badTerminal = true;
+ }
+ if (badTerminal) {
+ error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", "");
+ return;
+ }
+
+ // the body
+ inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
+}
+
+// Do limit checks for built-in arrays.
+void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size)
+{
+ if (identifier.compare("gl_TexCoord") == 0)
+ limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size");
+ else if (identifier.compare("gl_ClipDistance") == 0)
+ limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size");
+ else if (identifier.compare("gl_CullDistance") == 0)
+ limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size");
+}
+
+// See if the provided value is less than the symbol indicated by limit,
+// which should be a constant in the symbol table.
+void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature)
+{
+ TSymbol* symbol = symbolTable.find(limit);
+ assert(symbol->getAsVariable());
+ const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray();
+ assert(! constArray.empty());
+ if (value >= constArray[0].getIConst())
+ error(loc, "must be less than", feature, "%s (%d)", limit, constArray[0].getIConst());
+}
+
+//
+// Do any additional error checking, etc., once we know the parsing is done.
+//
+void TParseContext::finalErrorCheck()
+{
+ // Check on array indexes for ES 2.0 (version 100) limitations.
+ for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i)
+ constantIndexExpressionCheck(needsIndexLimitationChecking[i]);
+
+ // Check for stages that are enabled by extension.
+ // Can't do this at the beginning, it is chicken and egg to add a stage by
+ // extension.
+ // Stage-specific features were correctly tested for already, this is just
+ // about the stage itself.
+ switch (language) {
+ case EShLangGeometry:
+ if (profile == EEsProfile && version == 310)
+ requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders");
+ break;
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ if (profile == EEsProfile && version == 310)
+ requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders");
+ else if (profile != EEsProfile && version < 400)
+ requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders");
+ break;
+ case EShLangCompute:
+ if (profile != EEsProfile && version < 430)
+ requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders");
+ break;
+ default:
+ break;
+ }
+}
+
+//
+// Layout qualifier stuff.
+//
+
+// Put the id's layout qualification into the public type, for qualifiers not having a number set.
+// This is before we know any type information for error checking.
+void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id)
+{
+ std::transform(id.begin(), id.end(), id.begin(), ::tolower);
+
+ if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) {
+ publicType.qualifier.layoutMatrix = ElmColumnMajor;
+ return;
+ }
+ if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) {
+ publicType.qualifier.layoutMatrix = ElmRowMajor;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
+ if (vulkan > 0)
+ vulkanRemoved(loc, "packed");
+ publicType.qualifier.layoutPacking = ElpPacked;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpShared)) {
+ if (vulkan > 0)
+ vulkanRemoved(loc, "shared");
+ publicType.qualifier.layoutPacking = ElpShared;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpStd140)) {
+ publicType.qualifier.layoutPacking = ElpStd140;
+ return;
+ }
+ if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430");
+ profileRequires(loc, EEsProfile, 310, nullptr, "std430");
+ publicType.qualifier.layoutPacking = ElpStd430;
+ return;
+ }
+ // TODO: compile-time performance: may need to stop doing linear searches
+ for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) {
+ if (id == TQualifier::getLayoutFormatString(format)) {
+ if ((format > ElfEsFloatGuard && format < ElfFloatGuard) ||
+ (format > ElfEsIntGuard && format < ElfIntGuard) ||
+ (format > ElfEsUintGuard && format < ElfCount))
+ requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format");
+ profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store");
+ profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store");
+ publicType.qualifier.layoutFormat = format;
+ return;
+ }
+ }
+ if (id == "push_constant") {
+ requireVulkan(loc, "push_constant");
+ publicType.qualifier.layoutPushConstant = true;
+ return;
+ }
+ if (language == EShLangGeometry || language == EShLangTessEvaluation) {
+ if (id == TQualifier::getGeometryString(ElgTriangles)) {
+ publicType.shaderQualifiers.geometry = ElgTriangles;
+ return;
+ }
+ if (language == EShLangGeometry) {
+ if (id == TQualifier::getGeometryString(ElgPoints)) {
+ publicType.shaderQualifiers.geometry = ElgPoints;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgLineStrip)) {
+ publicType.shaderQualifiers.geometry = ElgLineStrip;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgLines)) {
+ publicType.shaderQualifiers.geometry = ElgLines;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) {
+ publicType.shaderQualifiers.geometry = ElgLinesAdjacency;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) {
+ publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgTriangleStrip)) {
+ publicType.shaderQualifiers.geometry = ElgTriangleStrip;
+ return;
+ }
+ } else {
+ assert(language == EShLangTessEvaluation);
+
+ // input primitive
+ if (id == TQualifier::getGeometryString(ElgTriangles)) {
+ publicType.shaderQualifiers.geometry = ElgTriangles;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgQuads)) {
+ publicType.shaderQualifiers.geometry = ElgQuads;
+ return;
+ }
+ if (id == TQualifier::getGeometryString(ElgIsolines)) {
+ publicType.shaderQualifiers.geometry = ElgIsolines;
+ return;
+ }
+
+ // vertex spacing
+ if (id == TQualifier::getVertexSpacingString(EvsEqual)) {
+ publicType.shaderQualifiers.spacing = EvsEqual;
+ return;
+ }
+ if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) {
+ publicType.shaderQualifiers.spacing = EvsFractionalEven;
+ return;
+ }
+ if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) {
+ publicType.shaderQualifiers.spacing = EvsFractionalOdd;
+ return;
+ }
+
+ // triangle order
+ if (id == TQualifier::getVertexOrderString(EvoCw)) {
+ publicType.shaderQualifiers.order = EvoCw;
+ return;
+ }
+ if (id == TQualifier::getVertexOrderString(EvoCcw)) {
+ publicType.shaderQualifiers.order = EvoCcw;
+ return;
+ }
+
+ // point mode
+ if (id == "point_mode") {
+ publicType.shaderQualifiers.pointMode = true;
+ return;
+ }
+ }
+ }
+ if (language == EShLangFragment) {
+ if (id == "origin_upper_left") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "origin_upper_left");
+ publicType.shaderQualifiers.originUpperLeft = true;
+ return;
+ }
+ if (id == "pixel_center_integer") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "pixel_center_integer");
+ publicType.shaderQualifiers.pixelCenterInteger = true;
+ return;
+ }
+ if (id == "early_fragment_tests") {
+ profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests");
+ profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests");
+ publicType.shaderQualifiers.earlyFragmentTests = true;
+ return;
+ }
+ for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) {
+ if (id == TQualifier::getLayoutDepthString(depth)) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier");
+ publicType.shaderQualifiers.layoutDepth = depth;
+ return;
+ }
+ }
+ if (id.compare(0, 13, "blend_support") == 0) {
+ bool found = false;
+ for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
+ if (id == TQualifier::getBlendEquationString(be)) {
+ requireExtensions(loc, 1, &E_GL_KHR_blend_equation_advanced, "blend equation");
+ intermediate.addBlendEquation(be);
+ publicType.shaderQualifiers.blendEquation = true;
+ found = true;
+ break;
+ }
+ }
+ if (! found)
+ error(loc, "unknown blend equation", "blend_support", "");
+ return;
+ }
+ }
+ error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
+}
+
+// Put the id's layout qualifier value into the public type, for qualifiers having a number set.
+// This is before we know any type information for error checking.
+void TParseContext::setLayoutQualifier(const 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();
+ int value;
+ if (constUnion) {
+ value = constUnion->getConstArray()[0].getIConst();
+ if (! constUnion->isLiteral()) {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature);
+ }
+ } else {
+ // grammar should have give out the error message
+ value = 0;
+ }
+
+ if (value < 0) {
+ error(loc, "cannot be negative", feature, "");
+ return;
+ }
+
+ std::transform(id.begin(), id.end(), id.begin(), ::tolower);
+
+ if (id == "offset") {
+ const char* feature = "uniform offset";
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
+ const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters };
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ publicType.qualifier.layoutOffset = value;
+ return;
+ } else if (id == "align") {
+ const char* feature = "uniform buffer-member align";
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
+ // "The specified alignment must be a power of 2, or a compile-time error results."
+ if (! IsPow2(value))
+ error(loc, "must be a power of 2", "align", "");
+ else
+ publicType.qualifier.layoutAlign = value;
+ return;
+ } else if (id == "location") {
+ profileRequires(loc, EEsProfile, 300, nullptr, "location");
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ~EEsProfile, 330, 2, exts, "location");
+ if ((unsigned int)value >= TQualifier::layoutLocationEnd)
+ error(loc, "location is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutLocation = value;
+ return;
+ } else if (id == "set") {
+ if ((unsigned int)value >= TQualifier::layoutSetEnd)
+ error(loc, "set is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutSet = value;
+ return;
+ } else if (id == "binding") {
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding");
+ profileRequires(loc, EEsProfile, 310, nullptr, "binding");
+ if ((unsigned int)value >= TQualifier::layoutBindingEnd)
+ error(loc, "binding is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutBinding = value;
+ return;
+ } else if (id == "component") {
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component");
+ if ((unsigned)value >= TQualifier::layoutComponentEnd)
+ error(loc, "component is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutComponent = value;
+ return;
+ } else if (id.compare(0, 4, "xfb_") == 0) {
+ // "Any shader making any static use (after preprocessing) of any of these
+ // *xfb_* qualifiers will cause the shader to be in a transform feedback
+ // capturing mode and hence responsible for describing the transform feedback
+ // setup."
+ intermediate.setXfbMode();
+ const char* feature = "transform feedback qualifier";
+ requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature);
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
+ if (id == "xfb_buffer") {
+ // "It is a compile-time error to specify an *xfb_buffer* that is greater than
+ // the implementation-dependent constant gl_MaxTransformFeedbackBuffers."
+ if (value >= resources.maxTransformFeedbackBuffers)
+ error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers);
+ if (value >= (int)TQualifier::layoutXfbBufferEnd)
+ error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1);
+ else
+ publicType.qualifier.layoutXfbBuffer = value;
+ return;
+ } else if (id == "xfb_offset") {
+ if (value >= (int)TQualifier::layoutXfbOffsetEnd)
+ error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1);
+ else
+ publicType.qualifier.layoutXfbOffset = value;
+ return;
+ } else if (id == "xfb_stride") {
+ // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
+ // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
+ if (value > 4 * resources.maxTransformFeedbackInterleavedComponents)
+ error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", resources.maxTransformFeedbackInterleavedComponents);
+ else if (value >= (int)TQualifier::layoutXfbStrideEnd)
+ error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1);
+ if (value < (int)TQualifier::layoutXfbStrideEnd)
+ publicType.qualifier.layoutXfbStride = value;
+ return;
+ }
+ }
+
+ if (id == "input_attachment_index") {
+ requireVulkan(loc, "input_attachment_index");
+ if (value >= (int)TQualifier::layoutAttachmentEnd)
+ error(loc, "attachment index is too large", id.c_str(), "");
+ else
+ publicType.qualifier.layoutAttachment = value;
+ return;
+ }
+ if (id == "constant_id") {
+ requireSpv(loc, "constant_id");
+ if (value >= (int)TQualifier::layoutSpecConstantIdEnd) {
+ error(loc, "specialization-constant id is too large", id.c_str(), "");
+ } else {
+ publicType.qualifier.layoutSpecConstantId = value;
+ publicType.qualifier.specConstant = true;
+ if (! intermediate.addUsedConstantId(value))
+ error(loc, "specialization-constant id already used", id.c_str(), "");
+ }
+ return;
+ }
+
+ switch (language) {
+ case EShLangVertex:
+ break;
+
+ case EShLangTessControl:
+ if (id == "vertices") {
+ if (value == 0)
+ error(loc, "must be greater than 0", "vertices", "");
+ else
+ publicType.shaderQualifiers.vertices = value;
+ return;
+ }
+ break;
+
+ case EShLangTessEvaluation:
+ break;
+
+ case EShLangGeometry:
+ if (id == "invocations") {
+ profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations");
+ if (value == 0)
+ error(loc, "must be at least 1", "invocations", "");
+ else
+ publicType.shaderQualifiers.invocations = value;
+ return;
+ }
+ if (id == "max_vertices") {
+ publicType.shaderQualifiers.vertices = value;
+ if (value > resources.maxGeometryOutputVertices)
+ error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", "");
+ return;
+ }
+ if (id == "stream") {
+ requireProfile(loc, ~EEsProfile, "selecting output stream");
+ publicType.qualifier.layoutStream = value;
+ if (value > 0)
+ intermediate.setMultiStream();
+ return;
+ }
+ break;
+
+ case EShLangFragment:
+ if (id == "index") {
+ requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output");
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output");
+
+ // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1."
+ if (value < 0 || value > 1) {
+ value = 0;
+ error(loc, "value must be 0 or 1", "index", "");
+ }
+
+ publicType.qualifier.layoutIndex = value;
+ return;
+ }
+ break;
+
+ case EShLangCompute:
+ if (id.compare(0, 11, "local_size_") == 0) {
+ profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize");
+ profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize");
+ if (id == "local_size_x") {
+ publicType.shaderQualifiers.localSize[0] = value;
+ return;
+ }
+ if (id == "local_size_y") {
+ publicType.shaderQualifiers.localSize[1] = value;
+ return;
+ }
+ if (id == "local_size_z") {
+ publicType.shaderQualifiers.localSize[2] = value;
+ return;
+ }
+ if (spv > 0) {
+ if (id == "local_size_x_id") {
+ publicType.shaderQualifiers.localSizeSpecId[0] = value;
+ return;
+ }
+ if (id == "local_size_y_id") {
+ publicType.shaderQualifiers.localSizeSpecId[1] = value;
+ return;
+ }
+ if (id == "local_size_z_id") {
+ publicType.shaderQualifiers.localSizeSpecId[2] = value;
+ return;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), "");
+}
+
+// Merge any layout qualifier information from src into dst, leaving everything else in dst alone
+//
+// "More than one layout qualifier may appear in a single declaration.
+// Additionally, the same layout-qualifier-name can occur multiple times
+// within a layout qualifier or across multiple layout qualifiers in the
+// same declaration. When the same layout-qualifier-name occurs
+// multiple times, in a single declaration, the last occurrence overrides
+// the former occurrence(s). Further, if such a layout-qualifier-name
+// will effect subsequent declarations or other observable behavior, it
+// is only the last occurrence that will have any effect, behaving as if
+// the earlier occurrence(s) within the declaration are not present.
+// This is also true for overriding layout-qualifier-names, where one
+// overrides the other (e.g., row_major vs. column_major); only the last
+// occurrence has any effect."
+//
+void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly)
+{
+ if (src.hasMatrix())
+ dst.layoutMatrix = src.layoutMatrix;
+ if (src.hasPacking())
+ dst.layoutPacking = src.layoutPacking;
+
+ if (src.hasStream())
+ dst.layoutStream = src.layoutStream;
+
+ if (src.hasFormat())
+ dst.layoutFormat = src.layoutFormat;
+
+ if (src.hasXfbBuffer())
+ dst.layoutXfbBuffer = src.layoutXfbBuffer;
+
+ if (src.hasAlign())
+ dst.layoutAlign = src.layoutAlign;
+
+ if (! inheritOnly) {
+ if (src.hasLocation())
+ dst.layoutLocation = src.layoutLocation;
+ if (src.hasComponent())
+ dst.layoutComponent = src.layoutComponent;
+ if (src.hasIndex())
+ dst.layoutIndex = src.layoutIndex;
+
+ if (src.hasOffset())
+ dst.layoutOffset = src.layoutOffset;
+
+ if (src.hasSet())
+ dst.layoutSet = src.layoutSet;
+ if (src.layoutBinding != TQualifier::layoutBindingEnd)
+ dst.layoutBinding = src.layoutBinding;
+
+ if (src.hasXfbStride())
+ dst.layoutXfbStride = src.layoutXfbStride;
+ if (src.hasXfbOffset())
+ dst.layoutXfbOffset = src.layoutXfbOffset;
+ if (src.hasAttachment())
+ dst.layoutAttachment = src.layoutAttachment;
+ if (src.hasSpecConstantId())
+ dst.layoutSpecConstantId = src.layoutSpecConstantId;
+
+ if (src.layoutPushConstant)
+ dst.layoutPushConstant = true;
+ }
+}
+
+// Do error layout error checking given a full variable/block declaration.
+void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol)
+{
+ const TType& type = symbol.getType();
+ const TQualifier& qualifier = type.getQualifier();
+
+ // first, cross check WRT to just the type
+ layoutTypeCheck(loc, type);
+
+ // now, any remaining error checking based on the object itself
+
+ if (qualifier.hasAnyLocation()) {
+ switch (qualifier.storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ if (symbol.getAsVariable() == nullptr)
+ error(loc, "can only be used on variable declaration", "location", "");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check packing and matrix
+ if (qualifier.hasUniformLayout()) {
+ switch (qualifier.storage) {
+ case EvqUniform:
+ case EvqBuffer:
+ if (type.getBasicType() != EbtBlock) {
+ if (qualifier.hasMatrix())
+ error(loc, "cannot specify matrix layout on a variable declaration", "layout", "");
+ if (qualifier.hasPacking())
+ error(loc, "cannot specify packing on a variable declaration", "layout", "");
+ // "The offset qualifier can only be used on block members of blocks..."
+ if (qualifier.hasOffset() && type.getBasicType() != EbtAtomicUint)
+ error(loc, "cannot specify on a variable declaration", "offset", "");
+ // "The align qualifier can only be used on blocks or block members..."
+ if (qualifier.hasAlign())
+ error(loc, "cannot specify on a variable declaration", "align", "");
+ if (qualifier.layoutPushConstant)
+ error(loc, "can only specify on a uniform block", "push_constant", "");
+ }
+ break;
+ default:
+ // these were already filtered by layoutTypeCheck() (or its callees)
+ break;
+ }
+ }
+}
+
+// Do layout error checking with respect to a type.
+void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
+{
+ const TQualifier& qualifier = type.getQualifier();
+
+ // first, intra-layout qualifier-only error checking
+ layoutQualifierCheck(loc, qualifier);
+
+ // now, error checking combining type and qualifier
+
+ if (qualifier.hasAnyLocation()) {
+ if (qualifier.hasLocation()) {
+ if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) {
+ if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers)
+ error(loc, "too large for fragment output", "location", "");
+ }
+ }
+ if (qualifier.hasComponent()) {
+ // "It is a compile-time error if this sequence of components gets larger than 3."
+ if (qualifier.layoutComponent + type.getVectorSize() > 4)
+ error(loc, "type overflows the available 4 components", "component", "");
+
+ // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these."
+ if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct)
+ error(loc, "cannot apply to a matrix, structure, or block", "component", "");
+ }
+
+ switch (qualifier.storage) {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ if (type.getBasicType() == EbtBlock)
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block");
+ break;
+ case EvqUniform:
+ case EvqBuffer:
+ break;
+ default:
+ error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", "");
+ break;
+ }
+
+ bool typeCollision;
+ int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision);
+ if (repeated >= 0 && ! typeCollision)
+ error(loc, "overlapping use of location", "location", "%d", repeated);
+ // "fragment-shader outputs ... if two variables are placed within the same
+ // location, they must have the same underlying type (floating-point or integer)"
+ if (typeCollision && language == EShLangFragment && qualifier.isPipeOutput())
+ error(loc, "fragment outputs sharing the same location must be the same basic type", "location", "%d", repeated);
+ }
+
+ if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) {
+ int repeated = intermediate.addXfbBufferOffset(type);
+ if (repeated >= 0)
+ error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
+
+ // "The offset must be a multiple of the size of the first component of the first
+ // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate
+ // containing a double, the offset must also be a multiple of 8..."
+ if (type.containsBasicType(EbtDouble) && ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8))
+ error(loc, "type contains double; xfb_offset must be a multiple of 8", "xfb_offset", "");
+ else if (! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4))
+ error(loc, "must be a multiple of size of first component", "xfb_offset", "");
+ }
+
+ if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) {
+ if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride))
+ error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer);
+ }
+
+ if (qualifier.hasBinding()) {
+ // Binding checking, from the spec:
+ //
+ // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or
+ // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time
+ // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as
+ // an array of size N, all elements of the array from binding through binding + N - 1 must be within this
+ // range."
+ //
+ if (type.getBasicType() != EbtSampler && type.getBasicType() != EbtBlock && type.getBasicType() != EbtAtomicUint)
+ error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", "");
+ if (type.getBasicType() == EbtSampler) {
+ int lastBinding = qualifier.layoutBinding;
+ if (type.isArray())
+ lastBinding += type.getCumulativeArraySize();
+ if (lastBinding >= resources.maxCombinedTextureImageUnits)
+ error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
+ }
+ if (type.getBasicType() == EbtAtomicUint) {
+ if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
+ error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
+ return;
+ }
+ }
+ }
+
+ // atomic_uint
+ if (type.getBasicType() == EbtAtomicUint) {
+ if (! type.getQualifier().hasBinding())
+ error(loc, "layout(binding=X) is required", "atomic_uint", "");
+ }
+
+ // "The offset qualifier can only be used on block members of blocks..."
+ if (qualifier.hasOffset()) {
+ if (type.getBasicType() == EbtBlock)
+ error(loc, "only applies to block members, not blocks", "offset", "");
+ }
+
+ // Image format
+ if (qualifier.hasFormat()) {
+ if (! type.isImage())
+ error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
+ else {
+ if (type.getSampler().type == EbtFloat && qualifier.layoutFormat > ElfFloatGuard)
+ error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
+ if (type.getSampler().type == EbtInt && (qualifier.layoutFormat < ElfFloatGuard || qualifier.layoutFormat > ElfIntGuard))
+ error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
+ if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard)
+ error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
+
+ if (profile == EEsProfile) {
+ // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must
+ // specify either memory qualifier readonly or the memory qualifier writeonly."
+ if (! (qualifier.layoutFormat == ElfR32f || qualifier.layoutFormat == ElfR32i || qualifier.layoutFormat == ElfR32ui)) {
+ if (! qualifier.readonly && ! qualifier.writeonly)
+ error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
+ }
+ }
+ }
+ } else if (type.isImage() && ! qualifier.writeonly)
+ error(loc, "image variables not declared 'writeonly' must have a format layout qualifier", "", "");
+
+ if (qualifier.layoutPushConstant && type.getBasicType() != EbtBlock)
+ error(loc, "can only be used with a block", "push_constant", "");
+
+ // input attachment
+ if (type.isSubpass()) {
+ if (! qualifier.hasAttachment())
+ error(loc, "requires an input_attachment_index layout qualifier", "subpass", "");
+ } else {
+ if (qualifier.hasAttachment())
+ error(loc, "can only be used with a subpass", "input_attachment_index", "");
+ }
+
+ // specialization-constant id
+ if (qualifier.hasSpecConstantId()) {
+ if (type.getQualifier().storage != EvqConst)
+ error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", "");
+ if (! type.isScalar())
+ error(loc, "can only be applied to a scalar", "constant_id", "");
+ switch (type.getBasicType())
+ {
+ case EbtInt:
+ case EbtUint:
+ case EbtInt64:
+ case EbtUint64:
+ case EbtBool:
+ case EbtFloat:
+ case EbtDouble:
+ break;
+ default:
+ error(loc, "cannot be applied to this type", "constant_id", "");
+ break;
+ }
+ }
+}
+
+// Do layout error checking that can be done within a layout qualifier proper, not needing to know
+// if there are blocks, atomic counters, variables, etc.
+void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ if (qualifier.storage == EvqShared && qualifier.hasLayout())
+ error(loc, "cannot apply layout qualifiers to a shared variable", "shared", "");
+
+ // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
+ if (qualifier.hasComponent() && ! qualifier.hasLocation())
+ error(loc, "must specify 'location' to use 'component'", "component", "");
+
+ if (qualifier.hasAnyLocation()) {
+
+ // "As with input layout qualifiers, all shaders except compute shaders
+ // allow *location* layout qualifiers on output variable declarations,
+ // output block declarations, and output block member declarations."
+
+ switch (qualifier.storage) {
+ case EvqVaryingIn:
+ {
+ const char* feature = "location qualifier on input";
+ if (profile == EEsProfile && version < 310)
+ requireStage(loc, EShLangVertex, feature);
+ else
+ requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+ if (language == EShLangVertex) {
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
+ profileRequires(loc, EEsProfile, 300, nullptr, feature);
+ } else {
+ profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ }
+ break;
+ }
+ case EvqVaryingOut:
+ {
+ const char* feature = "location qualifier on output";
+ if (profile == EEsProfile && version < 310)
+ requireStage(loc, EShLangFragment, feature);
+ else
+ requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+ if (language == EShLangFragment) {
+ const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
+ profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
+ profileRequires(loc, EEsProfile, 300, nullptr, feature);
+ } else {
+ profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ }
+ break;
+ }
+ case EvqUniform:
+ case EvqBuffer:
+ {
+ const char* feature = "location qualifier on uniform or buffer";
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature);
+ profileRequires(loc, EEsProfile, 310, nullptr, feature);
+ break;
+ }
+ default:
+ break;
+ }
+ if (qualifier.hasIndex()) {
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "can only be used on an output", "index", "");
+ if (! qualifier.hasLocation())
+ error(loc, "can only be used with an explicit location", "index", "");
+ }
+ }
+
+ if (qualifier.hasBinding()) {
+ if (! qualifier.isUniformOrBuffer())
+ error(loc, "requires uniform or buffer storage qualifier", "binding", "");
+ }
+ if (qualifier.hasStream()) {
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "can only be used on an output", "stream", "");
+ }
+ if (qualifier.hasXfb()) {
+ if (qualifier.storage != EvqVaryingOut)
+ error(loc, "can only be used on an output", "xfb layout qualifier", "");
+ }
+ if (qualifier.hasUniformLayout()) {
+ if (! qualifier.isUniformOrBuffer()) {
+ if (qualifier.hasMatrix() || qualifier.hasPacking())
+ error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
+ if (qualifier.hasOffset() || qualifier.hasAlign())
+ error(loc, "offset/align can only be used on a uniform or buffer", "layout", "");
+ }
+ }
+ if (qualifier.layoutPushConstant) {
+ if (qualifier.storage != EvqUniform)
+ error(loc, "can only be used with a uniform", "push_constant", "");
+ if (qualifier.hasSet())
+ error(loc, "cannot be used with push_constant", "set", "");
+ }
+}
+
+// For places that can't have shader-level layout qualifiers
+void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers)
+{
+ const char* message = "can only apply to a standalone qualifier";
+
+ if (shaderQualifiers.geometry != ElgNone)
+ error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
+ if (shaderQualifiers.invocations != TQualifier::layoutNotSet)
+ error(loc, message, "invocations", "");
+ if (shaderQualifiers.vertices != TQualifier::layoutNotSet) {
+ if (language == EShLangGeometry)
+ error(loc, message, "max_vertices", "");
+ else if (language == EShLangTessControl)
+ error(loc, message, "vertices", "");
+ else
+ assert(0);
+ }
+ for (int i = 0; i < 3; ++i) {
+ if (shaderQualifiers.localSize[i] > 1)
+ error(loc, message, "local_size", "");
+ if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet)
+ error(loc, message, "local_size id", "");
+ }
+ if (shaderQualifiers.blendEquation)
+ error(loc, message, "blend equation", "");
+ // TBD: correctness: are any of these missing? pixelCenterInteger, originUpperLeft, spacing, order, pointmode, earlyfragment, depth
+}
+
+// Correct and/or advance an object's offset layout qualifier.
+void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol)
+{
+ const TQualifier& qualifier = symbol.getType().getQualifier();
+ if (symbol.getType().getBasicType() == EbtAtomicUint) {
+ if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) {
+
+ // Set the offset
+ int offset;
+ if (qualifier.hasOffset())
+ offset = qualifier.layoutOffset;
+ else
+ offset = atomicUintOffsets[qualifier.layoutBinding];
+ symbol.getWritableType().getQualifier().layoutOffset = offset;
+
+ // Check for overlap
+ int numOffsets = 4;
+ if (symbol.getType().isArray())
+ numOffsets *= symbol.getType().getCumulativeArraySize();
+ int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
+ if (repeated >= 0)
+ error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated);
+
+ // Bump the default offset
+ atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets;
+ }
+ }
+}
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise nullptr.
+//
+const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ const TFunction* function = nullptr;
+
+ if (symbolTable.isFunctionNameVariable(call.getName())) {
+ error(loc, "can't use function syntax on variable", call.getName().c_str(), "");
+ return nullptr;
+ }
+
+ if (profile == EEsProfile || version < 120)
+ function = findFunctionExact(loc, call, builtIn);
+ else if (version < 400)
+ function = findFunction120(loc, call, builtIn);
+ else
+ function = findFunction400(loc, call, builtIn);
+
+ return function;
+}
+
+// Function finding algorithm for ES and desktop 110.
+const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+ if (symbol == nullptr) {
+ error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+
+ return nullptr;
+ }
+
+ return symbol->getAsFunction();
+}
+
+// Function finding algorithm for desktop versions 120 through 330.
+const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ // first, look for an exact match
+ TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+ if (symbol)
+ return symbol->getAsFunction();
+
+ // exact match not found, look through a list of overloaded functions of the same name
+
+ // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types
+ // on input parameters (in or inout or default) must have a conversion from the calling argument type to the
+ // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion
+ // from the formal parameter type to the calling argument type. When argument conversions are used to find
+ // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match
+ // more than one function."
+
+ const TFunction* candidate = nullptr;
+ TVector<TFunction*> candidateList;
+ symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
+
+ for (TVector<TFunction*>::const_iterator it = candidateList.begin(); it != candidateList.end(); ++it) {
+ const TFunction& function = *(*it);
+
+ // to even be a potential match, number of arguments has to match
+ if (call.getParamCount() != function.getParamCount())
+ continue;
+
+ bool possibleMatch = true;
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ // same types is easy
+ if (*function[i].type == *call[i].type)
+ continue;
+
+ // We have a mismatch in type, see if it is implicitly convertible
+
+ if (function[i].type->isArray() || call[i].type->isArray() ||
+ ! function[i].type->sameElementShape(*call[i].type))
+ possibleMatch = false;
+ else {
+ // do direction-specific checks for conversion of basic type
+ if (function[i].type->getQualifier().isParamInput()) {
+ if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType()))
+ possibleMatch = false;
+ }
+ if (function[i].type->getQualifier().isParamOutput()) {
+ if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType()))
+ possibleMatch = false;
+ }
+ }
+ if (! possibleMatch)
+ break;
+ }
+ if (possibleMatch) {
+ if (candidate) {
+ // our second match, meaning ambiguity
+ error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), "");
+ } else
+ candidate = &function;
+ }
+ }
+
+ if (candidate == nullptr)
+ error(loc, "no matching overloaded function found", call.getName().c_str(), "");
+
+ return candidate;
+}
+
+// Function finding algorithm for desktop version 400 and above.
+const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn)
+{
+ // TODO: 4.00 functionality: findFunction400()
+ return findFunction120(loc, call, builtIn);
+}
+
+// When a declaration includes a type, but not a variable name, it can be
+// to establish defaults.
+void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
+{
+ if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && publicType.qualifier.hasOffset()) {
+ if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
+ error(loc, "atomic_uint binding is too large", "binding", "");
+ return;
+ }
+ atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
+ return;
+ }
+
+ if (publicType.qualifier.hasLayout())
+ warn(loc, "useless application of layout qualifier", "layout", "");
+}
+
+//
+// Do everything necessary to handle a variable (non-block) declaration.
+// Either redeclaring a variable, or making a new one, updating the symbol
+// table, and all error checking.
+//
+// Returns a subtree node that computes an initializer, if needed.
+// Returns nullptr if there is no code to execute for initialization.
+//
+// 'publicType' is the type part of the declaration (to the left)
+// 'arraySizes' is the arrayness tagged on the identifier (to the right)
+//
+TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, TArraySizes* arraySizes, TIntermTyped* initializer)
+{
+ TType type(publicType); // shallow copy; 'type' shares the arrayness and structure definition with 'publicType'
+ if (type.isImplicitlySizedArray()) {
+ // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
+ // of different sizes, for this case sharing the shallow copy of arrayness
+ // with the publicType oversubscribes it, so get a deep copy of the arrayness.
+ type.newArraySizes(*publicType.arraySizes);
+ }
+
+ if (voidErrorCheck(loc, identifier, type.getBasicType()))
+ return nullptr;
+
+ if (initializer)
+ rValueErrorCheck(loc, "initializer", initializer);
+ else
+ nonInitConstCheck(loc, identifier, type);
+
+ samplerCheck(loc, type, identifier, initializer);
+ atomicUintCheck(loc, type, identifier);
+ transparentCheck(loc, type, identifier);
+
+ if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
+ error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
+ if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.layoutDepth != EldNone)
+ error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", "");
+
+ // Check for redeclaration of built-ins and/or attempting to declare a reserved name
+ bool newDeclaration = false; // true if a new entry gets added to the symbol table
+ TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers, newDeclaration);
+ if (! symbol)
+ reservedErrorCheck(loc, identifier);
+
+ inheritGlobalDefaults(type.getQualifier());
+
+ // Declare the variable
+ if (arraySizes || type.isArray()) {
+ // Arrayness is potentially coming both from the type and from the
+ // variable: "int[] a[];" or just one or the other.
+ // Merge it all to the type, so all arrayness is part of the type.
+ arrayDimCheck(loc, &type, arraySizes);
+ arrayDimMerge(type, arraySizes);
+
+ // Check that implicit sizing is only where allowed.
+ arrayUnsizedCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false);
+
+ if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type))
+ declareArray(loc, identifier, type, symbol, newDeclaration);
+
+ if (initializer) {
+ profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer");
+ profileRequires(loc, EEsProfile, 300, nullptr, "initializer");
+ }
+ } else {
+ // non-array case
+ if (! symbol)
+ symbol = declareNonArray(loc, identifier, type, newDeclaration);
+ else if (type != symbol->getType())
+ error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
+ }
+
+ if (! symbol)
+ return nullptr;
+
+ // Deal with initializer
+ TIntermNode* initNode = nullptr;
+ if (symbol && initializer) {
+ TVariable* variable = symbol->getAsVariable();
+ if (! variable) {
+ error(loc, "initializer requires a variable, not a member", identifier.c_str(), "");
+ return nullptr;
+ }
+ initNode = executeInitializer(loc, initializer, variable);
+ }
+
+ // look for errors in layout qualifier use
+ layoutObjectCheck(loc, *symbol);
+ fixOffset(loc, *symbol);
+
+ // see if it's a linker-level object to track
+ if (newDeclaration && symbolTable.atGlobalLevel())
+ intermediate.addSymbolLinkageNode(linkage, *symbol);
+
+ return initNode;
+}
+
+// Pick up global defaults from the provide global defaults into dst.
+void TParseContext::inheritGlobalDefaults(TQualifier& dst) const
+{
+ if (dst.storage == EvqVaryingOut) {
+ if (! dst.hasStream() && language == EShLangGeometry)
+ dst.layoutStream = globalOutputDefaults.layoutStream;
+ if (! dst.hasXfbBuffer())
+ dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer;
+ }
+}
+
+//
+// Make an internal-only variable whose name is for debug purposes only
+// and won't be searched for. Callers will only use the return value to use
+// the variable, not the name to look it up. It is okay if the name
+// is the same as other names; there won't be any conflict.
+//
+TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const
+{
+ TString* nameString = new TString(name);
+ TVariable* variable = new TVariable(nameString, type);
+ symbolTable.makeInternalVariable(*variable);
+
+ return variable;
+}
+
+//
+// Declare a non-array variable, the main point being there is no redeclaration
+// for resizing allowed.
+//
+// Return the successfully declared variable.
+//
+TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type, bool& newDeclaration)
+{
+ // make a new variable
+ TVariable* variable = new TVariable(&identifier, type);
+
+ ioArrayCheck(loc, type, identifier);
+ // add variable to symbol table
+ if (! symbolTable.insert(*variable)) {
+ error(loc, "redefinition", variable->getName().c_str(), "");
+ return nullptr;
+ } else {
+ newDeclaration = true;
+ return variable;
+ }
+}
+
+//
+// Handle all types of initializers from the grammar.
+//
+// Returning nullptr just means there is no code to execute to handle the
+// initializer, which will, for example, be the case for constant initializers.
+//
+TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
+{
+ //
+ // Identifier must be of type constant, a global, or a temporary, and
+ // starting at version 120, desktop allows uniforms to have initializers.
+ //
+ TStorageQualifier qualifier = variable->getType().getQualifier().storage;
+ if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
+ (qualifier == EvqUniform && profile != EEsProfile && version >= 120))) {
+ error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
+ return nullptr;
+ }
+ arrayObjectCheck(loc, variable->getType(), "array initializer");
+
+ //
+ // If the initializer was from braces { ... }, we convert the whole subtree to a
+ // constructor-style subtree, allowing the rest of the code to operate
+ // identically for both kinds of initializers.
+ //
+ // Type can't be deduced from the initializer list, so a skeletal type to
+ // follow has to be passed in. Constness and specialization-constness
+ // should be deduced bottom up, not dictated by the skeletal type.
+ //
+ TType skeletalType;
+ skeletalType.shallowCopy(variable->getType());
+ skeletalType.getQualifier().makeTemporary();
+ initializer = convertInitializerList(loc, skeletalType, initializer);
+ if (! initializer) {
+ // error recovery; don't leave const without constant values
+ if (qualifier == EvqConst)
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+
+ // Fix outer arrayness if variable is unsized, getting size from the initializer
+ if (initializer->getType().isExplicitlySizedArray() &&
+ variable->getType().isImplicitlySizedArray())
+ variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize());
+
+ // Inner arrayness can also get set by an initializer
+ if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() &&
+ initializer->getType().getArraySizes()->getNumDims() ==
+ variable->getType().getArraySizes()->getNumDims()) {
+ // adopt unsized sizes from the initializer's sizes
+ for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) {
+ if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize)
+ variable->getWritableType().getArraySizes().setDimSize(d, initializer->getType().getArraySizes()->getDimSize(d));
+ }
+ }
+
+ // Uniforms require a compile-time constant initializer
+ if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
+ error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+ // Global consts require a constant initializer (specialization constant is okay)
+ if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
+ error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+
+ // Const variables require a constant initializer, depending on version
+ if (qualifier == EvqConst) {
+ if (! initializer->getType().getQualifier().isConstant()) {
+ const char* initFeature = "non-constant initializer";
+ requireProfile(loc, ~EEsProfile, initFeature);
+ profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ variable->getWritableType().getQualifier().storage = EvqConstReadOnly;
+ qualifier = EvqConstReadOnly;
+ }
+ } else {
+ // Non-const global variables in ES need a const initializer.
+ //
+ // "In declarations of global variables with no storage qualifier or with a const
+ // qualifier any initializer must be a constant expression."
+ if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
+ const char* initFeature = "non-constant global initializer";
+ if (relaxedErrors())
+ warn(loc, "not allowed in this version", initFeature, "");
+ else
+ requireProfile(loc, ~EEsProfile, initFeature);
+ }
+ }
+
+ if (qualifier == EvqConst || qualifier == EvqUniform) {
+ // Compile-time tagging of the variable with its constant value...
+
+ initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
+ if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) {
+ error(loc, "non-matching or non-convertible constant type for const initializer",
+ variable->getType().getStorageQualifierString(), "");
+ variable->getWritableType().getQualifier().makeTemporary();
+ return nullptr;
+ }
+
+ // We either have a folded constant in getAsConstantUnion, or we have to use
+ // the initializer's subtree in the AST to represent the computation of a
+ // specialization constant.
+ assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant());
+ if (initializer->getAsConstantUnion())
+ variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
+ else {
+ // It's a specialization constant.
+ variable->getWritableType().getQualifier().makeSpecConstant();
+
+ // Keep the subtree that computes the specialization constant with the variable.
+ // Later, a symbol node will adopt the subtree from the variable.
+ variable->setConstSubtree(initializer);
+ }
+ } else {
+ // normal assigning of a value to a variable...
+ specializationCheck(loc, initializer->getType(), "initializer");
+ TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
+ TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
+ if (! initNode)
+ assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+
+ return initNode;
+ }
+
+ return nullptr;
+}
+
+//
+// Reprocess any initializer-list (the "{ ... }" syntax) parts of the
+// initializer.
+//
+// Need to hierarchically assign correct types and implicit
+// conversions. Will do this mimicking the same process used for
+// creating a constructor-style initializer, ensuring we get the
+// same form. However, it has to in parallel walk the 'type'
+// passed in, as type cannot be deduced from an initializer list.
+//
+TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer)
+{
+ // Will operate recursively. Once a subtree is found that is constructor style,
+ // everything below it is already good: Only the "top part" of the initializer
+ // can be an initializer list, where "top part" can extend for several (or all) levels.
+
+ // see if we have bottomed out in the tree within the initializer-list part
+ TIntermAggregate* initList = initializer->getAsAggregate();
+ if (! initList || initList->getOp() != EOpNull)
+ return initializer;
+
+ // Of the initializer-list set of nodes, need to process bottom up,
+ // so recurse deep, then process on the way up.
+
+ // Go down the tree here...
+ if (type.isArray()) {
+ // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate.
+ // Later on, initializer execution code will deal with array size logic.
+ TType arrayType;
+ arrayType.shallowCopy(type); // sharing struct stuff is fine
+ arrayType.newArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
+
+ // edit array sizes to fill in unsized dimensions
+ arrayType.changeOuterArraySize((int)initList->getSequence().size());
+ TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped();
+ if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() &&
+ arrayType.getArraySizes().getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
+ for (int d = 1; d < arrayType.getArraySizes().getNumDims(); ++d) {
+ if (arrayType.getArraySizes().getDimSize(d) == UnsizedArraySize)
+ arrayType.getArraySizes().setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1));
+ }
+ }
+
+ TType elementType(arrayType, 0); // dereferenced type
+ for (size_t i = 0; i < initList->getSequence().size(); ++i) {
+ initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped());
+ if (initList->getSequence()[i] == nullptr)
+ return nullptr;
+ }
+
+ return addConstructor(loc, initList, arrayType, mapTypeToConstructorOp(arrayType));
+ } else if (type.isStruct()) {
+ if (type.getStruct()->size() != initList->getSequence().size()) {
+ error(loc, "wrong number of structure members", "initializer list", "");
+ return nullptr;
+ }
+ for (size_t i = 0; i < type.getStruct()->size(); ++i) {
+ initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped());
+ if (initList->getSequence()[i] == nullptr)
+ return nullptr;
+ }
+ } else if (type.isMatrix()) {
+ if (type.getMatrixCols() != (int)initList->getSequence().size()) {
+ error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str());
+ return nullptr;
+ }
+ TType vectorType(type, 0); // dereferenced type
+ for (int i = 0; i < type.getMatrixCols(); ++i) {
+ initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped());
+ if (initList->getSequence()[i] == nullptr)
+ return nullptr;
+ }
+ } else if (type.isVector()) {
+ if (type.getVectorSize() != (int)initList->getSequence().size()) {
+ error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
+ return nullptr;
+ }
+ } else {
+ error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
+ return nullptr;
+ }
+
+ // now that the subtree is processed, process this node
+ return addConstructor(loc, initList, type, mapTypeToConstructorOp(type));
+}
+
+//
+// Test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right data type, if allowed and required.
+//
+// Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type, TOperator op)
+{
+ if (node == nullptr || node->getAsTyped() == nullptr)
+ return nullptr;
+ rValueErrorCheck(loc, "constructor", node->getAsTyped());
+
+ TIntermAggregate* aggrNode = node->getAsAggregate();
+
+ // Combined texture-sampler constructors are completely semantic checked
+ // in constructorTextureSamplerError()
+ if (op == EOpConstructTextureSampler)
+ return intermediate.setAggregateOperator(aggrNode, op, type, loc);
+
+ TTypeList::const_iterator memberTypes;
+ if (op == EOpConstructStruct)
+ memberTypes = type.getStruct()->begin();
+
+ TType elementType;
+ if (type.isArray()) {
+ TType dereferenced(type, 0);
+ elementType.shallowCopy(dereferenced);
+ } else
+ elementType.shallowCopy(type);
+
+ bool singleArg;
+ if (aggrNode) {
+ if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+ singleArg = true;
+ else
+ singleArg = false;
+ } else
+ singleArg = true;
+
+ TIntermTyped *newNode;
+ if (singleArg) {
+ // If structure constructor or array constructor is being called
+ // for only one parameter inside the structure, we need to call constructAggregate function once.
+ if (type.isArray())
+ newNode = constructAggregate(node, elementType, 1, node->getLoc());
+ else if (op == EOpConstructStruct)
+ newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc());
+ else
+ newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
+
+ if (newNode && (type.isArray() || op == EOpConstructStruct))
+ newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
+
+ return newNode;
+ }
+
+ //
+ // Handle list of arguments.
+ //
+ TIntermSequence &sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor
+ // if the structure constructor contains more than one parameter, then construct
+ // each parameter
+
+ int paramCount = 0; // keeps track of the constructor parameter number being checked
+
+ // for each parameter to the constructor call, check to see if the right type is passed or convert them
+ // to the right type if possible (and allowed).
+ // for structure constructors, just check if the right type is passed, no conversion is allowed.
+ for (TIntermSequence::iterator p = sequenceVector.begin();
+ p != sequenceVector.end(); p++, paramCount++) {
+ if (type.isArray())
+ newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc());
+ else if (op == EOpConstructStruct)
+ newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
+ else
+ newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
+
+ if (newNode)
+ *p = newNode;
+ else
+ return nullptr;
+ }
+
+ return intermediate.setAggregateOperator(aggrNode, op, type, loc);
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
+// float, then float is converted to int.
+//
+// Returns nullptr for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc, bool subset)
+{
+ TIntermTyped* newNode;
+ TOperator basicOp;
+
+ //
+ // First, convert types as needed.
+ //
+ switch (op) {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2x2:
+ case EOpConstructMat2x3:
+ case EOpConstructMat2x4:
+ case EOpConstructMat3x2:
+ case EOpConstructMat3x3:
+ case EOpConstructMat3x4:
+ case EOpConstructMat4x2:
+ case EOpConstructMat4x3:
+ case EOpConstructMat4x4:
+ case EOpConstructFloat:
+ basicOp = EOpConstructFloat;
+ break;
+
+ case EOpConstructDVec2:
+ case EOpConstructDVec3:
+ case EOpConstructDVec4:
+ case EOpConstructDMat2x2:
+ case EOpConstructDMat2x3:
+ case EOpConstructDMat2x4:
+ case EOpConstructDMat3x2:
+ case EOpConstructDMat3x3:
+ case EOpConstructDMat3x4:
+ case EOpConstructDMat4x2:
+ case EOpConstructDMat4x3:
+ case EOpConstructDMat4x4:
+ case EOpConstructDouble:
+ basicOp = EOpConstructDouble;
+ break;
+
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ basicOp = EOpConstructInt;
+ break;
+
+ case EOpConstructUVec2:
+ case EOpConstructUVec3:
+ case EOpConstructUVec4:
+ case EOpConstructUint:
+ basicOp = EOpConstructUint;
+ break;
+
+ case EOpConstructI64Vec2:
+ case EOpConstructI64Vec3:
+ case EOpConstructI64Vec4:
+ case EOpConstructInt64:
+ basicOp = EOpConstructInt64;
+ break;
+
+ case EOpConstructU64Vec2:
+ case EOpConstructU64Vec3:
+ case EOpConstructU64Vec4:
+ case EOpConstructUint64:
+ basicOp = EOpConstructUint64;
+ break;
+
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ basicOp = EOpConstructBool;
+ break;
+
+ default:
+ error(loc, "unsupported construction", "", "");
+
+ return nullptr;
+ }
+ newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc());
+ if (newNode == nullptr) {
+ error(loc, "can't convert", "constructor", "");
+ return nullptr;
+ }
+
+ //
+ // Now, if there still isn't an operation to do the construction, and we need one, add one.
+ //
+
+ // Otherwise, skip out early.
+ if (subset || (newNode != node && newNode->getType() == type))
+ return newNode;
+
+ // setAggregateOperator will insert a new node for the constructor, as needed.
+ return intermediate.setAggregateOperator(newNode, op, type, loc);
+}
+
+// This function tests for the type of the parameters to the structure or array constructor. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns nullptr for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc)
+{
+ TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped());
+ if (! converted || converted->getType() != type) {
+ error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
+ node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str());
+
+ return nullptr;
+ }
+
+ return converted;
+}
+
+//
+// Do everything needed to add an interface block.
+//
+void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
+{
+ blockStageIoCheck(loc, currentBlockQualifier);
+ blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
+ if (arraySizes) {
+ arrayUnsizedCheck(loc, currentBlockQualifier, arraySizes, false, false);
+ arrayDimCheck(loc, arraySizes, 0);
+ if (arraySizes->getNumDims() > 1)
+ requireProfile(loc, ~EEsProfile, "array-of-array of block");
+ }
+
+ // fix and check for member storage qualifiers and types that don't belong within a block
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TType& memberType = *typeList[member].type;
+ TQualifier& memberQualifier = memberType.getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ globalQualifierFixCheck(memberLoc, memberQualifier);
+ if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
+ error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
+ memberQualifier.storage = currentBlockQualifier.storage;
+ if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
+ error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
+ if (memberType.isArray())
+ arrayUnsizedCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1);
+ if (memberQualifier.hasOffset()) {
+ requireProfile(memberLoc, ~EEsProfile, "offset on block member");
+ profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member");
+ }
+
+ if (memberType.containsOpaque())
+ error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
+ }
+
+ // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will
+ // do all the rest.
+ if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) {
+ redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes);
+ return;
+ }
+
+ // Not a redeclaration of a built-in; check that all names are user names.
+ reservedErrorCheck(loc, *blockName);
+ if (instanceName)
+ reservedErrorCheck(loc, *instanceName);
+ for (unsigned int member = 0; member < typeList.size(); ++member)
+ reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName());
+
+ // Make default block qualification, and adjust the member qualifications
+
+ TQualifier defaultQualification;
+ switch (currentBlockQualifier.storage) {
+ case EvqUniform: defaultQualification = globalUniformDefaults; break;
+ case EvqBuffer: defaultQualification = globalBufferDefaults; break;
+ case EvqVaryingIn: defaultQualification = globalInputDefaults; break;
+ case EvqVaryingOut: defaultQualification = globalOutputDefaults; break;
+ default: defaultQualification.clear(); break;
+ }
+
+ // Special case for "push_constant uniform", which has a default of std430,
+ // contrary to normal uniform defaults, and can't have a default tracked for it.
+ if (currentBlockQualifier.layoutPushConstant && !currentBlockQualifier.hasPacking())
+ currentBlockQualifier.layoutPacking = ElpStd430;
+
+ // fix and check for member layout qualifiers
+
+ mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true);
+
+ // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
+ // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
+ if (currentBlockQualifier.hasAlign() || currentBlockQualifier.hasAlign()) {
+ if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) {
+ error(loc, "can only be used with std140 or std430 layout packing", "offset/align", "");
+ defaultQualification.layoutAlign = -1;
+ }
+ }
+
+ bool memberWithLocation = false;
+ bool memberWithoutLocation = false;
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ if (memberQualifier.hasStream()) {
+ if (defaultQualification.layoutStream != memberQualifier.layoutStream)
+ error(memberLoc, "member cannot contradict block", "stream", "");
+ }
+
+ // "This includes a block's inheritance of the
+ // current global default buffer, a block member's inheritance of the block's
+ // buffer, and the requirement that any *xfb_buffer* declared on a block
+ // member must match the buffer inherited from the block."
+ if (memberQualifier.hasXfbBuffer()) {
+ if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer)
+ error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", "");
+ }
+
+ if (memberQualifier.hasPacking())
+ error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), "");
+ if (memberQualifier.hasLocation()) {
+ const char* feature = "location on block member";
+ switch (currentBlockQualifier.storage) {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature);
+ profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature);
+ profileRequires(memberLoc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature);
+ memberWithLocation = true;
+ break;
+ default:
+ error(memberLoc, "can only use in an in/out block", feature, "");
+ break;
+ }
+ } else
+ memberWithoutLocation = true;
+ if (memberQualifier.hasAlign()) {
+ if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430)
+ error(memberLoc, "can only be used with std140 or std430 layout packing", "align", "");
+ }
+
+ TQualifier newMemberQualification = defaultQualification;
+ mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false);
+ memberQualifier = newMemberQualification;
+ }
+
+ // Process the members
+ fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
+ fixBlockXfbOffsets(currentBlockQualifier, typeList);
+ fixBlockUniformOffsets(currentBlockQualifier, typeList);
+ for (unsigned int member = 0; member < typeList.size(); ++member)
+ layoutTypeCheck(typeList[member].loc, *typeList[member].type);
+
+ // reverse merge, so that currentBlockQualifier now has all layout information
+ // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers)
+ mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true);
+
+ //
+ // Build and add the interface block as a new type named 'blockName'
+ //
+
+ TType blockType(&typeList, *blockName, currentBlockQualifier);
+ if (arraySizes)
+ blockType.newArraySizes(*arraySizes);
+ else
+ ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName);
+
+ //
+ // Don't make a user-defined type out of block name; that will cause an error
+ // if the same block name gets reused in a different interface.
+ //
+ // "Block names have no other use within a shader
+ // beyond interface matching; it is a compile-time error to use a block name at global scope for anything
+ // other than as a block name (e.g., use of a block name for a global variable name or function name is
+ // currently reserved)."
+ //
+ // Use the symbol table to prevent normal reuse of the block's name, as a variable entry,
+ // whose type is EbtBlock, but without all the structure; that will come from the type
+ // the instances point to.
+ //
+ TType blockNameType(EbtBlock, blockType.getQualifier().storage);
+ TVariable* blockNameVar = new TVariable(blockName, blockNameType);
+ if (! symbolTable.insert(*blockNameVar)) {
+ TSymbol* existingName = symbolTable.find(*blockName);
+ if (existingName->getType().getBasicType() == EbtBlock) {
+ if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
+ error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString());
+ return;
+ }
+ } else {
+ error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
+ return;
+ }
+ }
+
+ // Add the variable, as anonymous or named instanceName.
+ // Make an anonymous variable if no name was provided.
+ if (! instanceName)
+ instanceName = NewPoolTString("");
+
+ TVariable& variable = *new TVariable(instanceName, blockType);
+ if (! symbolTable.insert(variable)) {
+ if (*instanceName == "")
+ error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), "");
+ else
+ error(loc, "block instance name redefinition", variable.getName().c_str(), "");
+
+ return;
+ }
+
+ // Check for general layout qualifier errors
+ layoutObjectCheck(loc, variable);
+
+ if (isIoResizeArray(blockType)) {
+ ioArraySymbolResizeList.push_back(&variable);
+ checkIoArraysConsistency(loc, true);
+ } else
+ fixIoArraySize(loc, variable.getWritableType());
+
+ // Save it in the AST for linker use.
+ intermediate.addSymbolLinkageNode(linkage, variable);
+}
+
+// Do all block-declaration checking regarding the combination of in/out/uniform/buffer
+// with a particular stage.
+void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ switch (qualifier.storage) {
+ case EvqUniform:
+ profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
+ profileRequires(loc, ENoProfile, 140, nullptr, "uniform block");
+ if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.layoutPushConstant)
+ error(loc, "requires the 'buffer' storage qualifier", "std430", "");
+ break;
+ case EvqBuffer:
+ requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
+ profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block");
+ profileRequires(loc, EEsProfile, 310, nullptr, "buffer block");
+ break;
+ case EvqVaryingIn:
+ profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block");
+ // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader
+ // "Compute shaders do not permit user-defined input variables..."
+ requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask|EShLangFragmentMask), "input block");
+ if (language == EShLangFragment)
+ profileRequires(loc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block");
+ break;
+ case EvqVaryingOut:
+ profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block");
+ requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask), "output block");
+ // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins
+ if (language == EShLangVertex && ! parsingBuiltins)
+ profileRequires(loc, EEsProfile, 0, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block");
+ break;
+ default:
+ error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
+ break;
+ }
+}
+
+// Do all block-declaration checking regarding its qualifiers.
+void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool instanceName)
+{
+ // The 4.5 specification says:
+ //
+ // interface-block :
+ // layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt ;
+ //
+ // interface-qualifier :
+ // in
+ // out
+ // patch in
+ // patch out
+ // uniform
+ // buffer
+ //
+ // Note however memory qualifiers aren't included, yet the specification also says
+ //
+ // "...memory qualifiers may also be used in the declaration of shader storage blocks..."
+
+ if (qualifier.isInterpolation())
+ error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", "");
+ if (qualifier.centroid)
+ error(loc, "cannot use centroid qualifier on an interface block", "centroid", "");
+ if (qualifier.sample)
+ error(loc, "cannot use sample qualifier on an interface block", "sample", "");
+ if (qualifier.invariant)
+ error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
+ if (qualifier.layoutPushConstant) {
+ intermediate.addPushConstantCount();
+ if (! instanceName)
+ error(loc, "requires an instance name", "push_constant", "");
+ }
+}
+
+//
+// "For a block, this process applies to the entire block, or until the first member
+// is reached that has a location layout qualifier. When a block member is declared with a location
+// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level
+// declaration. Subsequent members are again assigned consecutive locations, based on the newest location,
+// until the next member declared with a location qualifier. The values used for locations do not have to be
+// declared in increasing order."
+void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation)
+{
+ // "If a block has no block-level location layout qualifier, it is required that either all or none of its members
+ // have a location layout qualifier, or a compile-time error results."
+ if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation)
+ error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", "");
+ else {
+ if (memberWithLocation) {
+ // remove any block-level location and make it per *every* member
+ int nextLocation = 0; // by the rule above, initial value is not relevant
+ if (qualifier.hasAnyLocation()) {
+ nextLocation = qualifier.layoutLocation;
+ qualifier.layoutLocation = TQualifier::layoutLocationEnd;
+ if (qualifier.hasComponent()) {
+ // "It is a compile-time error to apply the *component* qualifier to a ... block"
+ error(loc, "cannot apply to a block", "component", "");
+ }
+ if (qualifier.hasIndex()) {
+ error(loc, "cannot apply to a block", "index", "");
+ }
+ }
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+ if (! memberQualifier.hasLocation()) {
+ if (nextLocation >= (int)TQualifier::layoutLocationEnd)
+ error(memberLoc, "location is too large", "location", "");
+ memberQualifier.layoutLocation = nextLocation;
+ memberQualifier.layoutComponent = 0;
+ }
+ nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(*typeList[member].type);
+ }
+ }
+ }
+}
+
+void TParseContext::fixBlockXfbOffsets(TQualifier& qualifier, TTypeList& typeList)
+{
+ // "If a block is qualified with xfb_offset, all its
+ // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any
+ // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer
+ // offsets."
+
+ if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset())
+ return;
+
+ int nextOffset = qualifier.layoutXfbOffset;
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ bool containsDouble = false;
+ int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, containsDouble);
+ // see if we need to auto-assign an offset to this member
+ if (! memberQualifier.hasXfbOffset()) {
+ // "if applied to an aggregate containing a double, the offset must also be a multiple of 8"
+ if (containsDouble)
+ RoundToPow2(nextOffset, 8);
+ memberQualifier.layoutXfbOffset = nextOffset;
+ } else
+ nextOffset = memberQualifier.layoutXfbOffset;
+ nextOffset += memberSize;
+ }
+
+ // The above gave all block members an offset, so we can take it off the block now,
+ // which will avoid double counting the offset usage.
+ qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd;
+}
+
+// Calculate and save the offset of each block member, using the recursively
+// defined block offset rules and the user-provided offset and align.
+//
+// Also, compute and save the total size of the block. For the block's size, arrayness
+// is not taken into account, as each element is backed by a separate buffer.
+//
+void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
+{
+ if (! qualifier.isUniformOrBuffer())
+ return;
+ if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430)
+ return;
+
+ int offset = 0;
+ int memberSize;
+ for (unsigned int member = 0; member < typeList.size(); ++member) {
+ TQualifier& memberQualifier = typeList[member].type->getQualifier();
+ const TSourceLoc& memberLoc = typeList[member].loc;
+
+ // "When align is applied to an array, it effects only the start of the array, not the array's internal stride."
+
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix;
+ int dummyStride;
+ int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking == ElpStd140,
+ subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
+ if (memberQualifier.hasOffset()) {
+ // "The specified offset must be a multiple
+ // of the base alignment of the type of the block member it qualifies, or a compile-time error results."
+ if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment))
+ error(memberLoc, "must be a multiple of the member's alignment", "offset", "");
+
+ // "It is a compile-time error to specify an offset that is smaller than the offset of the previous
+ // member in the block or that lies within the previous member of the block"
+ if (memberQualifier.layoutOffset < offset)
+ error(memberLoc, "cannot lie in previous members", "offset", "");
+
+ // "The offset qualifier forces the qualified member to start at or after the specified
+ // integral-constant expression, which will be its byte offset from the beginning of the buffer.
+ // "The actual offset of a member is computed as
+ // follows: If offset was declared, start with that offset, otherwise start with the next available offset."
+ offset = std::max(offset, memberQualifier.layoutOffset);
+ }
+
+ // "The actual alignment of a member will be the greater of the specified align alignment and the standard
+ // (e.g., std140) base alignment for the member's type."
+ if (memberQualifier.hasAlign())
+ memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign);
+
+ // "If the resulting offset is not a multiple of the actual alignment,
+ // increase it to the first offset that is a multiple of
+ // the actual alignment."
+ RoundToPow2(offset, memberAlignment);
+ typeList[member].type->getQualifier().layoutOffset = offset;
+ offset += memberSize;
+ }
+}
+
+// For an identifier that is already declared, add more qualification to it.
+void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
+{
+ TSymbol* symbol = symbolTable.find(identifier);
+ if (! symbol) {
+ error(loc, "identifier not previously declared", identifier.c_str(), "");
+ return;
+ }
+ if (symbol->getAsFunction()) {
+ error(loc, "cannot re-qualify a function name", identifier.c_str(), "");
+ return;
+ }
+
+ if (qualifier.isAuxiliary() ||
+ qualifier.isMemory() ||
+ qualifier.isInterpolation() ||
+ qualifier.hasLayout() ||
+ qualifier.storage != EvqTemporary ||
+ qualifier.precision != EpqNone) {
+ error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), "");
+ return;
+ }
+
+ // For read-only built-ins, add a new symbol for holding the modified qualifier.
+ // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block)
+ if (symbol->isReadOnly())
+ symbol = symbolTable.copyUp(symbol);
+
+ if (qualifier.invariant) {
+ if (intermediate.inIoAccessed(identifier))
+ error(loc, "cannot change qualification after use", "invariant", "");
+ symbol->getWritableType().getQualifier().invariant = true;
+ invariantCheck(loc, symbol->getType().getQualifier());
+ } else if (qualifier.noContraction) {
+ if (intermediate.inIoAccessed(identifier))
+ error(loc, "cannot change qualification after use", "precise", "");
+ symbol->getWritableType().getQualifier().noContraction = true;
+ } else if (qualifier.specConstant) {
+ symbol->getWritableType().getQualifier().makeSpecConstant();
+ if (qualifier.hasSpecConstantId())
+ symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId;
+ } else
+ warn(loc, "unknown requalification", "", "");
+}
+
+void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers)
+{
+ for (unsigned int i = 0; i < identifiers.size(); ++i)
+ addQualifierToExisting(loc, qualifier, *identifiers[i]);
+}
+
+// Make sure 'invariant' isn't being applied to a non-allowed object.
+void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier)
+{
+ if (! qualifier.invariant)
+ return;
+
+ bool pipeOut = qualifier.isPipeOutput();
+ bool pipeIn = qualifier.isPipeInput();
+ if (version >= 300 || (profile != EEsProfile && version >= 420)) {
+ if (! pipeOut)
+ error(loc, "can only apply to an output", "invariant", "");
+ } else {
+ if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn))
+ error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", "");
+ }
+}
+
+//
+// Updating default qualifier for the case of a declaration with just a qualifier,
+// no type, block, or identifier.
+//
+void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType)
+{
+ if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) {
+ assert(language == EShLangTessControl || language == EShLangGeometry);
+ const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices";
+
+ if (publicType.qualifier.storage != EvqVaryingOut)
+ error(loc, "can only apply to 'out'", id, "");
+ if (! intermediate.setVertices(publicType.shaderQualifiers.vertices))
+ error(loc, "cannot change previously set layout value", id, "");
+
+ if (language == EShLangTessControl)
+ checkIoArraysConsistency(loc);
+ }
+ if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) {
+ if (publicType.qualifier.storage != EvqVaryingIn)
+ error(loc, "can only apply to 'in'", "invocations", "");
+ if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations))
+ error(loc, "cannot change previously set layout value", "invocations", "");
+ }
+ if (publicType.shaderQualifiers.geometry != ElgNone) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ switch (publicType.shaderQualifiers.geometry) {
+ case ElgPoints:
+ case ElgLines:
+ case ElgLinesAdjacency:
+ case ElgTriangles:
+ case ElgTrianglesAdjacency:
+ case ElgQuads:
+ case ElgIsolines:
+ if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) {
+ if (language == EShLangGeometry)
+ checkIoArraysConsistency(loc);
+ } else
+ error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ break;
+ default:
+ error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ }
+ } else if (publicType.qualifier.storage == EvqVaryingOut) {
+ switch (publicType.shaderQualifiers.geometry) {
+ case ElgPoints:
+ case ElgLineStrip:
+ case ElgTriangleStrip:
+ if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry))
+ error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ break;
+ default:
+ error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+ }
+ } else
+ error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage));
+ }
+ if (publicType.shaderQualifiers.spacing != EvsNone) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing))
+ error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), "");
+ } else
+ error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), "");
+ }
+ if (publicType.shaderQualifiers.order != EvoNone) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order))
+ error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), "");
+ } else
+ error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), "");
+ }
+ if (publicType.shaderQualifiers.pointMode) {
+ if (publicType.qualifier.storage == EvqVaryingIn)
+ intermediate.setPointMode();
+ else
+ error(loc, "can only apply to 'in'", "point_mode", "");
+ }
+ for (int i = 0; i < 3; ++i) {
+ if (publicType.shaderQualifiers.localSize[i] > 1) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i]))
+ error(loc, "cannot change previously set size", "local_size", "");
+ else {
+ int max = 0;
+ switch (i) {
+ case 0: max = resources.maxComputeWorkGroupSizeX; break;
+ case 1: max = resources.maxComputeWorkGroupSizeY; break;
+ case 2: max = resources.maxComputeWorkGroupSizeZ; break;
+ default: break;
+ }
+ if (intermediate.getLocalSize(i) > (unsigned int)max)
+ error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", "");
+
+ // Fix the existing constant gl_WorkGroupSize with this new information.
+ TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize");
+ if (workGroupSize != nullptr)
+ workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i));
+ }
+ } else
+ error(loc, "can only apply to 'in'", "local_size", "");
+ }
+ if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) {
+ if (publicType.qualifier.storage == EvqVaryingIn) {
+ if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i]))
+ error(loc, "cannot change previously set size", "local_size", "");
+ } else
+ error(loc, "can only apply to 'in'", "local_size id", "");
+ // Set the workgroup built-in variable as a specialization constant
+ TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize");
+ if (workGroupSize != nullptr)
+ workGroupSize->getWritableType().getQualifier().specConstant = true;
+ }
+ }
+ if (publicType.shaderQualifiers.earlyFragmentTests) {
+ if (publicType.qualifier.storage == EvqVaryingIn)
+ intermediate.setEarlyFragmentTests();
+ else
+ error(loc, "can only apply to 'in'", "early_fragment_tests", "");
+ }
+ if (publicType.shaderQualifiers.blendEquation) {
+ if (publicType.qualifier.storage != EvqVaryingOut)
+ error(loc, "can only apply to 'out'", "blend equation", "");
+ }
+
+ const TQualifier& qualifier = publicType.qualifier;
+
+ if (qualifier.isAuxiliary() ||
+ qualifier.isMemory() ||
+ qualifier.isInterpolation() ||
+ qualifier.precision != EpqNone)
+ error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", "");
+ // "The offset qualifier can only be used on block members of blocks..."
+ // "The align qualifier can only be used on blocks or block members..."
+ if (qualifier.hasOffset() ||
+ qualifier.hasAlign())
+ error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", "");
+
+ layoutQualifierCheck(loc, qualifier);
+
+ switch (qualifier.storage) {
+ case EvqUniform:
+ if (qualifier.hasMatrix())
+ globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix;
+ if (qualifier.hasPacking())
+ globalUniformDefaults.layoutPacking = qualifier.layoutPacking;
+ break;
+ case EvqBuffer:
+ if (qualifier.hasMatrix())
+ globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix;
+ if (qualifier.hasPacking())
+ globalBufferDefaults.layoutPacking = qualifier.layoutPacking;
+ break;
+ case EvqVaryingIn:
+ break;
+ case EvqVaryingOut:
+ if (qualifier.hasStream())
+ globalOutputDefaults.layoutStream = qualifier.layoutStream;
+ if (qualifier.hasXfbBuffer())
+ globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer;
+ if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) {
+ if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride))
+ error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer);
+ }
+ break;
+ default:
+ error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
+ return;
+ }
+
+ if (qualifier.hasBinding())
+ error(loc, "cannot declare a default, include a type or full declaration", "binding", "");
+ if (qualifier.hasAnyLocation())
+ error(loc, "cannot declare a default, use a full declaration", "location/component/index", "");
+ if (qualifier.hasXfbOffset())
+ error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
+ if (qualifier.layoutPushConstant)
+ error(loc, "cannot declare a default, can only be used on a block", "push_constant", "");
+ if (qualifier.hasSpecConstantId())
+ error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
+}
+
+//
+// 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,
+// and follow that by the case/default we are on now. (See switch topology comment on
+// TIntermSwitch.)
+//
+void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode)
+{
+ TIntermSequence* switchSequence = switchSequenceStack.back();
+
+ if (statements) {
+ if (switchSequence->size() == 0)
+ error(statements->getLoc(), "cannot have statements before first case/default label", "switch", "");
+ statements->setOperator(EOpSequence);
+ switchSequence->push_back(statements);
+ }
+ if (branchNode) {
+ // check all previous cases for the same label (or both are 'default')
+ for (unsigned int s = 0; s < switchSequence->size(); ++s) {
+ TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode();
+ if (prevBranch) {
+ TIntermTyped* prevExpression = prevBranch->getExpression();
+ TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression();
+ if (prevExpression == nullptr && newExpression == nullptr)
+ error(branchNode->getLoc(), "duplicate label", "default", "");
+ else if (prevExpression != nullptr &&
+ newExpression != nullptr &&
+ prevExpression->getAsConstantUnion() &&
+ newExpression->getAsConstantUnion() &&
+ prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() ==
+ newExpression->getAsConstantUnion()->getConstArray()[0].getIConst())
+ error(branchNode->getLoc(), "duplicated value", "case", "");
+ }
+ }
+ switchSequence->push_back(branchNode);
+ }
+}
+
+//
+// Turn the top-level node sequence built up of wrapupSwitchSubsequence9)
+// into a switch node.
+//
+TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements)
+{
+ profileRequires(loc, EEsProfile, 300, nullptr, "switch statements");
+ profileRequires(loc, ENoProfile, 130, nullptr, "switch statements");
+
+ wrapupSwitchSubsequence(lastStatements, nullptr);
+
+ if (expression == nullptr ||
+ (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) ||
+ expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector())
+ error(loc, "condition must be a scalar integer expression", "switch", "");
+
+ // If there is nothing to do, drop the switch but still execute the expression
+ TIntermSequence* switchSequence = switchSequenceStack.back();
+ if (switchSequence->size() == 0)
+ return expression;
+
+ if (lastStatements == nullptr) {
+ // This was originally an ERRROR, because early versions of the specification said
+ // "it is an error to have no statement between a label and the end of the switch statement."
+ // The specifications were updated to remove this (being ill-defined what a "statement" was),
+ // so, this became a warning. However, 3.0 tests still check for the error.
+ if (profile == EEsProfile && version <= 300 && ! relaxedErrors())
+ error(loc, "last case/default label not followed by statements", "switch", "");
+ else
+ warn(loc, "last case/default label not followed by statements", "switch", "");
+
+ // emulate a break for error recovery
+ lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc));
+ lastStatements->setOperator(EOpSequence);
+ switchSequence->push_back(lastStatements);
+ }
+
+ TIntermAggregate* body = new TIntermAggregate(EOpSequence);
+ body->getSequence() = *switchSequenceStack.back();
+ body->setLoc(loc);
+
+ TIntermSwitch* switchNode = new TIntermSwitch(expression, body);
+ switchNode->setLoc(loc);
+
+ return switchNode;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h
new file mode 100644
index 00000000000..a4775e71875
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h
@@ -0,0 +1,388 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// This header defines a two-level parse-helper hierarchy, derived from
+// TParseVersions:
+// - TParseContextBase: sharable across multiple parsers
+// - TParseContext: GLSL specific helper
+//
+
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "parseVersions.h"
+#include "../Include/ShHandle.h"
+#include "SymbolTable.h"
+#include "localintermediate.h"
+#include "Scan.h"
+#include <functional>
+
+#include <functional>
+
+namespace glslang {
+
+struct TPragma {
+ TPragma(bool o, bool d) : optimize(o), debug(d) { }
+ bool optimize;
+ bool debug;
+ TPragmaTable pragmaTable;
+};
+
+class TScanContext;
+class TPpContext;
+
+typedef std::set<int> TIdSetType;
+
+//
+// Sharable code (as well as what's in TParseVersions) across
+// parse helpers.
+//
+class TParseContextBase : public TParseVersions {
+public:
+ TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, int version,
+ EProfile profile, int spv, int vulkan, EShLanguage language,
+ TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
+ : TParseVersions(interm, version, profile, spv, vulkan, language, infoSink, forwardCompatible, messages),
+ symbolTable(symbolTable), tokensBeforeEOF(false),
+ linkage(nullptr), scanContext(nullptr), ppContext(nullptr) { }
+ virtual ~TParseContextBase() { }
+
+ virtual void setLimits(const TBuiltInResource&) = 0;
+
+ EShLanguage getLanguage() const { return language; }
+ TIntermAggregate*& getLinkage() { return linkage; }
+ void setScanContext(TScanContext* c) { scanContext = c; }
+ TScanContext* getScanContext() const { return scanContext; }
+ void setPpContext(TPpContext* c) { ppContext = c; }
+ TPpContext* getPpContext() const { return ppContext; }
+
+ virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
+ virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
+ virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
+ virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
+ virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
+
+ virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
+ virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
+ virtual bool lineDirectiveShouldSetNextLine() const = 0;
+ virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
+
+ virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
+
+ virtual void notifyVersion(int line, int version, const char* type_string)
+ {
+ if (versionCallback)
+ versionCallback(line, version, type_string);
+ }
+ virtual void notifyErrorDirective(int line, const char* error_message)
+ {
+ if (errorCallback)
+ errorCallback(line, error_message);
+ }
+ virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
+ {
+ if (lineCallback)
+ lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
+ }
+ virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
+ {
+ if (extensionCallback)
+ extensionCallback(line, extension, behavior);
+ }
+
+ TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
+ bool tokensBeforeEOF;
+
+protected:
+ TParseContextBase(TParseContextBase&);
+ TParseContextBase& operator=(TParseContextBase&);
+
+ TIntermAggregate* linkage; // aggregate node of objects the linker may need, if not referenced by the rest of the AST
+ TScanContext* scanContext;
+ TPpContext* ppContext;
+
+ // These, if set, will be called when a line, pragma ... is preprocessed.
+ // They will be called with any parameters to the original directive.
+ std::function<void(int, int, bool, int, const char*)> lineCallback;
+ std::function<void(int, const TVector<TString>&)> pragmaCallback;
+ std::function<void(int, int, const char*)> versionCallback;
+ std::function<void(int, const char*, const char*)> extensionCallback;
+ std::function<void(int, const char*)> errorCallback;
+};
+
+//
+// GLSL-specific parse helper. Should have GLSL in the name, but that's
+// too big of a change for comparing branches at the moment, and perhaps
+// impacts downstream consumers as well.
+//
+class TParseContext : public TParseContextBase {
+public:
+ TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, int spv, int vulkan, EShLanguage, TInfoSink&,
+ bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
+ virtual ~TParseContext();
+
+ void setLimits(const TBuiltInResource&);
+ bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false);
+ void parserError(const char* s); // for bison's yyerror
+
+ void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+ void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+ void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+ void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...);
+
+ void reservedErrorCheck(const TSourceLoc&, const TString&);
+ void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op);
+ bool lineContinuationCheck(const TSourceLoc&, bool endOfComment);
+ bool lineDirectiveShouldSetNextLine() const;
+ bool builtInName(const TString&);
+
+ void handlePragma(const TSourceLoc&, const TVector<TString>&);
+ TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
+ TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
+ void checkIndex(const TSourceLoc&, const TType&, int& index);
+ void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
+
+ void makeEditable(TSymbol*&);
+ TVariable* getEditableVariable(const char* name);
+ bool isIoResizeArray(const TType&) const;
+ void fixIoArraySize(const TSourceLoc&, TType&);
+ void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
+ void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
+ void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
+ int getIoArrayImplicitSize() const;
+ void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
+
+ TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
+ TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
+ TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
+ void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, const TString& field);
+ TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
+ TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
+ TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
+ void checkLocation(const TSourceLoc&, TOperator);
+ TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
+ void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
+ TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
+ void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
+ void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
+ TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
+
+ bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
+ void assignError(const TSourceLoc&, const char* op, TString left, TString right);
+ void unaryOpError(const TSourceLoc&, const char* op, TString operand);
+ void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
+ void variableCheck(TIntermTyped*& nodePtr);
+ bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
+ void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
+ void constantValueCheck(TIntermTyped* node, const char* token);
+ void integerCheck(const TIntermTyped* node, const char* token);
+ void globalCheck(const TSourceLoc&, const char* token);
+ bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
+ bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
+ void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&);
+ bool arrayQualifierError(const TSourceLoc&, const TQualifier&);
+ bool arrayError(const TSourceLoc&, const TType&);
+ void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
+ void structArrayCheck(const TSourceLoc&, const TType& structure);
+ void arrayUnsizedCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember);
+ void arrayOfArrayVersionCheck(const TSourceLoc&);
+ void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
+ void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
+ void arrayDimMerge(TType& type, const TArraySizes* sizes);
+ bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
+ void boolCheck(const TSourceLoc&, const TIntermTyped*);
+ void boolCheck(const TSourceLoc&, const TPublicType&);
+ void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
+ void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
+ void transparentCheck(const TSourceLoc&, const TType&, const TString& identifier);
+ void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
+ void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
+ bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
+ void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
+ void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier);
+ int computeSamplerTypeIndex(TSampler&);
+ TPrecisionQualifier getDefaultPrecision(TPublicType&);
+ void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&);
+ void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type);
+ bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
+ TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration);
+ void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
+ void paramCheckFix(const TSourceLoc&, const TStorageQualifier&, TType& type);
+ void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
+ void nestedBlockCheck(const TSourceLoc&);
+ void nestedStructCheck(const TSourceLoc&);
+ void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
+ void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
+ void specializationCheck(const TSourceLoc&, const TType&, const char* op);
+ void structTypeCheck(const TSourceLoc&, TPublicType&);
+ void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
+ void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
+ void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
+
+ void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
+ void constantIndexExpressionCheck(TIntermNode*);
+
+ void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
+ void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
+ void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
+ void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
+ void layoutTypeCheck(const TSourceLoc&, const TType&);
+ void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
+ void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
+ void fixOffset(const TSourceLoc&, TSymbol&);
+
+ const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
+ void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
+ TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
+ TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
+ TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
+ TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
+ void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
+ void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
+ void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
+ void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
+ void fixBlockXfbOffsets(TQualifier&, TTypeList&);
+ void fixBlockUniformOffsets(TQualifier&, TTypeList&);
+ void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
+ void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
+ void invariantCheck(const TSourceLoc&, const TQualifier&);
+ void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
+ void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
+ TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
+
+ void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
+
+protected:
+ void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
+ void inheritGlobalDefaults(TQualifier& dst) const;
+ TVariable* makeInternalVariable(const char* name, const TType&) const;
+ TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&, bool& newDeclaration);
+ void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
+ TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
+ TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
+ TOperator mapTypeToConstructorOp(const TType&) const;
+ void finalErrorCheck();
+ void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, TPrefixType prefix,
+ va_list args);
+
+public:
+ //
+ // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
+ //
+
+ // Current state of parsing
+ struct TPragma contextPragma;
+ int loopNestingLevel; // 0 if outside all loops
+ int structNestingLevel; // 0 if outside blocks and structures
+ int controlFlowNestingLevel; // 0 if outside all flow control
+ int statementNestingLevel; // 0 if outside all flow control or compound statements
+ TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
+ TList<int> switchLevel; // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
+ bool inMain; // if inside a function, true if the function is main
+ bool postMainReturn; // if inside a function, true if the function is main and this is after a return statement
+ const TType* currentFunctionType; // the return type of the function that's currently being parsed
+ bool functionReturnsValue; // true if a non-void function has a return
+ const TString* blockName;
+ TQualifier currentBlockQualifier;
+ TPrecisionQualifier defaultPrecision[EbtNumTypes];
+ TBuiltInResource resources;
+ TLimits& limits;
+
+protected:
+ TParseContext(TParseContext&);
+ TParseContext& operator=(TParseContext&);
+
+ const bool parsingBuiltins; // true if parsing built-in symbols/functions
+ static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex()
+ TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
+ bool afterEOF;
+ TQualifier globalBufferDefaults;
+ TQualifier globalUniformDefaults;
+ TQualifier globalInputDefaults;
+ TQualifier globalOutputDefaults;
+ int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
+ TString currentCaller; // name of last function body entered (not valid when at global scope)
+ TIdSetType inductiveLoopIds;
+ bool anyIndexLimits;
+ TVector<TIntermTyped*> needsIndexLimitationChecking;
+
+ //
+ // Geometry shader input arrays:
+ // - array sizing is based on input primitive and/or explicit size
+ //
+ // Tessellation control output arrays:
+ // - array sizing is based on output layout(vertices=...) and/or explicit size
+ //
+ // Both:
+ // - array sizing is retroactive
+ // - built-in block redeclarations interact with this
+ //
+ // Design:
+ // - use a per-context "resize-list", a list of symbols whose array sizes
+ // can be fixed
+ //
+ // - the resize-list starts empty at beginning of user-shader compilation, it does
+ // not have built-ins in it
+ //
+ // - on built-in array use: copyUp() symbol and add it to the resize-list
+ //
+ // - on user array declaration: add it to the resize-list
+ //
+ // - on block redeclaration: copyUp() symbol and add it to the resize-list
+ // * note, that appropriately gives an error if redeclaring a block that
+ // was already used and hence already copied-up
+ //
+ // - on seeing a layout declaration that sizes the array, fix everything in the
+ // resize-list, giving errors for mismatch
+ //
+ // - on seeing an array size declaration, give errors on mismatch between it and previous
+ // array-sizing declarations
+ //
+ TVector<TSymbol*> ioArraySymbolResizeList;
+};
+
+} // end namespace glslang
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/PoolAlloc.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/PoolAlloc.cpp
new file mode 100644
index 00000000000..d56979b492b
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/PoolAlloc.cpp
@@ -0,0 +1,347 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/Common.h"
+#include "../Include/PoolAlloc.h"
+
+#include "../Include/InitializeGlobals.h"
+#include "../OSDependent/osinclude.h"
+
+namespace glslang {
+
+OS_TLSIndex PoolIndex;
+
+void InitializeMemoryPools()
+{
+ TThreadMemoryPools* pools = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
+ if (pools)
+ return;
+
+ TPoolAllocator *threadPoolAllocator = new TPoolAllocator();
+
+ TThreadMemoryPools* threadData = new TThreadMemoryPools();
+
+ threadData->threadPoolAllocator = threadPoolAllocator;
+
+ OS_SetTLSValue(PoolIndex, threadData);
+}
+
+void FreeGlobalPools()
+{
+ // Release the allocated memory for this thread.
+ TThreadMemoryPools* globalPools = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
+ if (! globalPools)
+ return;
+
+ GetThreadPoolAllocator().popAll();
+ delete &GetThreadPoolAllocator();
+ delete globalPools;
+}
+
+bool InitializePoolIndex()
+{
+ // Allocate a TLS index.
+ if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+ return false;
+
+ return true;
+}
+
+void FreePoolIndex()
+{
+ // Release the TLS index.
+ OS_FreeTLSIndex(PoolIndex);
+}
+
+TPoolAllocator& GetThreadPoolAllocator()
+{
+ TThreadMemoryPools* threadData = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
+
+ return *threadData->threadPoolAllocator;
+}
+
+void SetThreadPoolAllocator(TPoolAllocator& poolAllocator)
+{
+ TThreadMemoryPools* threadData = static_cast<TThreadMemoryPools*>(OS_GetTLSValue(PoolIndex));
+
+ threadData->threadPoolAllocator = &poolAllocator;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
+ pageSize(growthIncrement),
+ alignment(allocationAlignment),
+ freeList(0),
+ inUseList(0),
+ numCalls(0)
+{
+ //
+ // Don't allow page sizes we know are smaller than all common
+ // OS page sizes.
+ //
+ if (pageSize < 4*1024)
+ pageSize = 4*1024;
+
+ //
+ // A large currentPageOffset indicates a new page needs to
+ // be obtained to allocate memory.
+ //
+ currentPageOffset = pageSize;
+
+ //
+ // Adjust alignment to be at least pointer aligned and
+ // power of 2.
+ //
+ size_t minAlign = sizeof(void*);
+ alignment &= ~(minAlign - 1);
+ if (alignment < minAlign)
+ alignment = minAlign;
+ size_t a = 1;
+ while (a < alignment)
+ a <<= 1;
+ alignment = a;
+ alignmentMask = a - 1;
+
+ //
+ // Align header skip
+ //
+ headerSkip = minAlign;
+ if (headerSkip < sizeof(tHeader)) {
+ headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+ }
+
+ push();
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+ while (inUseList) {
+ tHeader* next = inUseList->nextPage;
+ inUseList->~tHeader();
+ delete [] reinterpret_cast<char*>(inUseList);
+ inUseList = next;
+ }
+
+ //
+ // Always delete the free list memory - it can't be being
+ // (correctly) referenced, whether the pool allocator was
+ // global or not. We should not check the guard blocks
+ // here, because we did it already when the block was
+ // placed into the free list.
+ //
+ while (freeList) {
+ tHeader* next = freeList->nextPage;
+ delete [] reinterpret_cast<char*>(freeList);
+ freeList = next;
+ }
+}
+
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal = 0xfe;
+const unsigned char TAllocation::userDataFill = 0xcd;
+
+# ifdef GUARD_BLOCKS
+ const size_t TAllocation::guardBlockSize = 16;
+# else
+ const size_t TAllocation::guardBlockSize = 0;
+# endif
+
+//
+// Check a single guard block for damage
+//
+#ifdef GUARD_BLOCKS
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+#else
+void TAllocation::checkGuardBlock(unsigned char*, unsigned char, const char*) const
+#endif
+{
+#ifdef GUARD_BLOCKS
+ for (size_t x = 0; x < guardBlockSize; x++) {
+ if (blockMem[x] != val) {
+ const int maxSize = 80;
+ char assertMsg[maxSize];
+
+ // We don't print the assert message. It's here just to be helpful.
+ snprintf(assertMsg, maxSize, "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
+ locText, size, data());
+ assert(0 && "PoolAlloc: Damage in guard block");
+ }
+ }
+#else
+ assert(guardBlockSize == 0);
+#endif
+}
+
+
+void TPoolAllocator::push()
+{
+ tAllocState state = { currentPageOffset, inUseList };
+
+ stack.push_back(state);
+
+ //
+ // Indicate there is no current page to allocate from.
+ //
+ currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+ if (stack.size() < 1)
+ return;
+
+ tHeader* page = stack.back().page;
+ currentPageOffset = stack.back().offset;
+
+ while (inUseList != page) {
+ // invoke destructor to free allocation list
+ inUseList->~tHeader();
+
+ tHeader* nextInUse = inUseList->nextPage;
+ if (inUseList->pageCount > 1)
+ delete [] reinterpret_cast<char*>(inUseList);
+ else {
+ inUseList->nextPage = freeList;
+ freeList = inUseList;
+ }
+ inUseList = nextInUse;
+ }
+
+ stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+ while (stack.size() > 0)
+ pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+ // If we are using guard blocks, all allocations are bracketed by
+ // them: [guardblock][allocation][guardblock]. numBytes is how
+ // much memory the caller asked for. allocationSize is the total
+ // size including guard blocks. In release build,
+ // guardBlockSize=0 and this all gets optimized away.
+ size_t allocationSize = TAllocation::allocationSize(numBytes);
+
+ //
+ // Just keep some interesting statistics.
+ //
+ ++numCalls;
+ totalBytes += numBytes;
+
+ //
+ // Do the allocation, most likely case first, for efficiency.
+ // This step could be moved to be inline sometime.
+ //
+ if (currentPageOffset + allocationSize <= pageSize) {
+ //
+ // Safe to allocate from currentPageOffset.
+ //
+ unsigned char* memory = reinterpret_cast<unsigned char*>(inUseList) + currentPageOffset;
+ currentPageOffset += allocationSize;
+ currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, memory, numBytes);
+ }
+
+ if (allocationSize + headerSkip > pageSize) {
+ //
+ // Do a multi-page allocation. Don't mix these with the others.
+ // The OS is efficient and allocating and free-ing multiple pages.
+ //
+ size_t numBytesToAlloc = allocationSize + headerSkip;
+ tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+ if (memory == 0)
+ return 0;
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+ inUseList = memory;
+
+ currentPageOffset = pageSize; // make next allocation come from a new page
+
+ // No guard blocks for multi-page allocations (yet)
+ return reinterpret_cast<void*>(reinterpret_cast<UINT_PTR>(memory) + headerSkip);
+ }
+
+ //
+ // Need a simple page to allocate from.
+ //
+ tHeader* memory;
+ if (freeList) {
+ memory = freeList;
+ freeList = freeList->nextPage;
+ } else {
+ memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+ if (memory == 0)
+ return 0;
+ }
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, 1);
+ inUseList = memory;
+
+ unsigned char* ret = reinterpret_cast<unsigned char*>(inUseList) + headerSkip;
+ currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, ret, numBytes);
+}
+
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+ for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+ alloc->check();
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.cpp
new file mode 100644
index 00000000000..a4fa551cadf
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.cpp
@@ -0,0 +1,118 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+#include "RemoveTree.h"
+
+namespace glslang {
+
+//
+// Code to recursively delete the intermediate tree.
+//
+struct TRemoveTraverser : TIntermTraverser {
+ TRemoveTraverser() : TIntermTraverser(false, false, true, false) {}
+
+ virtual void visitSymbol(TIntermSymbol* node)
+ {
+ delete node;
+ }
+
+ virtual bool visitBinary(TVisit /* visit*/ , TIntermBinary* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitUnary(TVisit /* visit */, TIntermUnary* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitAggregate(TVisit /* visit*/ , TIntermAggregate* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitSelection(TVisit /* visit*/ , TIntermSelection* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitSwitch(TVisit /* visit*/ , TIntermSwitch* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual void visitConstantUnion(TIntermConstantUnion* node)
+ {
+ delete node;
+ }
+
+ virtual bool visitLoop(TVisit /* visit*/ , TIntermLoop* node)
+ {
+ delete node;
+
+ return true;
+ }
+
+ virtual bool visitBranch(TVisit /* visit*/ , TIntermBranch* node)
+ {
+ delete node;
+
+ return true;
+ }
+};
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+ TRemoveTraverser it;
+
+ root->traverse(&it);
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.h
new file mode 100644
index 00000000000..483b25dcb51
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/RemoveTree.h
@@ -0,0 +1,39 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+namespace glslang {
+
+void RemoveAllTreeNodes(TIntermNode*);
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp
new file mode 100644
index 00000000000..762fb86c4f8
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp
@@ -0,0 +1,1331 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// GLSL scanning, leveraging the scanning done by the preprocessor.
+//
+
+#include <string.h>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "../Include/Types.h"
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "glslang_tab.cpp.h"
+#include "ScanContext.h"
+#include "Scan.h"
+
+// preprocessor includes
+#include "preprocessor/PpContext.h"
+#include "preprocessor/PpTokens.h"
+
+// Required to avoid missing prototype warnings for some compilers
+int yylex(YYSTYPE*, glslang::TParseContext&);
+
+namespace glslang {
+
+// read past any white space
+void TInputScanner::consumeWhiteSpace(bool& foundNonSpaceTab)
+{
+ int c = peek(); // don't accidentally consume anything other than whitespace
+ while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\r' || c == '\n')
+ foundNonSpaceTab = true;
+ get();
+ c = peek();
+ }
+}
+
+// return true if a comment was actually consumed
+bool TInputScanner::consumeComment()
+{
+ if (peek() != '/')
+ return false;
+
+ get(); // consume the '/'
+ int c = peek();
+ if (c == '/') {
+
+ // a '//' style comment
+ get(); // consume the second '/'
+ c = get();
+ do {
+ while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n')
+ c = get();
+
+ if (c == EndOfInput || c == '\r' || c == '\n') {
+ while (c == '\r' || c == '\n')
+ c = get();
+
+ // we reached the end of the comment
+ break;
+ } else {
+ // it's a '\', so we need to keep going, after skipping what's escaped
+
+ // read the skipped character
+ c = get();
+
+ // if it's a two-character newline, skip both characters
+ if (c == '\r' && peek() == '\n')
+ get();
+ c = get();
+ }
+ } while (true);
+
+ // put back the last non-comment character
+ if (c != EndOfInput)
+ unget();
+
+ return true;
+ } else if (c == '*') {
+
+ // a '/*' style comment
+ get(); // consume the '*'
+ c = get();
+ do {
+ while (c != EndOfInput && c != '*')
+ c = get();
+ if (c == '*') {
+ c = get();
+ if (c == '/')
+ break; // end of comment
+ // not end of comment
+ } else // end of input
+ break;
+ } while (true);
+
+ return true;
+ } else {
+ // it's not a comment, put the '/' back
+ unget();
+
+ return false;
+ }
+}
+
+// skip whitespace, then skip a comment, rinse, repeat
+void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
+{
+ do {
+ consumeWhiteSpace(foundNonSpaceTab);
+
+ // if not starting a comment now, then done
+ int c = peek();
+ if (c != '/' || c == EndOfInput)
+ return;
+
+ // skip potential comment
+ foundNonSpaceTab = true;
+ if (! consumeComment())
+ return;
+
+ } while (true);
+}
+
+// Returns true if there was non-white space (e.g., a comment, newline) before the #version
+// or no #version was found; otherwise, returns false. There is no error case, it always
+// succeeds, but will leave version == 0 if no #version was found.
+//
+// Sets notFirstToken based on whether tokens (beyond white space and comments)
+// appeared before the #version.
+//
+// N.B. does not attempt to leave input in any particular known state. The assumption
+// is that scanning will start anew, following the rules for the chosen version/profile,
+// and with a corresponding parsing context.
+//
+bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken)
+{
+ // This function doesn't have to get all the semantics correct,
+ // just find the #version if there is a correct one present.
+ // The preprocessor will have the responsibility of getting all the semantics right.
+
+ bool versionNotFirst = false; // means not first WRT comments and white space, nothing more
+ notFirstToken = false; // means not first WRT to real tokens
+ version = 0; // means not found
+ profile = ENoProfile;
+
+ bool foundNonSpaceTab = false;
+ bool lookingInMiddle = false;
+ int c;
+ do {
+ if (lookingInMiddle) {
+ notFirstToken = true;
+ // make forward progress by finishing off the current line plus extra new lines
+ if (peek() == '\n' || peek() == '\r') {
+ while (peek() == '\n' || peek() == '\r')
+ get();
+ } else
+ do {
+ c = get();
+ } while (c != EndOfInput && c != '\n' && c != '\r');
+ while (peek() == '\n' || peek() == '\r')
+ get();
+ if (peek() == EndOfInput)
+ return true;
+ }
+ lookingInMiddle = true;
+
+ // Nominal start, skipping the desktop allowed comments and white space, but tracking if
+ // something else was found for ES:
+ consumeWhitespaceComment(foundNonSpaceTab);
+ if (foundNonSpaceTab)
+ versionNotFirst = true;
+
+ // "#"
+ if (get() != '#') {
+ versionNotFirst = true;
+ continue;
+ }
+
+ // whitespace
+ do {
+ c = get();
+ } while (c == ' ' || c == '\t');
+
+ // "version"
+ if ( c != 'v' ||
+ get() != 'e' ||
+ get() != 'r' ||
+ get() != 's' ||
+ get() != 'i' ||
+ get() != 'o' ||
+ get() != 'n') {
+ versionNotFirst = true;
+ continue;
+ }
+
+ // whitespace
+ do {
+ c = get();
+ } while (c == ' ' || c == '\t');
+
+ // version number
+ while (c >= '0' && c <= '9') {
+ version = 10 * version + (c - '0');
+ c = get();
+ }
+ if (version == 0) {
+ versionNotFirst = true;
+ continue;
+ }
+
+ // whitespace
+ while (c == ' ' || c == '\t')
+ c = get();
+
+ // profile
+ const int maxProfileLength = 13; // not including any 0
+ char profileString[maxProfileLength];
+ int profileLength;
+ for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
+ if (c == EndOfInput || c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ break;
+ profileString[profileLength] = (char)c;
+ c = get();
+ }
+ if (c != EndOfInput && c != ' ' && c != '\t' && c != '\n' && c != '\r') {
+ versionNotFirst = true;
+ continue;
+ }
+
+ if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
+ profile = EEsProfile;
+ else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
+ profile = ECoreProfile;
+ else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
+ profile = ECompatibilityProfile;
+
+ return versionNotFirst;
+ } while (true);
+}
+
+// Fill this in when doing glslang-level scanning, to hand back to the parser.
+class TParserToken {
+public:
+ explicit TParserToken(YYSTYPE& b) : sType(b) { }
+
+ YYSTYPE& sType;
+protected:
+ TParserToken(TParserToken&);
+ TParserToken& operator=(TParserToken&);
+};
+
+} // end namespace glslang
+
+// This is the function the glslang parser (i.e., bison) calls to get its next token
+int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext)
+{
+ glslang::TParserToken token(*glslangTokenDesc);
+
+ return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token);
+}
+
+namespace {
+
+struct str_eq
+{
+ bool operator()(const char* lhs, const char* rhs) const
+ {
+ return strcmp(lhs, rhs) == 0;
+ }
+};
+
+struct str_hash
+{
+ size_t operator()(const char* str) const
+ {
+ // djb2
+ unsigned long hash = 5381;
+ int c;
+
+ while ((c = *str++) != 0)
+ hash = ((hash << 5) + hash) + c;
+
+ return hash;
+ }
+};
+
+// A single global usable by all threads, by all versions, by all languages.
+// After a single process-level initialization, this is read only and thread safe
+std::unordered_map<const char*, int, str_hash, str_eq>* KeywordMap = nullptr;
+std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = nullptr;
+
+};
+
+namespace glslang {
+
+void TScanContext::fillInKeywordMap()
+{
+ if (KeywordMap != nullptr) {
+ // this is really an error, as this should called only once per process
+ // but, the only risk is if two threads called simultaneously
+ return;
+ }
+ KeywordMap = new std::unordered_map<const char*, int, str_hash, str_eq>;
+
+ (*KeywordMap)["const"] = CONST;
+ (*KeywordMap)["uniform"] = UNIFORM;
+ (*KeywordMap)["in"] = IN;
+ (*KeywordMap)["out"] = OUT;
+ (*KeywordMap)["inout"] = INOUT;
+ (*KeywordMap)["struct"] = STRUCT;
+ (*KeywordMap)["break"] = BREAK;
+ (*KeywordMap)["continue"] = CONTINUE;
+ (*KeywordMap)["do"] = DO;
+ (*KeywordMap)["for"] = FOR;
+ (*KeywordMap)["while"] = WHILE;
+ (*KeywordMap)["switch"] = SWITCH;
+ (*KeywordMap)["case"] = CASE;
+ (*KeywordMap)["default"] = DEFAULT;
+ (*KeywordMap)["if"] = IF;
+ (*KeywordMap)["else"] = ELSE;
+ (*KeywordMap)["discard"] = DISCARD;
+ (*KeywordMap)["return"] = RETURN;
+ (*KeywordMap)["void"] = VOID;
+ (*KeywordMap)["bool"] = BOOL;
+ (*KeywordMap)["float"] = FLOAT;
+ (*KeywordMap)["int"] = INT;
+ (*KeywordMap)["bvec2"] = BVEC2;
+ (*KeywordMap)["bvec3"] = BVEC3;
+ (*KeywordMap)["bvec4"] = BVEC4;
+ (*KeywordMap)["vec2"] = VEC2;
+ (*KeywordMap)["vec3"] = VEC3;
+ (*KeywordMap)["vec4"] = VEC4;
+ (*KeywordMap)["ivec2"] = IVEC2;
+ (*KeywordMap)["ivec3"] = IVEC3;
+ (*KeywordMap)["ivec4"] = IVEC4;
+ (*KeywordMap)["mat2"] = MAT2;
+ (*KeywordMap)["mat3"] = MAT3;
+ (*KeywordMap)["mat4"] = MAT4;
+ (*KeywordMap)["true"] = BOOLCONSTANT;
+ (*KeywordMap)["false"] = BOOLCONSTANT;
+ (*KeywordMap)["attribute"] = ATTRIBUTE;
+ (*KeywordMap)["varying"] = VARYING;
+ (*KeywordMap)["buffer"] = BUFFER;
+ (*KeywordMap)["coherent"] = COHERENT;
+ (*KeywordMap)["restrict"] = RESTRICT;
+ (*KeywordMap)["readonly"] = READONLY;
+ (*KeywordMap)["writeonly"] = WRITEONLY;
+ (*KeywordMap)["atomic_uint"] = ATOMIC_UINT;
+ (*KeywordMap)["volatile"] = VOLATILE;
+ (*KeywordMap)["layout"] = LAYOUT;
+ (*KeywordMap)["shared"] = SHARED;
+ (*KeywordMap)["patch"] = PATCH;
+ (*KeywordMap)["sample"] = SAMPLE;
+ (*KeywordMap)["subroutine"] = SUBROUTINE;
+ (*KeywordMap)["highp"] = HIGH_PRECISION;
+ (*KeywordMap)["mediump"] = MEDIUM_PRECISION;
+ (*KeywordMap)["lowp"] = LOW_PRECISION;
+ (*KeywordMap)["precision"] = PRECISION;
+ (*KeywordMap)["mat2x2"] = MAT2X2;
+ (*KeywordMap)["mat2x3"] = MAT2X3;
+ (*KeywordMap)["mat2x4"] = MAT2X4;
+ (*KeywordMap)["mat3x2"] = MAT3X2;
+ (*KeywordMap)["mat3x3"] = MAT3X3;
+ (*KeywordMap)["mat3x4"] = MAT3X4;
+ (*KeywordMap)["mat4x2"] = MAT4X2;
+ (*KeywordMap)["mat4x3"] = MAT4X3;
+ (*KeywordMap)["mat4x4"] = MAT4X4;
+ (*KeywordMap)["dmat2"] = DMAT2;
+ (*KeywordMap)["dmat3"] = DMAT3;
+ (*KeywordMap)["dmat4"] = DMAT4;
+ (*KeywordMap)["dmat2x2"] = DMAT2X2;
+ (*KeywordMap)["dmat2x3"] = DMAT2X3;
+ (*KeywordMap)["dmat2x4"] = DMAT2X4;
+ (*KeywordMap)["dmat3x2"] = DMAT3X2;
+ (*KeywordMap)["dmat3x3"] = DMAT3X3;
+ (*KeywordMap)["dmat3x4"] = DMAT3X4;
+ (*KeywordMap)["dmat4x2"] = DMAT4X2;
+ (*KeywordMap)["dmat4x3"] = DMAT4X3;
+ (*KeywordMap)["dmat4x4"] = DMAT4X4;
+ (*KeywordMap)["image1D"] = IMAGE1D;
+ (*KeywordMap)["iimage1D"] = IIMAGE1D;
+ (*KeywordMap)["uimage1D"] = UIMAGE1D;
+ (*KeywordMap)["image2D"] = IMAGE2D;
+ (*KeywordMap)["iimage2D"] = IIMAGE2D;
+ (*KeywordMap)["uimage2D"] = UIMAGE2D;
+ (*KeywordMap)["image3D"] = IMAGE3D;
+ (*KeywordMap)["iimage3D"] = IIMAGE3D;
+ (*KeywordMap)["uimage3D"] = UIMAGE3D;
+ (*KeywordMap)["image2DRect"] = IMAGE2DRECT;
+ (*KeywordMap)["iimage2DRect"] = IIMAGE2DRECT;
+ (*KeywordMap)["uimage2DRect"] = UIMAGE2DRECT;
+ (*KeywordMap)["imageCube"] = IMAGECUBE;
+ (*KeywordMap)["iimageCube"] = IIMAGECUBE;
+ (*KeywordMap)["uimageCube"] = UIMAGECUBE;
+ (*KeywordMap)["imageBuffer"] = IMAGEBUFFER;
+ (*KeywordMap)["iimageBuffer"] = IIMAGEBUFFER;
+ (*KeywordMap)["uimageBuffer"] = UIMAGEBUFFER;
+ (*KeywordMap)["image1DArray"] = IMAGE1DARRAY;
+ (*KeywordMap)["iimage1DArray"] = IIMAGE1DARRAY;
+ (*KeywordMap)["uimage1DArray"] = UIMAGE1DARRAY;
+ (*KeywordMap)["image2DArray"] = IMAGE2DARRAY;
+ (*KeywordMap)["iimage2DArray"] = IIMAGE2DARRAY;
+ (*KeywordMap)["uimage2DArray"] = UIMAGE2DARRAY;
+ (*KeywordMap)["imageCubeArray"] = IMAGECUBEARRAY;
+ (*KeywordMap)["iimageCubeArray"] = IIMAGECUBEARRAY;
+ (*KeywordMap)["uimageCubeArray"] = UIMAGECUBEARRAY;
+ (*KeywordMap)["image2DMS"] = IMAGE2DMS;
+ (*KeywordMap)["iimage2DMS"] = IIMAGE2DMS;
+ (*KeywordMap)["uimage2DMS"] = UIMAGE2DMS;
+ (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
+ (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
+ (*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY;
+ (*KeywordMap)["double"] = DOUBLE;
+ (*KeywordMap)["dvec2"] = DVEC2;
+ (*KeywordMap)["dvec3"] = DVEC3;
+ (*KeywordMap)["dvec4"] = DVEC4;
+ (*KeywordMap)["uint"] = UINT;
+ (*KeywordMap)["uvec2"] = UVEC2;
+ (*KeywordMap)["uvec3"] = UVEC3;
+ (*KeywordMap)["uvec4"] = UVEC4;
+
+ (*KeywordMap)["int64_t"] = INT64_T;
+ (*KeywordMap)["uint64_t"] = UINT64_T;
+ (*KeywordMap)["i64vec2"] = I64VEC2;
+ (*KeywordMap)["i64vec3"] = I64VEC3;
+ (*KeywordMap)["i64vec4"] = I64VEC4;
+ (*KeywordMap)["u64vec2"] = U64VEC2;
+ (*KeywordMap)["u64vec3"] = U64VEC3;
+ (*KeywordMap)["u64vec4"] = U64VEC4;
+
+ (*KeywordMap)["sampler2D"] = SAMPLER2D;
+ (*KeywordMap)["samplerCube"] = SAMPLERCUBE;
+ (*KeywordMap)["samplerCubeArray"] = SAMPLERCUBEARRAY;
+ (*KeywordMap)["samplerCubeArrayShadow"] = SAMPLERCUBEARRAYSHADOW;
+ (*KeywordMap)["isamplerCubeArray"] = ISAMPLERCUBEARRAY;
+ (*KeywordMap)["usamplerCubeArray"] = USAMPLERCUBEARRAY;
+ (*KeywordMap)["sampler1DArrayShadow"] = SAMPLER1DARRAYSHADOW;
+ (*KeywordMap)["isampler1DArray"] = ISAMPLER1DARRAY;
+ (*KeywordMap)["usampler1D"] = USAMPLER1D;
+ (*KeywordMap)["isampler1D"] = ISAMPLER1D;
+ (*KeywordMap)["usampler1DArray"] = USAMPLER1DARRAY;
+ (*KeywordMap)["samplerBuffer"] = SAMPLERBUFFER;
+ (*KeywordMap)["samplerCubeShadow"] = SAMPLERCUBESHADOW;
+ (*KeywordMap)["sampler2DArray"] = SAMPLER2DARRAY;
+ (*KeywordMap)["sampler2DArrayShadow"] = SAMPLER2DARRAYSHADOW;
+ (*KeywordMap)["isampler2D"] = ISAMPLER2D;
+ (*KeywordMap)["isampler3D"] = ISAMPLER3D;
+ (*KeywordMap)["isamplerCube"] = ISAMPLERCUBE;
+ (*KeywordMap)["isampler2DArray"] = ISAMPLER2DARRAY;
+ (*KeywordMap)["usampler2D"] = USAMPLER2D;
+ (*KeywordMap)["usampler3D"] = USAMPLER3D;
+ (*KeywordMap)["usamplerCube"] = USAMPLERCUBE;
+ (*KeywordMap)["usampler2DArray"] = USAMPLER2DARRAY;
+ (*KeywordMap)["isampler2DRect"] = ISAMPLER2DRECT;
+ (*KeywordMap)["usampler2DRect"] = USAMPLER2DRECT;
+ (*KeywordMap)["isamplerBuffer"] = ISAMPLERBUFFER;
+ (*KeywordMap)["usamplerBuffer"] = USAMPLERBUFFER;
+ (*KeywordMap)["sampler2DMS"] = SAMPLER2DMS;
+ (*KeywordMap)["isampler2DMS"] = ISAMPLER2DMS;
+ (*KeywordMap)["usampler2DMS"] = USAMPLER2DMS;
+ (*KeywordMap)["sampler2DMSArray"] = SAMPLER2DMSARRAY;
+ (*KeywordMap)["isampler2DMSArray"] = ISAMPLER2DMSARRAY;
+ (*KeywordMap)["usampler2DMSArray"] = USAMPLER2DMSARRAY;
+ (*KeywordMap)["sampler1D"] = SAMPLER1D;
+ (*KeywordMap)["sampler1DShadow"] = SAMPLER1DSHADOW;
+ (*KeywordMap)["sampler3D"] = SAMPLER3D;
+ (*KeywordMap)["sampler2DShadow"] = SAMPLER2DSHADOW;
+ (*KeywordMap)["sampler2DRect"] = SAMPLER2DRECT;
+ (*KeywordMap)["sampler2DRectShadow"] = SAMPLER2DRECTSHADOW;
+ (*KeywordMap)["sampler1DArray"] = SAMPLER1DARRAY;
+
+ (*KeywordMap)["samplerExternalOES"] = SAMPLEREXTERNALOES; // GL_OES_EGL_image_external
+
+ (*KeywordMap)["sampler"] = SAMPLER;
+ (*KeywordMap)["samplerShadow"] = SAMPLERSHADOW;
+
+ (*KeywordMap)["texture2D"] = TEXTURE2D;
+ (*KeywordMap)["textureCube"] = TEXTURECUBE;
+ (*KeywordMap)["textureCubeArray"] = TEXTURECUBEARRAY;
+ (*KeywordMap)["itextureCubeArray"] = ITEXTURECUBEARRAY;
+ (*KeywordMap)["utextureCubeArray"] = UTEXTURECUBEARRAY;
+ (*KeywordMap)["itexture1DArray"] = ITEXTURE1DARRAY;
+ (*KeywordMap)["utexture1D"] = UTEXTURE1D;
+ (*KeywordMap)["itexture1D"] = ITEXTURE1D;
+ (*KeywordMap)["utexture1DArray"] = UTEXTURE1DARRAY;
+ (*KeywordMap)["textureBuffer"] = TEXTUREBUFFER;
+ (*KeywordMap)["texture2DArray"] = TEXTURE2DARRAY;
+ (*KeywordMap)["itexture2D"] = ITEXTURE2D;
+ (*KeywordMap)["itexture3D"] = ITEXTURE3D;
+ (*KeywordMap)["itextureCube"] = ITEXTURECUBE;
+ (*KeywordMap)["itexture2DArray"] = ITEXTURE2DARRAY;
+ (*KeywordMap)["utexture2D"] = UTEXTURE2D;
+ (*KeywordMap)["utexture3D"] = UTEXTURE3D;
+ (*KeywordMap)["utextureCube"] = UTEXTURECUBE;
+ (*KeywordMap)["utexture2DArray"] = UTEXTURE2DARRAY;
+ (*KeywordMap)["itexture2DRect"] = ITEXTURE2DRECT;
+ (*KeywordMap)["utexture2DRect"] = UTEXTURE2DRECT;
+ (*KeywordMap)["itextureBuffer"] = ITEXTUREBUFFER;
+ (*KeywordMap)["utextureBuffer"] = UTEXTUREBUFFER;
+ (*KeywordMap)["texture2DMS"] = TEXTURE2DMS;
+ (*KeywordMap)["itexture2DMS"] = ITEXTURE2DMS;
+ (*KeywordMap)["utexture2DMS"] = UTEXTURE2DMS;
+ (*KeywordMap)["texture2DMSArray"] = TEXTURE2DMSARRAY;
+ (*KeywordMap)["itexture2DMSArray"] = ITEXTURE2DMSARRAY;
+ (*KeywordMap)["utexture2DMSArray"] = UTEXTURE2DMSARRAY;
+ (*KeywordMap)["texture1D"] = TEXTURE1D;
+ (*KeywordMap)["texture3D"] = TEXTURE3D;
+ (*KeywordMap)["texture2DRect"] = TEXTURE2DRECT;
+ (*KeywordMap)["texture1DArray"] = TEXTURE1DARRAY;
+
+ (*KeywordMap)["subpassInput"] = SUBPASSINPUT;
+ (*KeywordMap)["subpassInputMS"] = SUBPASSINPUTMS;
+ (*KeywordMap)["isubpassInput"] = ISUBPASSINPUT;
+ (*KeywordMap)["isubpassInputMS"] = ISUBPASSINPUTMS;
+ (*KeywordMap)["usubpassInput"] = USUBPASSINPUT;
+ (*KeywordMap)["usubpassInputMS"] = USUBPASSINPUTMS;
+
+ (*KeywordMap)["noperspective"] = NOPERSPECTIVE;
+ (*KeywordMap)["smooth"] = SMOOTH;
+ (*KeywordMap)["flat"] = FLAT;
+ (*KeywordMap)["centroid"] = CENTROID;
+ (*KeywordMap)["precise"] = PRECISE;
+ (*KeywordMap)["invariant"] = INVARIANT;
+ (*KeywordMap)["packed"] = PACKED;
+ (*KeywordMap)["resource"] = RESOURCE;
+ (*KeywordMap)["superp"] = SUPERP;
+
+ ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
+
+ ReservedSet->insert("common");
+ ReservedSet->insert("partition");
+ ReservedSet->insert("active");
+ ReservedSet->insert("asm");
+ ReservedSet->insert("class");
+ ReservedSet->insert("union");
+ ReservedSet->insert("enum");
+ ReservedSet->insert("typedef");
+ ReservedSet->insert("template");
+ ReservedSet->insert("this");
+ ReservedSet->insert("goto");
+ ReservedSet->insert("inline");
+ ReservedSet->insert("noinline");
+ ReservedSet->insert("public");
+ ReservedSet->insert("static");
+ ReservedSet->insert("extern");
+ ReservedSet->insert("external");
+ ReservedSet->insert("interface");
+ ReservedSet->insert("long");
+ ReservedSet->insert("short");
+ ReservedSet->insert("half");
+ ReservedSet->insert("fixed");
+ ReservedSet->insert("unsigned");
+ ReservedSet->insert("input");
+ ReservedSet->insert("output");
+ ReservedSet->insert("hvec2");
+ ReservedSet->insert("hvec3");
+ ReservedSet->insert("hvec4");
+ ReservedSet->insert("fvec2");
+ ReservedSet->insert("fvec3");
+ ReservedSet->insert("fvec4");
+ ReservedSet->insert("sampler3DRect");
+ ReservedSet->insert("filter");
+ ReservedSet->insert("sizeof");
+ ReservedSet->insert("cast");
+ ReservedSet->insert("namespace");
+ ReservedSet->insert("using");
+}
+
+void TScanContext::deleteKeywordMap()
+{
+ delete KeywordMap;
+ KeywordMap = nullptr;
+ delete ReservedSet;
+ ReservedSet = nullptr;
+}
+
+int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
+{
+ do {
+ parserToken = &token;
+ TPpToken ppToken;
+ tokenText = pp->tokenize(&ppToken);
+ if (tokenText == nullptr)
+ return 0;
+
+ loc = ppToken.loc;
+ parserToken->sType.lex.loc = loc;
+ switch (ppToken.token) {
+ case ';': afterType = false; return SEMICOLON;
+ case ',': afterType = false; return COMMA;
+ case ':': return COLON;
+ case '=': afterType = false; return EQUAL;
+ case '(': afterType = false; return LEFT_PAREN;
+ case ')': afterType = false; return RIGHT_PAREN;
+ case '.': field = true; return DOT;
+ case '!': return BANG;
+ case '-': return DASH;
+ case '~': return TILDE;
+ case '+': return PLUS;
+ case '*': return STAR;
+ case '/': return SLASH;
+ case '%': return PERCENT;
+ case '<': return LEFT_ANGLE;
+ case '>': return RIGHT_ANGLE;
+ case '|': return VERTICAL_BAR;
+ case '^': return CARET;
+ case '&': return AMPERSAND;
+ case '?': return QUESTION;
+ case '[': return LEFT_BRACKET;
+ case ']': return RIGHT_BRACKET;
+ case '{': return LEFT_BRACE;
+ case '}': return RIGHT_BRACE;
+ case '\\':
+ parseContext.error(loc, "illegal use of escape character", "\\", "");
+ break;
+
+ case PpAtomAdd: return ADD_ASSIGN;
+ case PpAtomSub: return SUB_ASSIGN;
+ case PpAtomMul: return MUL_ASSIGN;
+ case PpAtomDiv: return DIV_ASSIGN;
+ case PpAtomMod: return MOD_ASSIGN;
+
+ case PpAtomRight: return RIGHT_OP;
+ case PpAtomLeft: return LEFT_OP;
+
+ case PpAtomRightAssign: return RIGHT_ASSIGN;
+ case PpAtomLeftAssign: return LEFT_ASSIGN;
+ case PpAtomAndAssign: return AND_ASSIGN;
+ case PpAtomOrAssign: return OR_ASSIGN;
+ case PpAtomXorAssign: return XOR_ASSIGN;
+
+ case PpAtomAnd: return AND_OP;
+ case PpAtomOr: return OR_OP;
+ case PpAtomXor: return XOR_OP;
+
+ case PpAtomEQ: return EQ_OP;
+ case PpAtomGE: return GE_OP;
+ case PpAtomNE: return NE_OP;
+ case PpAtomLE: return LE_OP;
+
+ case PpAtomDecrement: return DEC_OP;
+ case PpAtomIncrement: return INC_OP;
+
+ case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
+ case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
+ case PpAtomConstInt64: parserToken->sType.lex.i64 = ppToken.i64val; return INT64CONSTANT;
+ case PpAtomConstUint64: parserToken->sType.lex.i64 = ppToken.i64val; return UINT64CONSTANT;
+ case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
+ case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
+ case PpAtomIdentifier:
+ {
+ int token = tokenizeIdentifier();
+ field = false;
+ return token;
+ }
+
+ case EndOfInput: return 0;
+
+ default:
+ char buf[2];
+ buf[0] = (char)ppToken.token;
+ buf[1] = 0;
+ parseContext.error(loc, "unexpected token", buf, "");
+ break;
+ }
+ } while (true);
+}
+
+int TScanContext::tokenizeIdentifier()
+{
+ if (ReservedSet->find(tokenText) != ReservedSet->end())
+ return reservedWord();
+
+ auto it = KeywordMap->find(tokenText);
+ if (it == KeywordMap->end()) {
+ // Should have an identifier of some sort
+ return identifierOrType();
+ }
+ keyword = it->second;
+
+ switch (keyword) {
+ case CONST:
+ case UNIFORM:
+ case IN:
+ case OUT:
+ case INOUT:
+ case STRUCT:
+ case BREAK:
+ case CONTINUE:
+ case DO:
+ case FOR:
+ case WHILE:
+ case IF:
+ case ELSE:
+ case DISCARD:
+ case RETURN:
+ case CASE:
+ return keyword;
+
+ case SWITCH:
+ case DEFAULT:
+ if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 130))
+ reservedWord();
+ return keyword;
+
+ case VOID:
+ case BOOL:
+ case FLOAT:
+ case INT:
+ case BVEC2:
+ case BVEC3:
+ case BVEC4:
+ case VEC2:
+ case VEC3:
+ case VEC4:
+ case IVEC2:
+ case IVEC3:
+ case IVEC4:
+ case MAT2:
+ case MAT3:
+ case MAT4:
+ case SAMPLER2D:
+ case SAMPLERCUBE:
+ afterType = true;
+ return keyword;
+
+ case BOOLCONSTANT:
+ if (strcmp("true", tokenText) == 0)
+ parserToken->sType.lex.b = true;
+ else
+ parserToken->sType.lex.b = false;
+ return keyword;
+
+ case ATTRIBUTE:
+ case VARYING:
+ if (parseContext.profile == EEsProfile && parseContext.version >= 300)
+ reservedWord();
+ return keyword;
+
+ case BUFFER:
+ if ((parseContext.profile == EEsProfile && parseContext.version < 310) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 430))
+ return identifierOrType();
+ return keyword;
+
+ case ATOMIC_UINT:
+ if ((parseContext.profile == EEsProfile && parseContext.version >= 310) ||
+ parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
+ return keyword;
+ return es30ReservedFromGLSL(420);
+
+ case COHERENT:
+ case RESTRICT:
+ case READONLY:
+ case WRITEONLY:
+ if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+ return keyword;
+ return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420);
+
+ case VOLATILE:
+ if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+ return keyword;
+ if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
+ reservedWord();
+ return keyword;
+
+ case LAYOUT:
+ {
+ const int numLayoutExts = 2;
+ const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack,
+ E_GL_ARB_explicit_attrib_location };
+ if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 140 &&
+ ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts)))
+ return identifierOrType();
+ return keyword;
+ }
+ case SHARED:
+ if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 140))
+ return identifierOrType();
+ return keyword;
+
+ case PATCH:
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ (parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) ||
+ (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
+ return keyword;
+
+ return es30ReservedFromGLSL(400);
+
+ case SAMPLE:
+ if (parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
+ return keyword;
+ return es30ReservedFromGLSL(400);
+
+ case SUBROUTINE:
+ return es30ReservedFromGLSL(400);
+
+ case HIGH_PRECISION:
+ case MEDIUM_PRECISION:
+ case LOW_PRECISION:
+ case PRECISION:
+ return precisionKeyword();
+
+ case MAT2X2:
+ case MAT2X3:
+ case MAT2X4:
+ case MAT3X2:
+ case MAT3X3:
+ case MAT3X4:
+ case MAT4X2:
+ case MAT4X3:
+ case MAT4X4:
+ return matNxM();
+
+ case DMAT2:
+ case DMAT3:
+ case DMAT4:
+ case DMAT2X2:
+ case DMAT2X3:
+ case DMAT2X4:
+ case DMAT3X2:
+ case DMAT3X3:
+ case DMAT3X4:
+ case DMAT4X2:
+ case DMAT4X3:
+ case DMAT4X4:
+ return dMat();
+
+ case IMAGE1D:
+ case IIMAGE1D:
+ case UIMAGE1D:
+ case IMAGE1DARRAY:
+ case IIMAGE1DARRAY:
+ case UIMAGE1DARRAY:
+ case IMAGE2DRECT:
+ case IIMAGE2DRECT:
+ case UIMAGE2DRECT:
+ afterType = true;
+ return firstGenerationImage(false);
+
+ case IMAGEBUFFER:
+ case IIMAGEBUFFER:
+ case UIMAGEBUFFER:
+ afterType = true;
+ if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+ return keyword;
+ return firstGenerationImage(false);
+
+ case IMAGE2D:
+ case IIMAGE2D:
+ case UIMAGE2D:
+ case IMAGE3D:
+ case IIMAGE3D:
+ case UIMAGE3D:
+ case IMAGECUBE:
+ case IIMAGECUBE:
+ case UIMAGECUBE:
+ case IMAGE2DARRAY:
+ case IIMAGE2DARRAY:
+ case UIMAGE2DARRAY:
+ afterType = true;
+ return firstGenerationImage(true);
+
+ case IMAGECUBEARRAY:
+ case IIMAGECUBEARRAY:
+ case UIMAGECUBEARRAY:
+ afterType = true;
+ if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+ return keyword;
+ return secondGenerationImage();
+
+ case IMAGE2DMS:
+ case IIMAGE2DMS:
+ case UIMAGE2DMS:
+ case IMAGE2DMSARRAY:
+ case IIMAGE2DMSARRAY:
+ case UIMAGE2DMSARRAY:
+ afterType = true;
+ return secondGenerationImage();
+
+ case DOUBLE:
+ case DVEC2:
+ case DVEC3:
+ case DVEC4:
+ afterType = true;
+ if (parseContext.profile == EEsProfile || parseContext.version < 400)
+ reservedWord();
+ return keyword;
+
+ case INT64_T:
+ case UINT64_T:
+ case I64VEC2:
+ case I64VEC3:
+ case I64VEC4:
+ case U64VEC2:
+ case U64VEC3:
+ case U64VEC4:
+ if (parseContext.profile != EEsProfile && parseContext.version >= 450)
+ return keyword;
+ return identifierOrType();
+
+ case SAMPLERCUBEARRAY:
+ case SAMPLERCUBEARRAYSHADOW:
+ case ISAMPLERCUBEARRAY:
+ case USAMPLERCUBEARRAY:
+ afterType = true;
+ if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
+ return keyword;
+ if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
+ reservedWord();
+ return keyword;
+
+ case ISAMPLER1D:
+ case ISAMPLER1DARRAY:
+ case SAMPLER1DARRAYSHADOW:
+ case USAMPLER1D:
+ case USAMPLER1DARRAY:
+ afterType = true;
+ return es30ReservedFromGLSL(130);
+
+ case UINT:
+ case UVEC2:
+ case UVEC3:
+ case UVEC4:
+ case SAMPLERCUBESHADOW:
+ case SAMPLER2DARRAY:
+ case SAMPLER2DARRAYSHADOW:
+ case ISAMPLER2D:
+ case ISAMPLER3D:
+ case ISAMPLERCUBE:
+ case ISAMPLER2DARRAY:
+ case USAMPLER2D:
+ case USAMPLER3D:
+ case USAMPLERCUBE:
+ case USAMPLER2DARRAY:
+ afterType = true;
+ return nonreservedKeyword(300, 130);
+
+ case ISAMPLER2DRECT:
+ case USAMPLER2DRECT:
+ afterType = true;
+ return es30ReservedFromGLSL(140);
+
+ case SAMPLERBUFFER:
+ afterType = true;
+ if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+ return keyword;
+ return es30ReservedFromGLSL(130);
+
+ case ISAMPLERBUFFER:
+ case USAMPLERBUFFER:
+ afterType = true;
+ if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
+ return keyword;
+ return es30ReservedFromGLSL(140);
+
+ case SAMPLER2DMS:
+ case ISAMPLER2DMS:
+ case USAMPLER2DMS:
+ afterType = true;
+ if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+ return keyword;
+ return es30ReservedFromGLSL(150);
+
+ case SAMPLER2DMSARRAY:
+ case ISAMPLER2DMSARRAY:
+ case USAMPLER2DMSARRAY:
+ afterType = true;
+ if (parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
+ return keyword;
+ return es30ReservedFromGLSL(150);
+
+ case SAMPLER1D:
+ case SAMPLER1DSHADOW:
+ afterType = true;
+ if (parseContext.profile == EEsProfile)
+ reservedWord();
+ return keyword;
+
+ case SAMPLER3D:
+ afterType = true;
+ if (parseContext.profile == EEsProfile && parseContext.version < 300) {
+ if (! parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
+ reservedWord();
+ }
+ return keyword;
+
+ case SAMPLER2DSHADOW:
+ afterType = true;
+ if (parseContext.profile == EEsProfile && parseContext.version < 300)
+ reservedWord();
+ return keyword;
+
+ case SAMPLER2DRECT:
+ case SAMPLER2DRECTSHADOW:
+ afterType = true;
+ if (parseContext.profile == EEsProfile)
+ reservedWord();
+ else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) {
+ if (parseContext.relaxedErrors())
+ parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword");
+ else
+ reservedWord();
+ }
+ return keyword;
+
+ case SAMPLER1DARRAY:
+ afterType = true;
+ if (parseContext.profile == EEsProfile && parseContext.version == 300)
+ reservedWord();
+ else if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 130))
+ return identifierOrType();
+ return keyword;
+
+ case SAMPLEREXTERNALOES:
+ afterType = true;
+ if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external))
+ return keyword;
+ return identifierOrType();
+
+ case TEXTURE2D:
+ case TEXTURECUBE:
+ case TEXTURECUBEARRAY:
+ case ITEXTURECUBEARRAY:
+ case UTEXTURECUBEARRAY:
+ case ITEXTURE1DARRAY:
+ case UTEXTURE1D:
+ case ITEXTURE1D:
+ case UTEXTURE1DARRAY:
+ case TEXTUREBUFFER:
+ case TEXTURE2DARRAY:
+ case ITEXTURE2D:
+ case ITEXTURE3D:
+ case ITEXTURECUBE:
+ case ITEXTURE2DARRAY:
+ case UTEXTURE2D:
+ case UTEXTURE3D:
+ case UTEXTURECUBE:
+ case UTEXTURE2DARRAY:
+ case ITEXTURE2DRECT:
+ case UTEXTURE2DRECT:
+ case ITEXTUREBUFFER:
+ case UTEXTUREBUFFER:
+ case TEXTURE2DMS:
+ case ITEXTURE2DMS:
+ case UTEXTURE2DMS:
+ case TEXTURE2DMSARRAY:
+ case ITEXTURE2DMSARRAY:
+ case UTEXTURE2DMSARRAY:
+ case TEXTURE1D:
+ case TEXTURE3D:
+ case TEXTURE2DRECT:
+ case TEXTURE1DARRAY:
+ case SAMPLER:
+ case SAMPLERSHADOW:
+ if (parseContext.spv > 0)
+ return keyword;
+ else
+ return identifierOrType();
+
+ case SUBPASSINPUT:
+ case SUBPASSINPUTMS:
+ case ISUBPASSINPUT:
+ case ISUBPASSINPUTMS:
+ case USUBPASSINPUT:
+ case USUBPASSINPUTMS:
+ if (parseContext.spv > 0)
+ return keyword;
+ else
+ return identifierOrType();
+
+ case NOPERSPECTIVE:
+ return es30ReservedFromGLSL(130);
+
+ case SMOOTH:
+ if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 130))
+ return identifierOrType();
+ return keyword;
+
+ case FLAT:
+ if (parseContext.profile == EEsProfile && parseContext.version < 300)
+ reservedWord();
+ else if (parseContext.profile != EEsProfile && parseContext.version < 130)
+ return identifierOrType();
+ return keyword;
+
+ case CENTROID:
+ if (parseContext.version < 120)
+ return identifierOrType();
+ return keyword;
+
+ case PRECISE:
+ if ((parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5)) ||
+ (parseContext.profile != EEsProfile && parseContext.version >= 400))
+ return keyword;
+ if (parseContext.profile == EEsProfile && parseContext.version == 310) {
+ reservedWord();
+ return keyword;
+ }
+ return identifierOrType();
+
+ case INVARIANT:
+ if (parseContext.profile != EEsProfile && parseContext.version < 120)
+ return identifierOrType();
+ return keyword;
+
+ case PACKED:
+ if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < 330))
+ return reservedWord();
+ return identifierOrType();
+
+ case RESOURCE:
+ {
+ bool reserved = (parseContext.profile == EEsProfile && parseContext.version >= 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version >= 420);
+ return identifierOrReserved(reserved);
+ }
+ case SUPERP:
+ {
+ bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130;
+ return identifierOrReserved(reserved);
+ }
+
+ default:
+ parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
+ return 0;
+ }
+}
+
+int TScanContext::identifierOrType()
+{
+ parserToken->sType.lex.string = NewPoolTString(tokenText);
+ if (field)
+ return IDENTIFIER;
+
+ parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
+ if (afterType == false && parserToken->sType.lex.symbol) {
+ if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
+ if (variable->isUserType()) {
+ afterType = true;
+
+ return TYPE_NAME;
+ }
+ }
+ }
+
+ return IDENTIFIER;
+}
+
+// Give an error for use of a reserved symbol.
+// However, allow built-in declarations to use reserved words, to allow
+// extension support before the extension is enabled.
+int TScanContext::reservedWord()
+{
+ if (! parseContext.symbolTable.atBuiltInLevel())
+ parseContext.error(loc, "Reserved word.", tokenText, "", "");
+
+ return 0;
+}
+
+int TScanContext::identifierOrReserved(bool reserved)
+{
+ if (reserved) {
+ reservedWord();
+
+ return 0;
+ }
+
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using future reserved keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+// For keywords that suddenly showed up on non-ES (not previously reserved)
+// but then got reserved by ES 3.0.
+int TScanContext::es30ReservedFromGLSL(int version)
+{
+ if (parseContext.symbolTable.atBuiltInLevel())
+ return keyword;
+
+ if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version < version)) {
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, "");
+
+ return identifierOrType();
+ } else if (parseContext.profile == EEsProfile && parseContext.version >= 300)
+ reservedWord();
+
+ return keyword;
+}
+
+// For a keyword that was never reserved, until it suddenly
+// showed up, both in an es version and a non-ES version.
+int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion)
+{
+ if ((parseContext.profile == EEsProfile && parseContext.version < esVersion) ||
+ (parseContext.profile != EEsProfile && parseContext.version < nonEsVersion)) {
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using future keyword", tokenText, "");
+
+ return identifierOrType();
+ }
+
+ return keyword;
+}
+
+int TScanContext::precisionKeyword()
+{
+ if (parseContext.profile == EEsProfile || parseContext.version >= 130)
+ return keyword;
+
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::matNxM()
+{
+ afterType = true;
+
+ if (parseContext.version > 110)
+ return keyword;
+
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::dMat()
+{
+ afterType = true;
+
+ if (parseContext.profile == EEsProfile && parseContext.version >= 300) {
+ reservedWord();
+
+ return keyword;
+ }
+
+ if (parseContext.profile != EEsProfile && parseContext.version >= 400)
+ return keyword;
+
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using future type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::firstGenerationImage(bool inEs310)
+{
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
+ (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
+ return keyword;
+
+ if ((parseContext.profile == EEsProfile && parseContext.version >= 300) ||
+ (parseContext.profile != EEsProfile && parseContext.version >= 130)) {
+ reservedWord();
+
+ return keyword;
+ }
+
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using future type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+int TScanContext::secondGenerationImage()
+{
+ if (parseContext.profile == EEsProfile && parseContext.version >= 310) {
+ reservedWord();
+ return keyword;
+ }
+
+ if (parseContext.symbolTable.atBuiltInLevel() ||
+ (parseContext.profile != EEsProfile &&
+ (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
+ return keyword;
+
+ if (parseContext.forwardCompatible)
+ parseContext.warn(loc, "using future type keyword", tokenText, "");
+
+ return identifierOrType();
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.h
new file mode 100644
index 00000000000..1cc437cb496
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Scan.h
@@ -0,0 +1,265 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _GLSLANG_SCAN_INCLUDED_
+#define _GLSLANG_SCAN_INCLUDED_
+
+#include "Versions.h"
+
+namespace glslang {
+
+// Use a global end-of-input character, so no tranlation is needed across
+// layers of encapsulation. Characters are all 8 bit, and positive, so there is
+// no aliasing of character 255 onto -1, for example.
+const int EndOfInput = -1;
+
+//
+// A character scanner that seamlessly, on read-only strings, reads across an
+// array of strings without assuming null termination.
+//
+class TInputScanner {
+public:
+ TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0, bool single = false) :
+ numSources(n),
+ sources(reinterpret_cast<const unsigned char* const *>(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters
+ lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), endOfFileReached(false)
+ {
+ loc = new TSourceLoc[numSources];
+ for (int i = 0; i < numSources; ++i) {
+ loc[i].init();
+ }
+ if (names != nullptr) {
+ for (int i = 0; i < numSources; ++i)
+ loc[i].name = names[i];
+ }
+ loc[currentSource].string = -stringBias;
+ loc[currentSource].line = 1;
+ loc[currentSource].column = 0;
+ logicalSourceLoc.string = 0;
+ logicalSourceLoc.line = 1;
+ logicalSourceLoc.column = 0;
+ logicalSourceLoc.name = loc[0].name;
+ }
+
+ virtual ~TInputScanner()
+ {
+ delete [] loc;
+ }
+
+ // retrieve the next character and advance one character
+ int get()
+ {
+ int ret = peek();
+ if (ret == EndOfInput) return ret;
+ ++loc[currentSource].column;
+ ++logicalSourceLoc.column;
+ if (ret == '\n') {
+ ++loc[currentSource].line;
+ ++logicalSourceLoc.line;
+ logicalSourceLoc.column = 0;
+ loc[currentSource].column = 0;
+ }
+ advance();
+
+ return ret;
+ }
+
+ // retrieve the next character, no advance
+ int peek()
+ {
+ if (currentSource >= numSources) {
+ endOfFileReached = true;
+ return EndOfInput;
+ }
+ // Make sure we do not read off the end of a string.
+ // N.B. Sources can have a length of 0.
+ int sourceToRead = currentSource;
+ size_t charToRead = currentChar;
+ while(charToRead >= lengths[sourceToRead]) {
+ charToRead = 0;
+ sourceToRead += 1;
+ if (sourceToRead >= numSources) {
+ return EndOfInput;
+ }
+ }
+
+ // Here, we care about making negative valued characters positive
+ return sources[sourceToRead][charToRead];
+ }
+
+ // go back one character
+ void unget()
+ {
+ // Do not roll back once we've reached the end of the file.
+ if (endOfFileReached) return;
+
+ if (currentChar > 0) {
+ --currentChar;
+ --loc[currentSource].column;
+ --logicalSourceLoc.column;
+ if (loc[currentSource].column < 0) {
+ // We've moved back past a new line. Find the
+ // previous newline (or start of the file) to compute
+ // the column count on the now current line.
+ size_t chIndex = currentChar;
+ while (chIndex > 0) {
+ if (sources[currentSource][chIndex] == '\n') {
+ break;
+ }
+ --chIndex;
+ }
+ logicalSourceLoc.column = (int)(currentChar - chIndex);
+ loc[currentSource].column = (int)(currentChar - chIndex);
+ }
+ } else {
+ do {
+ --currentSource;
+ } while (currentSource > 0 && lengths[currentSource] == 0);
+ if (lengths[currentSource] == 0) {
+ // set to 0 if we've backed up to the start of an empty string
+ currentChar = 0;
+ } else
+ currentChar = lengths[currentSource] - 1;
+ }
+ if (peek() == '\n') {
+ --loc[currentSource].line;
+ --logicalSourceLoc.line;
+ }
+ }
+
+ // for #line override
+ void setLine(int newLine)
+ {
+ logicalSourceLoc.line = newLine;
+ loc[getLastValidSourceIndex()].line = newLine;
+ }
+
+ // for #line override in filename based parsing
+ void setFile(const char* filename)
+ {
+ logicalSourceLoc.name = filename;
+ loc[getLastValidSourceIndex()].name = filename;
+ }
+
+ void setFile(const char* filename, size_t i)
+ {
+ if (i == getLastValidSourceIndex()) {
+ logicalSourceLoc.name = filename;
+ }
+ loc[i].name = filename;
+ }
+
+ void setString(int newString)
+ {
+ logicalSourceLoc.string = newString;
+ loc[getLastValidSourceIndex()].string = newString;
+ logicalSourceLoc.name = nullptr;
+ loc[getLastValidSourceIndex()].name = nullptr;
+ }
+
+ // for #include content indentation
+ void setColumn(int col)
+ {
+ logicalSourceLoc.column = col;
+ loc[getLastValidSourceIndex()].column = col;
+ }
+
+ const TSourceLoc& getSourceLoc() const
+ {
+ if (singleLogical) {
+ return logicalSourceLoc;
+ } else {
+ return loc[std::max(0, std::min(currentSource, numSources - finale - 1))];
+ }
+ }
+ // Returns the index (starting from 0) of the most recent valid source string we are reading from.
+ int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); }
+
+ void consumeWhiteSpace(bool& foundNonSpaceTab);
+ bool consumeComment();
+ void consumeWhitespaceComment(bool& foundNonSpaceTab);
+ bool scanVersion(int& version, EProfile& profile, bool& notFirstToken);
+
+protected:
+
+ // advance one character
+ void advance()
+ {
+ ++currentChar;
+ if (currentChar >= lengths[currentSource]) {
+ ++currentSource;
+ if (currentSource < numSources) {
+ loc[currentSource].string = loc[currentSource - 1].string + 1;
+ loc[currentSource].line = 1;
+ loc[currentSource].column = 0;
+ }
+ while (currentSource < numSources && lengths[currentSource] == 0) {
+ ++currentSource;
+ if (currentSource < numSources) {
+ loc[currentSource].string = loc[currentSource - 1].string + 1;
+ loc[currentSource].line = 1;
+ loc[currentSource].column = 0;
+ }
+ }
+ currentChar = 0;
+ }
+ }
+
+ int numSources; // number of strings in source
+ const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput
+ const size_t *lengths; // length of each string
+ int currentSource;
+ size_t currentChar;
+
+ // This is for reporting what string/line an error occurred on, and can be overridden by #line.
+ // It remembers the last state of each source string as it is left for the next one, so unget()
+ // can restore that state.
+ TSourceLoc* loc; // an array
+
+ int stringBias; // the first string that is the user's string number 0
+ int finale; // number of internal strings after user's last string
+
+ TSourceLoc logicalSourceLoc;
+ bool singleLogical; // treats the strings as a single logical string.
+ // locations will be reported from the first string.
+
+ // set to true once peak() returns EndOfFile, so that we won't roll back
+ // once we've reached EndOfFile.
+ bool endOfFileReached;
+};
+
+} // end namespace glslang
+
+#endif // _GLSLANG_SCAN_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/ScanContext.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/ScanContext.h
new file mode 100644
index 00000000000..f237bee9f29
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/ScanContext.h
@@ -0,0 +1,86 @@
+//
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// This holds context specific to the GLSL scanner, which
+// sits between the preprocessor scanner and parser.
+//
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
+class TPpContext;
+class TPpToken;
+class TParserToken;
+
+class TScanContext {
+public:
+ explicit TScanContext(TParseContextBase& pc) : parseContext(pc), afterType(false), field(false) { }
+ virtual ~TScanContext() { }
+
+ static void fillInKeywordMap();
+ static void deleteKeywordMap();
+
+ int tokenize(TPpContext*, TParserToken&);
+
+protected:
+ TScanContext(TScanContext&);
+ TScanContext& operator=(TScanContext&);
+
+ int tokenizeIdentifier();
+ int identifierOrType();
+ int reservedWord();
+ int identifierOrReserved(bool reserved);
+ int es30ReservedFromGLSL(int version);
+ int nonreservedKeyword(int esVersion, int nonEsVersion);
+ int precisionKeyword();
+ int matNxM();
+ int dMat();
+ int firstGenerationImage(bool inEs310);
+ int secondGenerationImage();
+
+ TParseContextBase& parseContext;
+ bool afterType; // true if we've recognized a type, so can only be looking for an identifier
+ bool field; // true if we're on a field, right after a '.'
+ TSourceLoc loc;
+ TParserToken* parserToken;
+ TPpToken* ppToken;
+
+ const char* tokenText;
+ int keyword;
+};
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp
new file mode 100644
index 00000000000..c2b56055f9f
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp
@@ -0,0 +1,1623 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013-2016 LunarG, Inc.
+//Copyright (C) 2015-2016 Google, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Implement the top-level of interface to the compiler/linker,
+// as defined in ShaderLang.h
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <memory>
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../../hlsl/hlslParseHelper.h"
+#include "../../hlsl/hlslParseables.h"
+#include "Scan.h"
+#include "ScanContext.h"
+
+#include "../Include/ShHandle.h"
+#include "../../OGLCompilersDLL/InitializeDll.h"
+
+#include "preprocessor/PpContext.h"
+
+#define SH_EXPORTING
+#include "../Public/ShaderLang.h"
+#include "reflection.h"
+#include "Initialize.h"
+
+namespace { // anonymous namespace for file-local functions and symbols
+
+using namespace glslang;
+
+// Create a language specific version of parseables.
+TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source)
+{
+ switch (source) {
+ case EShSourceGlsl: return new TBuiltIns(); // GLSL builtIns
+ case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics
+
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
+ return nullptr;
+ }
+}
+
+// Local mapping functions for making arrays of symbol tables....
+
+int MapVersionToIndex(int version)
+{
+ switch (version) {
+ case 100: return 0;
+ case 110: return 1;
+ case 120: return 2;
+ case 130: return 3;
+ case 140: return 4;
+ case 150: return 5;
+ case 300: return 6;
+ case 330: return 7;
+ case 400: return 8;
+ case 410: return 9;
+ case 420: return 10;
+ case 430: return 11;
+ case 440: return 12;
+ case 310: return 13;
+ case 450: return 14;
+ default: // |
+ return 0; // |
+ } // |
+} // V
+const int VersionCount = 15; // number of case statements above
+
+int MapProfileToIndex(EProfile profile)
+{
+ switch (profile) {
+ case ENoProfile: return 0;
+ case ECoreProfile: return 1;
+ case ECompatibilityProfile: return 2;
+ case EEsProfile: return 3;
+ default: // |
+ return 0; // |
+ } // |
+} // V
+const int ProfileCount = 4; // number of case statements above
+
+// only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins
+enum EPrecisionClass {
+ EPcGeneral,
+ EPcFragment,
+ EPcCount
+};
+
+// A process-global symbol table per version per profile for built-ins common
+// to multiple stages (languages), and a process-global symbol table per version
+// per profile per stage for built-ins unique to each stage. They will be sparsely
+// populated, so they will only be generated as needed.
+//
+// Each has a different set of built-ins, and we want to preserve that from
+// compile to compile.
+//
+TSymbolTable* CommonSymbolTable[VersionCount][ProfileCount][EPcCount] = {};
+TSymbolTable* SharedSymbolTables[VersionCount][ProfileCount][EShLangCount] = {};
+
+TPoolAllocator* PerProcessGPA = 0;
+
+//
+// Parse and add to the given symbol table the content of the given shader string.
+//
+bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, int spv, int vulkan, EShLanguage language, TInfoSink& infoSink,
+ TSymbolTable& symbolTable)
+{
+ TIntermediate intermediate(language, version, profile);
+
+ TParseContext parseContext(symbolTable, intermediate, true, version, profile, spv, vulkan, language, infoSink);
+ TShader::ForbidInclude includer;
+ TPpContext ppContext(parseContext, "", includer);
+ TScanContext scanContext(parseContext);
+ parseContext.setScanContext(&scanContext);
+ parseContext.setPpContext(&ppContext);
+
+ //
+ // Push the symbol table to give it an initial scope. This
+ // push should not have a corresponding pop, so that built-ins
+ // are preserved, and the test for an empty table fails.
+ //
+
+ symbolTable.push();
+
+ const char* builtInShaders[2];
+ size_t builtInLengths[2];
+ builtInShaders[0] = builtIns.c_str();
+ builtInLengths[0] = builtIns.size();
+
+ if (builtInLengths[0] == 0)
+ return true;
+
+ TInputScanner input(1, builtInShaders, builtInLengths);
+ if (! parseContext.parseShaderStrings(ppContext, input) != 0) {
+ infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+ printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str());
+ printf("%s\n", builtInShaders[0]);
+
+ return false;
+ }
+
+ return true;
+}
+
+int CommonIndex(EProfile profile, EShLanguage language)
+{
+ return (profile == EEsProfile && language == EShLangFragment) ? EPcFragment : EPcGeneral;
+}
+
+//
+// To initialize per-stage shared tables, with the common table already complete.
+//
+void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, int spv, int vulkan,
+ EShLanguage language, TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables)
+{
+ (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
+ InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spv, vulkan, language, infoSink, *symbolTables[language]);
+ builtInParseables.identifyBuiltIns(version, profile, spv, vulkan, language, *symbolTables[language]);
+ if (profile == EEsProfile && version >= 300)
+ (*symbolTables[language]).setNoBuiltInRedeclarations();
+ if (version == 110)
+ (*symbolTables[language]).setSeparateNameSpaces();
+}
+
+//
+// Initialize the full set of shareable symbol tables;
+// The common (cross-stage) and those shareable per-stage.
+//
+bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, EProfile profile, int spv, int vulkan, EShSource source)
+{
+ std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
+
+ builtInParseables->initialize(version, profile, spv, vulkan);
+
+ // do the common tables
+ InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spv, vulkan, EShLangVertex, infoSink, *commonTable[EPcGeneral]);
+ if (profile == EEsProfile)
+ InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spv, vulkan, EShLangFragment, infoSink, *commonTable[EPcFragment]);
+
+ // do the per-stage tables
+
+ // always have vertex and fragment
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spv, vulkan, EShLangVertex, infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spv, vulkan, EShLangFragment, infoSink, commonTable, symbolTables);
+
+ // check for tessellation
+ if ((profile != EEsProfile && version >= 150) ||
+ (profile == EEsProfile && version >= 310)) {
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spv, vulkan, EShLangTessControl, infoSink, commonTable, symbolTables);
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spv, vulkan, EShLangTessEvaluation, infoSink, commonTable, symbolTables);
+ }
+
+ // check for geometry
+ if ((profile != EEsProfile && version >= 150) ||
+ (profile == EEsProfile && version >= 310))
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spv, vulkan, EShLangGeometry, infoSink, commonTable, symbolTables);
+
+ // check for compute
+ if ((profile != EEsProfile && version >= 420) ||
+ (profile == EEsProfile && version >= 310))
+ InitializeStageSymbolTable(*builtInParseables, version, profile, spv, vulkan, EShLangCompute, infoSink, commonTable, symbolTables);
+
+ return true;
+}
+
+bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version,
+ EProfile profile, int spv, int vulkan, EShLanguage language, EShSource source)
+{
+ std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
+
+ builtInParseables->initialize(*resources, version, profile, spv, vulkan, language);
+ InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spv, vulkan, language, infoSink, symbolTable);
+ builtInParseables->identifyBuiltIns(version, profile, spv, vulkan, language, symbolTable, *resources);
+
+ return true;
+}
+
+//
+// To do this on the fly, we want to leave the current state of our thread's
+// pool allocator intact, so:
+// - Switch to a new pool for parsing the built-ins
+// - Do the parsing, which builds the symbol table, using the new pool
+// - Switch to the process-global pool to save a copy the resulting symbol table
+// - Free up the new pool used to parse the built-ins
+// - Switch back to the original thread's pool
+//
+// This only gets done the first time any thread needs a particular symbol table
+// (lazy evaluation).
+//
+void SetupBuiltinSymbolTable(int version, EProfile profile, int spv, int vulkan, EShSource source)
+{
+ TInfoSink infoSink;
+
+ // Make sure only one thread tries to do this at a time
+ glslang::GetGlobalLock();
+
+ // See if it's already been done for this version/profile combination
+ int versionIndex = MapVersionToIndex(version);
+ int profileIndex = MapProfileToIndex(profile);
+ if (CommonSymbolTable[versionIndex][profileIndex][EPcGeneral]) {
+ glslang::ReleaseGlobalLock();
+
+ return;
+ }
+
+ // Switch to a new pool
+ TPoolAllocator& previousAllocator = GetThreadPoolAllocator();
+ TPoolAllocator* builtInPoolAllocator = new TPoolAllocator();
+ SetThreadPoolAllocator(*builtInPoolAllocator);
+
+ // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped.
+ TSymbolTable* commonTable[EPcCount];
+ TSymbolTable* stageTables[EShLangCount];
+ for (int precClass = 0; precClass < EPcCount; ++precClass)
+ commonTable[precClass] = new TSymbolTable;
+ for (int stage = 0; stage < EShLangCount; ++stage)
+ stageTables[stage] = new TSymbolTable;
+
+ // Generate the local symbol tables using the new pool
+ InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spv, vulkan, source);
+
+ // Switch to the process-global pool
+ SetThreadPoolAllocator(*PerProcessGPA);
+
+ // Copy the local symbol tables from the new pool to the global tables using the process-global pool
+ for (int precClass = 0; precClass < EPcCount; ++precClass) {
+ if (! commonTable[precClass]->isEmpty()) {
+ CommonSymbolTable[versionIndex][profileIndex][precClass] = new TSymbolTable;
+ CommonSymbolTable[versionIndex][profileIndex][precClass]->copyTable(*commonTable[precClass]);
+ CommonSymbolTable[versionIndex][profileIndex][precClass]->readOnly();
+ }
+ }
+ for (int stage = 0; stage < EShLangCount; ++stage) {
+ if (! stageTables[stage]->isEmpty()) {
+ SharedSymbolTables[versionIndex][profileIndex][stage] = new TSymbolTable;
+ SharedSymbolTables[versionIndex][profileIndex][stage]->adoptLevels(*CommonSymbolTable[versionIndex][profileIndex][CommonIndex(profile, (EShLanguage)stage)]);
+ SharedSymbolTables[versionIndex][profileIndex][stage]->copyTable(*stageTables[stage]);
+ SharedSymbolTables[versionIndex][profileIndex][stage]->readOnly();
+ }
+ }
+
+ // Clean up the local tables before deleting the pool they used.
+ for (int precClass = 0; precClass < EPcCount; ++precClass)
+ delete commonTable[precClass];
+ for (int stage = 0; stage < EShLangCount; ++stage)
+ delete stageTables[stage];
+
+ delete builtInPoolAllocator;
+ SetThreadPoolAllocator(previousAllocator);
+
+ glslang::ReleaseGlobalLock();
+}
+
+// Return true if the shader was correctly specified for version/profile/stage.
+bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion,
+ EShSource source, int& version, EProfile& profile, int spv)
+{
+ const int FirstProfileVersion = 150;
+ bool correct = true;
+
+ if (source == EShSourceHlsl) {
+ version = 450; // TODO: GLSL parser is still used for builtins.
+ profile = ENoProfile;
+ return correct;
+ }
+
+ // Get a good version...
+ if (version == 0) {
+ version = defaultVersion;
+ // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader");
+ }
+
+ // Get a good profile...
+ if (profile == ENoProfile) {
+ if (version == 300 || version == 310) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: versions 300 and 310 require specifying the 'es' profile");
+ profile = EEsProfile;
+ } else if (version == 100)
+ profile = EEsProfile;
+ else if (version >= FirstProfileVersion)
+ profile = ECoreProfile;
+ else
+ profile = ENoProfile;
+ } else {
+ // a profile was provided...
+ if (version < 150) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token");
+ if (version == 100)
+ profile = EEsProfile;
+ else
+ profile = ENoProfile;
+ } else if (version == 300 || version == 310) {
+ if (profile != EEsProfile) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: versions 300 and 310 support only the es profile");
+ }
+ profile = EEsProfile;
+ } else {
+ if (profile == EEsProfile) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: only version 300 and 310 support the es profile");
+ if (version >= FirstProfileVersion)
+ profile = ECoreProfile;
+ else
+ profile = ENoProfile;
+ }
+ // else: typical desktop case... e.g., "#version 410 core"
+ }
+ }
+
+ // Correct for stage type...
+ switch (stage) {
+ case EShLangGeometry:
+ if ((profile == EEsProfile && version < 310) ||
+ (profile != EEsProfile && version < 150)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above");
+ version = (profile == EEsProfile) ? 310 : 150;
+ if (profile == EEsProfile || profile == ENoProfile)
+ profile = ECoreProfile;
+ }
+ break;
+ case EShLangTessControl:
+ case EShLangTessEvaluation:
+ if ((profile == EEsProfile && version < 310) ||
+ (profile != EEsProfile && version < 150)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above");
+ version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not
+ if (profile == EEsProfile || profile == ENoProfile)
+ profile = ECoreProfile;
+ }
+ break;
+ case EShLangCompute:
+ if ((profile == EEsProfile && version < 310) ||
+ (profile != EEsProfile && version < 420)) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above");
+ version = profile == EEsProfile ? 310 : 420;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (profile == EEsProfile && version >= 300 && versionNotFirst) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines");
+ }
+
+ // Check for SPIR-V compatibility
+ if (spv > 0) {
+ if (profile == EEsProfile) {
+ if (version < 310) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: ES shaders for SPIR-V require version 310 or higher");
+ version = 310;
+ }
+ } else {
+ if (version < 140) {
+ correct = false;
+ infoSink.info.message(EPrefixError, "#version: Desktop shaders for SPIR-V require version 140 or higher");
+ version = 140;
+ }
+ }
+ }
+
+ // A meta check on the condition of the compiler itself...
+ switch (version) {
+
+ // ES versions
+ case 100:
+ case 300:
+ // versions are complete
+ break;
+
+ // Desktop versions
+ case 110:
+ case 120:
+ case 130:
+ case 140:
+ case 150:
+ case 330:
+ // versions are complete
+ break;
+
+ case 310:
+ case 400:
+ case 410:
+ case 420:
+ case 430:
+ case 440:
+ case 450:
+ infoSink.info << "Warning, version " << version << " is not yet complete; most version-specific features are present, but some are missing.\n";
+ break;
+
+ default:
+ infoSink.info << "Warning, version " << version << " is unknown.\n";
+ break;
+
+ }
+
+ return correct;
+}
+
+// This is the common setup and cleanup code for PreprocessDeferred and
+// CompileDeferred.
+// It takes any callable with a signature of
+// bool (TParseContextBase& parseContext, TPpContext& ppContext,
+// TInputScanner& input, bool versionWillBeError,
+// TSymbolTable& , TIntermediate& ,
+// EShOptimizationLevel , EShMessages );
+// Which returns false if a failure was detected and true otherwise.
+//
+template<typename ProcessingContext>
+bool ProcessDeferred(
+ TCompiler* compiler,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const char* const stringNames[],
+ const char* customPreamble,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan
+ EProfile defaultProfile,
+ // set version/profile to defaultVersion/defaultProfile regardless of the #version
+ // directive in the source code
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages, // warnings/errors/AST; things to print out
+ TIntermediate& intermediate, // returned tree, etc.
+ ProcessingContext& processingContext,
+ bool requireNonempty,
+ TShader::Includer& includer
+ )
+{
+ if (! InitThread())
+ return false;
+
+ // This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
+ GetThreadPoolAllocator().push();
+
+ if (numStrings == 0)
+ return true;
+
+ // Move to length-based strings, rather than null-terminated strings.
+ // Also, add strings to include the preamble and to ensure the shader is not null,
+ // which lets the grammar accept what was a null (post preprocessing) shader.
+ //
+ // Shader will look like
+ // string 0: system preamble
+ // string 1: custom preamble
+ // string 2...numStrings+1: user's shader
+ // string numStrings+2: "int;"
+ const int numPre = 2;
+ const int numPost = requireNonempty? 1 : 0;
+ const int numTotal = numPre + numStrings + numPost;
+ size_t* lengths = new size_t[numTotal];
+ const char** strings = new const char*[numTotal];
+ const char** names = new const char*[numTotal];
+ for (int s = 0; s < numStrings; ++s) {
+ strings[s + numPre] = shaderStrings[s];
+ if (inputLengths == 0 || inputLengths[s] < 0)
+ lengths[s + numPre] = strlen(shaderStrings[s]);
+ else
+ lengths[s + numPre] = inputLengths[s];
+ }
+ if (stringNames != nullptr) {
+ for (int s = 0; s < numStrings; ++s)
+ names[s + numPre] = stringNames[s];
+ } else {
+ for (int s = 0; s < numStrings; ++s)
+ names[s + numPre] = nullptr;
+ }
+
+ // First, without using the preprocessor or parser, find the #version, so we know what
+ // symbol tables, processing rules, etc. to set up. This does not need the extra strings
+ // outlined above, just the user shader.
+ int version;
+ EProfile profile;
+ glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]); // no preamble
+ bool versionNotFirstToken;
+ bool versionNotFirst = userInput.scanVersion(version, profile, versionNotFirstToken);
+ bool versionNotFound = version == 0;
+ if (forceDefaultVersionAndProfile) {
+ if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
+ (version != defaultVersion || profile != defaultProfile)) {
+ compiler->infoSink.info << "Warning, (version, profile) forced to be ("
+ << defaultVersion << ", " << ProfileName(defaultProfile)
+ << "), while in source code it is ("
+ << version << ", " << ProfileName(profile) << ")\n";
+ }
+
+ if (versionNotFound) {
+ versionNotFirstToken = false;
+ versionNotFirst = false;
+ versionNotFound = false;
+ }
+ version = defaultVersion;
+ profile = defaultProfile;
+ }
+ int spv = (messages & EShMsgSpvRules) ? 100 : 0; // TODO find path to get real version number here, for now non-0 is what matters
+ EShSource source = (messages & EShMsgReadHlsl) ? EShSourceHlsl : EShSourceGlsl;
+ bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, source, version, profile, spv);
+ bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
+ bool warnVersionNotFirst = false;
+ if (! versionWillBeError && versionNotFirstToken) {
+ if (messages & EShMsgRelaxedErrors)
+ warnVersionNotFirst = true;
+ else
+ versionWillBeError = true;
+ }
+
+ int vulkan = (messages & EShMsgVulkanRules) ? 100 : 0; // TODO find path to get real version number here, for now non-0 is what matters
+ intermediate.setSource(source);
+ intermediate.setVersion(version);
+ intermediate.setProfile(profile);
+ intermediate.setSpv(spv);
+ if (vulkan)
+ intermediate.setOriginUpperLeft();
+ SetupBuiltinSymbolTable(version, profile, spv, vulkan, source);
+
+ TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
+ [MapProfileToIndex(profile)]
+ [compiler->getLanguage()];
+
+ // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
+ TSymbolTable* symbolTableMemory = new TSymbolTable;
+ TSymbolTable& symbolTable = *symbolTableMemory;
+ if (cachedTable)
+ symbolTable.adoptLevels(*cachedTable);
+
+ // Add built-in symbols that are potentially context dependent;
+ // they get popped again further down.
+ AddContextSpecificSymbols(resources, compiler->infoSink, symbolTable, version, profile, spv, vulkan,
+ compiler->getLanguage(), source);
+
+ //
+ // Now we can process the full shader under proper symbols and rules.
+ //
+
+ TParseContextBase* parseContext;
+ if (source == EShSourceHlsl) {
+ parseContext = new HlslParseContext(symbolTable, intermediate, false, version, profile, spv, vulkan,
+ compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
+ }
+ else {
+ intermediate.setEntryPoint("main");
+ parseContext = new TParseContext(symbolTable, intermediate, false, version, profile, spv, vulkan,
+ compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
+ }
+ TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer);
+
+ // only GLSL (bison triggered, really) needs an externally set scan context
+ glslang::TScanContext scanContext(*parseContext);
+ if ((messages & EShMsgReadHlsl) == 0)
+ parseContext->setScanContext(&scanContext);
+
+ parseContext->setPpContext(&ppContext);
+ parseContext->setLimits(*resources);
+ if (! goodVersion)
+ parseContext->addError();
+ if (warnVersionNotFirst) {
+ TSourceLoc loc;
+ loc.init();
+ parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
+ }
+
+ parseContext->initializeExtensionBehavior();
+
+ // Fill in the strings as outlined above.
+ std::string preamble;
+ parseContext->getPreamble(preamble);
+ strings[0] = preamble.c_str();
+ lengths[0] = strlen(strings[0]);
+ names[0] = nullptr;
+ strings[1] = customPreamble;
+ lengths[1] = strlen(strings[1]);
+ names[1] = nullptr;
+ assert(2 == numPre);
+ if (requireNonempty) {
+ const int postIndex = numStrings + numPre;
+ strings[postIndex] = "\n int;";
+ lengths[postIndex] = strlen(strings[numStrings + numPre]);
+ names[postIndex] = nullptr;
+ }
+ TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, names, numPre, numPost);
+
+ // Push a new symbol allocation scope that will get used for the shader's globals.
+ symbolTable.push();
+
+ bool success = processingContext(*parseContext, ppContext, fullInput,
+ versionWillBeError, symbolTable,
+ intermediate, optLevel, messages);
+
+ // Clean up the symbol table. The AST is self-sufficient now.
+ delete symbolTableMemory;
+
+ delete parseContext;
+ delete [] lengths;
+ delete [] strings;
+ delete [] names;
+
+ return success;
+}
+
+// Responsible for keeping track of the most recent source string and line in
+// the preprocessor and outputting newlines appropriately if the source string
+// or line changes.
+class SourceLineSynchronizer {
+public:
+ SourceLineSynchronizer(const std::function<int()>& lastSourceIndex,
+ std::stringstream* output)
+ : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {}
+// SourceLineSynchronizer(const SourceLineSynchronizer&) = delete;
+// SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete;
+
+ // Sets the internally tracked source string index to that of the most
+ // recently read token. If we switched to a new source string, returns
+ // true and inserts a newline. Otherwise, returns false and outputs nothing.
+ bool syncToMostRecentString() {
+ if (getLastSourceIndex() != lastSource) {
+ // After switching to a new source string, we need to reset lastLine
+ // because line number resets every time a new source string is
+ // used. We also need to output a newline to separate the output
+ // from the previous source string (if there is one).
+ if (lastSource != -1 || lastLine != 0)
+ *output << std::endl;
+ lastSource = getLastSourceIndex();
+ lastLine = -1;
+ return true;
+ }
+ return false;
+ }
+
+ // Calls syncToMostRecentString() and then sets the internally tracked line
+ // number to tokenLine. If we switched to a new line, returns true and inserts
+ // newlines appropriately. Otherwise, returns false and outputs nothing.
+ bool syncToLine(int tokenLine) {
+ syncToMostRecentString();
+ const bool newLineStarted = lastLine < tokenLine;
+ for (; lastLine < tokenLine; ++lastLine) {
+ if (lastLine > 0) *output << std::endl;
+ }
+ return newLineStarted;
+ }
+
+ // Sets the internally tracked line number to newLineNum.
+ void setLineNum(int newLineNum) { lastLine = newLineNum; }
+
+private:
+ // A function for getting the index of the last valid source string we've
+ // read tokens from.
+ const std::function<int()> getLastSourceIndex;
+ // output stream for newlines.
+ std::stringstream* output;
+ // lastSource is the source string index (starting from 0) of the last token
+ // processed. It is tracked in order for newlines to be inserted when a new
+ // source string starts. -1 means we haven't started processing any source
+ // string.
+ int lastSource;
+ // lastLine is the line number (starting from 1) of the last token processed.
+ // It is tracked in order for newlines to be inserted when a token appears
+ // on a new line. 0 means we haven't started processing any line in the
+ // current source string.
+ int lastLine;
+};
+
+// DoPreprocessing is a valid ProcessingContext template argument,
+// which only performs the preprocessing step of compilation.
+// It places the result in the "string" argument to its constructor.
+struct DoPreprocessing {
+ explicit DoPreprocessing(std::string* string): outputString(string) {}
+ bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
+ TInputScanner& input, bool versionWillBeError,
+ TSymbolTable& , TIntermediate& ,
+ EShOptimizationLevel , EShMessages )
+ {
+ // This is a list of tokens that do not require a space before or after.
+ static const std::string unNeededSpaceTokens = ";()[]";
+ static const std::string noSpaceBeforeTokens = ",";
+ glslang::TPpToken token;
+
+ parseContext.setScanner(&input);
+ ppContext.setInput(input, versionWillBeError);
+
+ std::stringstream outputStream;
+ SourceLineSynchronizer lineSync(
+ std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputStream);
+
+ parseContext.setExtensionCallback([&lineSync, &outputStream](
+ int line, const char* extension, const char* behavior) {
+ lineSync.syncToLine(line);
+ outputStream << "#extension " << extension << " : " << behavior;
+ });
+
+ parseContext.setLineCallback([&lineSync, &outputStream, &parseContext](
+ int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
+ // SourceNum is the number of the source-string that is being parsed.
+ lineSync.syncToLine(curLineNum);
+ outputStream << "#line " << newLineNum;
+ if (hasSource) {
+ outputStream << " ";
+ if (sourceName != nullptr) {
+ outputStream << "\"" << sourceName << "\"";
+ } else {
+ outputStream << sourceNum;
+ }
+ }
+ if (parseContext.lineDirectiveShouldSetNextLine()) {
+ // newLineNum is the new line number for the line following the #line
+ // directive. So the new line number for the current line is
+ newLineNum -= 1;
+ }
+ outputStream << std::endl;
+ // And we are at the next line of the #line directive now.
+ lineSync.setLineNum(newLineNum + 1);
+ });
+
+ parseContext.setVersionCallback(
+ [&lineSync, &outputStream](int line, int version, const char* str) {
+ lineSync.syncToLine(line);
+ outputStream << "#version " << version;
+ if (str) {
+ outputStream << " " << str;
+ }
+ });
+
+ parseContext.setPragmaCallback([&lineSync, &outputStream](
+ int line, const glslang::TVector<glslang::TString>& ops) {
+ lineSync.syncToLine(line);
+ outputStream << "#pragma ";
+ for(size_t i = 0; i < ops.size(); ++i) {
+ outputStream << ops[i];
+ }
+ });
+
+ parseContext.setErrorCallback([&lineSync, &outputStream](
+ int line, const char* errorMessage) {
+ lineSync.syncToLine(line);
+ outputStream << "#error " << errorMessage;
+ });
+
+ int lastToken = EndOfInput; // lastToken records the last token processed.
+ while (const char* tok = ppContext.tokenize(&token)) {
+ bool isNewString = lineSync.syncToMostRecentString();
+ bool isNewLine = lineSync.syncToLine(token.loc.line);
+
+ if (isNewLine) {
+ // Don't emit whitespace onto empty lines.
+ // Copy any whitespace characters at the start of a line
+ // from the input to the output.
+ outputStream << std::string(token.loc.column - 1, ' ');
+ }
+
+ // Output a space in between tokens, but not at the start of a line,
+ // and also not around special tokens. This helps with readability
+ // and consistency.
+ if (!isNewString && !isNewLine && lastToken != EndOfInput &&
+ (unNeededSpaceTokens.find((char)token.token) == std::string::npos) &&
+ (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
+ (noSpaceBeforeTokens.find((char)token.token) == std::string::npos)) {
+ outputStream << " ";
+ }
+ lastToken = token.token;
+ outputStream << tok;
+ }
+ outputStream << std::endl;
+ *outputString = outputStream.str();
+
+ bool success = true;
+ if (parseContext.getNumErrors() > 0) {
+ success = false;
+ parseContext.infoSink.info.prefix(EPrefixError);
+ parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
+ }
+ return success;
+ }
+ std::string* outputString;
+};
+
+// DoFullParse is a valid ProcessingConext template argument for fully
+// parsing the shader. It populates the "intermediate" with the AST.
+struct DoFullParse{
+ bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
+ TInputScanner& fullInput, bool versionWillBeError,
+ TSymbolTable& symbolTable, TIntermediate& intermediate,
+ EShOptimizationLevel optLevel, EShMessages messages)
+ {
+ bool success = true;
+ // Parse the full shader.
+ if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
+ success = false;
+ intermediate.addSymbolLinkageNodes(parseContext.getLinkage(), parseContext.getLanguage(), symbolTable);
+
+ if (success && intermediate.getTreeRoot()) {
+ if (optLevel == EShOptNoGeneration)
+ parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
+ else
+ success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage());
+ } else if (! success) {
+ parseContext.infoSink.info.prefix(EPrefixError);
+ parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
+ }
+
+ if (messages & EShMsgAST)
+ intermediate.output(parseContext.infoSink, true);
+
+ return success;
+ }
+};
+
+// Take a single compilation unit, and run the preprocessor on it.
+// Return: True if there were no issues found in preprocessing,
+// False if during preprocessing any unknown version, pragmas or
+// extensions were found.
+bool PreprocessDeferred(
+ TCompiler* compiler,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const char* const stringNames[],
+ const char* preamble,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop
+ EProfile defaultProfile,
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages, // warnings/errors/AST; things to print out
+ TShader::Includer& includer,
+ TIntermediate& intermediate, // returned tree, etc.
+ std::string* outputString)
+{
+ DoPreprocessing parser(outputString);
+ return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
+ preamble, optLevel, resources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, messages, intermediate, parser,
+ false, includer);
+}
+
+
+//
+// do a partial compile on the given strings for a single compilation unit
+// for a potential deferred link into a single stage (and deferred full compile of that
+// stage through machine-dependent compilation).
+//
+// all preprocessing, parsing, semantic checks, etc. for a single compilation unit
+// are done here.
+//
+// return: the tree and other information is filled into the intermediate argument,
+// and true is returned by the function for success.
+//
+bool CompileDeferred(
+ TCompiler* compiler,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const char* const stringNames[],
+ const char* preamble,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop
+ EProfile defaultProfile,
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages, // warnings/errors/AST; things to print out
+ TIntermediate& intermediate,// returned tree, etc.
+ TShader::Includer& includer)
+{
+ DoFullParse parser;
+ return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
+ preamble, optLevel, resources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, messages, intermediate, parser,
+ true, includer);
+}
+
+} // end anonymous namespace for local functions
+
+
+//
+// ShInitialize() should be called exactly once per process, not per thread.
+//
+int ShInitialize()
+{
+ glslang::InitGlobalLock();
+
+ if (! InitProcess())
+ return 0;
+
+ if (! PerProcessGPA)
+ PerProcessGPA = new TPoolAllocator();
+
+ glslang::TScanContext::fillInKeywordMap();
+
+ return 1;
+}
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+
+ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
+
+ return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
+
+ return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructUniformMap()
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
+
+ return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+ if (base->getAsCompiler())
+ DeleteCompiler(base->getAsCompiler());
+ else if (base->getAsLinker())
+ DeleteLinker(base->getAsLinker());
+ else if (base->getAsUniformMap())
+ DeleteUniformMap(base->getAsUniformMap());
+}
+
+//
+// Cleanup symbol tables
+//
+int __fastcall ShFinalize()
+{
+ for (int version = 0; version < VersionCount; ++version) {
+ for (int p = 0; p < ProfileCount; ++p) {
+ for (int lang = 0; lang < EShLangCount; ++lang) {
+ delete SharedSymbolTables[version][p][lang];
+ SharedSymbolTables[version][p][lang] = 0;
+ }
+ }
+ }
+
+ for (int version = 0; version < VersionCount; ++version) {
+ for (int p = 0; p < ProfileCount; ++p) {
+ for (int pc = 0; pc < EPcCount; ++pc) {
+ delete CommonSymbolTable[version][p][pc];
+ CommonSymbolTable[version][p][pc] = 0;
+ }
+ }
+ }
+
+ if (PerProcessGPA) {
+ PerProcessGPA->popAll();
+ delete PerProcessGPA;
+ PerProcessGPA = 0;
+ }
+
+ glslang::TScanContext::deleteKeywordMap();
+
+ return 1;
+}
+
+//
+// Do a full compile on the given strings for a single compilation unit
+// forming a complete stage. The result of the machine dependent compilation
+// is left in the provided compile object.
+//
+// Return: The return value is really boolean, indicating
+// success (1) or failure (0).
+//
+int ShCompile(
+ const ShHandle handle,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const int* inputLengths,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int /*debugOptions*/,
+ int defaultVersion, // use 100 for ES environment, 110 for desktop
+ bool forwardCompatible, // give errors for use of deprecated features
+ EShMessages messages // warnings/errors/AST; things to print out
+ )
+{
+ // Map the generic handle to the C++ object
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return 0;
+
+ compiler->infoSink.info.erase();
+ compiler->infoSink.debug.erase();
+
+ TIntermediate intermediate(compiler->getLanguage());
+ TShader::ForbidInclude includer;
+ bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
+ "", optLevel, resources, defaultVersion, ENoProfile, false,
+ forwardCompatible, messages, intermediate, includer);
+
+ //
+ // Call the machine dependent compiler
+ //
+ if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration)
+ success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile());
+
+ intermediate.removeTree();
+
+ // Throw away all the temporary memory used by the compilation process.
+ // The push was done in the CompileDeferred() call above.
+ GetThreadPoolAllocator().pop();
+
+ return success ? 1 : 0;
+}
+
+//
+// Link the given compile objects.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShLinkExt(
+ const ShHandle linkHandle,
+ const ShHandle compHandles[],
+ const int numHandles)
+{
+ if (linkHandle == 0 || numHandles == 0)
+ return 0;
+
+ THandleList cObjects;
+
+ for (int i = 0; i < numHandles; ++i) {
+ if (compHandles[i] == 0)
+ return 0;
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
+ if (base->getAsLinker()) {
+ cObjects.push_back(base->getAsLinker());
+ }
+ if (base->getAsCompiler())
+ cObjects.push_back(base->getAsCompiler());
+
+
+ if (cObjects[i] == 0)
+ return 0;
+ }
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->infoSink.info.erase();
+
+ for (int i = 0; i < numHandles; ++i) {
+ if (cObjects[i]->getAsCompiler()) {
+ if (! cObjects[i]->getAsCompiler()->linkable()) {
+ linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");
+ return 0;
+ }
+ }
+ }
+
+ bool ret = linker->link(cObjects);
+
+ return ret ? 1 : 0;
+}
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+}
+
+//
+// Return any compiler/linker/uniformmap log of messages for the application.
+//
+const char* ShGetInfoLog(const ShHandle handle)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TInfoSink* infoSink;
+
+ if (base->getAsCompiler())
+ infoSink = &(base->getAsCompiler()->getInfoSink());
+ else if (base->getAsLinker())
+ infoSink = &(base->getAsLinker()->getInfoSink());
+ else
+ return 0;
+
+ infoSink->info << infoSink->debug.c_str();
+ return infoSink->info.c_str();
+}
+
+//
+// Return the resulting binary code from the link process. Structure
+// is machine dependent.
+//
+const void* ShGetExecutable(const ShHandle handle)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ return linker->getObjectCode();
+}
+
+//
+// Let the linker know where the application said it's attributes are bound.
+// The linker does not use these values, they are remapped by the ICD or
+// hardware. It just needs them to know what's aliased.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->setAppAttributeBindings(table);
+
+ return 1;
+}
+
+//
+// Let the linker know where the predefined attributes have to live.
+//
+int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->setFixedAttributeBindings(table);
+ return 1;
+}
+
+//
+// Some attribute locations are off-limits to the linker...
+//
+int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ linker->setExcludedAttributes(attributes, count);
+
+ return 1;
+}
+
+//
+// Return the index for OpenGL to use for knowing where a uniform lives.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShGetUniformLocation(const ShHandle handle, const char* name)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return -1;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TUniformMap* uniformMap= base->getAsUniformMap();
+ if (uniformMap == 0)
+ return -1;
+
+ return uniformMap->getLocation(name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Deferred-Lowering C++ Interface
+// -----------------------------------
+//
+// Below is a new alternate C++ interface that might potentially replace the above
+// opaque handle-based interface.
+//
+// See more detailed comment in ShaderLang.h
+//
+
+namespace glslang {
+
+#include "../Include/revision.h"
+
+const char* GetEsslVersionString()
+{
+ return "OpenGL ES GLSL 3.00 glslang LunarG Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
+}
+
+const char* GetGlslVersionString()
+{
+ return "4.20 glslang LunarG Khronos." GLSLANG_REVISION " " GLSLANG_DATE;
+}
+
+int GetKhronosToolId()
+{
+ return 8;
+}
+
+bool InitializeProcess()
+{
+ return ShInitialize() != 0;
+}
+
+void FinalizeProcess()
+{
+ ShFinalize();
+}
+
+class TDeferredCompiler : public TCompiler {
+public:
+ TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { }
+ virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; }
+};
+
+TShader::TShader(EShLanguage s)
+ : pool(0), stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
+{
+ infoSink = new TInfoSink;
+ compiler = new TDeferredCompiler(stage, *infoSink);
+ intermediate = new TIntermediate(s);
+}
+
+TShader::~TShader()
+{
+ delete infoSink;
+ delete compiler;
+ delete intermediate;
+ delete pool;
+}
+
+void TShader::setStrings(const char* const* s, int n)
+{
+ strings = s;
+ numStrings = n;
+ lengths = nullptr;
+}
+
+void TShader::setStringsWithLengths(const char* const* s, const int* l, int n)
+{
+ strings = s;
+ numStrings = n;
+ lengths = l;
+}
+
+void TShader::setStringsWithLengthsAndNames(
+ const char* const* s, const int* l, const char* const* names, int n)
+{
+ strings = s;
+ numStrings = n;
+ lengths = l;
+ stringNames = names;
+}
+
+void TShader::setEntryPoint(const char* entryPoint)
+{
+ intermediate->setEntryPoint(entryPoint);
+}
+
+//
+// Turn the shader strings into a parse tree in the TIntermediate.
+//
+// Returns true for success.
+//
+bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages messages, Includer& includer)
+{
+ if (! InitThread())
+ return false;
+
+ pool = new TPoolAllocator();
+ SetThreadPoolAllocator(*pool);
+ if (! preamble)
+ preamble = "";
+
+ return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
+ preamble, EShOptNone, builtInResources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, messages, *intermediate, includer);
+}
+
+bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
+{
+ return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
+}
+
+// Fill in a string with the result of preprocessing ShaderStrings
+// Returns true if all extensions, pragmas and version strings were valid.
+bool TShader::preprocess(const TBuiltInResource* builtInResources,
+ int defaultVersion, EProfile defaultProfile,
+ bool forceDefaultVersionAndProfile,
+ bool forwardCompatible, EShMessages message,
+ std::string* output_string,
+ Includer& includer)
+{
+ if (! InitThread())
+ return false;
+
+ pool = new TPoolAllocator();
+ SetThreadPoolAllocator(*pool);
+ if (! preamble)
+ preamble = "";
+
+ return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
+ EShOptNone, builtInResources, defaultVersion,
+ defaultProfile, forceDefaultVersionAndProfile,
+ forwardCompatible, message, includer, *intermediate, output_string);
+}
+
+const char* TShader::getInfoLog()
+{
+ return infoSink->info.c_str();
+}
+
+const char* TShader::getInfoDebugLog()
+{
+ return infoSink->debug.c_str();
+}
+
+TProgram::TProgram() : pool(0), reflection(0), linked(false)
+{
+ infoSink = new TInfoSink;
+ for (int s = 0; s < EShLangCount; ++s) {
+ intermediate[s] = 0;
+ newedIntermediate[s] = false;
+ }
+}
+
+TProgram::~TProgram()
+{
+ delete infoSink;
+ delete reflection;
+
+ for (int s = 0; s < EShLangCount; ++s)
+ if (newedIntermediate[s])
+ delete intermediate[s];
+
+ delete pool;
+}
+
+//
+// Merge the compilation units within each stage into a single TIntermediate.
+// All starting compilation units need to be the result of calling TShader::parse().
+//
+// Return true for success.
+//
+bool TProgram::link(EShMessages messages)
+{
+ if (linked)
+ return false;
+ linked = true;
+
+ bool error = false;
+
+ pool = new TPoolAllocator();
+ SetThreadPoolAllocator(*pool);
+
+ for (int s = 0; s < EShLangCount; ++s) {
+ if (! linkStage((EShLanguage)s, messages))
+ error = true;
+ }
+
+ // TODO: Link: cross-stage error checking
+
+ return ! error;
+}
+
+//
+// Merge the compilation units within the given stage into a single TIntermediate.
+//
+// Return true for success.
+//
+bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
+{
+ if (stages[stage].size() == 0)
+ return true;
+
+ int numEsShaders = 0, numNonEsShaders = 0;
+ for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
+ if ((*it)->intermediate->getProfile() == EEsProfile) {
+ numEsShaders++;
+ } else {
+ numNonEsShaders++;
+ }
+ }
+
+ if (numEsShaders > 0 && numNonEsShaders > 0) {
+ infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders");
+ return false;
+ } else if (numEsShaders > 1) {
+ infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program");
+ return false;
+ }
+
+ //
+ // Be efficient for the common single compilation unit per stage case,
+ // reusing it's TIntermediate instead of merging into a new one.
+ //
+ TIntermediate *firstIntermediate = stages[stage].front()->intermediate;
+ if (stages[stage].size() == 1)
+ intermediate[stage] = firstIntermediate;
+ else {
+ intermediate[stage] = new TIntermediate(stage,
+ firstIntermediate->getVersion(),
+ firstIntermediate->getProfile());
+ newedIntermediate[stage] = true;
+ }
+
+ infoSink->info << "\nLinked " << StageName(stage) << " stage:\n\n";
+
+ if (stages[stage].size() > 1) {
+ std::list<TShader*>::const_iterator it;
+ for (it = stages[stage].begin(); it != stages[stage].end(); ++it)
+ intermediate[stage]->merge(*infoSink, *(*it)->intermediate);
+ }
+
+ intermediate[stage]->finalCheck(*infoSink);
+
+ if (messages & EShMsgAST)
+ intermediate[stage]->output(*infoSink, true);
+
+ return intermediate[stage]->getNumErrors() == 0;
+}
+
+const char* TProgram::getInfoLog()
+{
+ return infoSink->info.c_str();
+}
+
+const char* TProgram::getInfoDebugLog()
+{
+ return infoSink->debug.c_str();
+}
+
+//
+// Reflection implementation.
+//
+
+bool TProgram::buildReflection()
+{
+ if (! linked || reflection)
+ return false;
+
+ reflection = new TReflection;
+
+ for (int s = 0; s < EShLangCount; ++s) {
+ if (intermediate[s]) {
+ if (! reflection->addStage((EShLanguage)s, *intermediate[s]))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int TProgram::getNumLiveUniformVariables() { return reflection->getNumUniforms(); }
+int TProgram::getNumLiveUniformBlocks() { return reflection->getNumUniformBlocks(); }
+const char* TProgram::getUniformName(int index) { return reflection->getUniform(index).name.c_str(); }
+const char* TProgram::getUniformBlockName(int index) { return reflection->getUniformBlock(index).name.c_str(); }
+int TProgram::getUniformBlockSize(int index) { return reflection->getUniformBlock(index).size; }
+int TProgram::getUniformIndex(const char* name) { return reflection->getIndex(name); }
+int TProgram::getUniformBlockIndex(int index) { return reflection->getUniform(index).index; }
+int TProgram::getUniformType(int index) { return reflection->getUniform(index).glDefineType; }
+int TProgram::getUniformBufferOffset(int index) { return reflection->getUniform(index).offset; }
+int TProgram::getUniformArraySize(int index) { return reflection->getUniform(index).size; }
+int TProgram::getNumLiveAttributes() { return reflection->getNumAttributes(); }
+const char* TProgram::getAttributeName(int index) { return reflection->getAttribute(index).name.c_str(); }
+int TProgram::getAttributeType(int index) { return reflection->getAttribute(index).glDefineType; }
+
+void TProgram::dumpReflection() { reflection->dump(); }
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp
new file mode 100644
index 00000000000..bf0f1f9fa74
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp
@@ -0,0 +1,351 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Symbol table for parsing. Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#include "SymbolTable.h"
+
+namespace glslang {
+
+//
+// TType helper function needs a place to live.
+//
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName)
+{
+ if (isMatrix())
+ mangledName += 'm';
+ else if (isVector())
+ mangledName += 'v';
+
+ switch (basicType) {
+ case EbtFloat: mangledName += 'f'; break;
+ case EbtDouble: mangledName += 'd'; break;
+ case EbtInt: mangledName += 'i'; break;
+ case EbtUint: mangledName += 'u'; break;
+ case EbtInt64: mangledName += "i64"; break;
+ case EbtUint64: mangledName += "u64"; break;
+ case EbtBool: mangledName += 'b'; break;
+ case EbtAtomicUint: mangledName += "au"; break;
+ case EbtSampler:
+ switch (sampler.type) {
+ case EbtInt: mangledName += "i"; break;
+ case EbtUint: mangledName += "u"; break;
+ default: break; // some compilers want this
+ }
+ if (sampler.image)
+ mangledName += "I"; // a normal image
+ else if (sampler.sampler)
+ mangledName += "p"; // a "pure" sampler
+ else if (!sampler.combined)
+ mangledName += "t"; // a "pure" texture
+ else
+ mangledName += "s"; // traditional combined sampler
+ if (sampler.arrayed)
+ mangledName += "A";
+ if (sampler.shadow)
+ mangledName += "S";
+ if (sampler.external)
+ mangledName += "E";
+ switch (sampler.dim) {
+ case Esd1D: mangledName += "1"; break;
+ case Esd2D: mangledName += "2"; break;
+ case Esd3D: mangledName += "3"; break;
+ case EsdCube: mangledName += "C"; break;
+ case EsdRect: mangledName += "R2"; break;
+ case EsdBuffer: mangledName += "B"; break;
+ case EsdSubpass: mangledName += "P"; break;
+ default: break; // some compilers want this
+ }
+ if (sampler.ms)
+ mangledName += "M";
+ break;
+ case EbtStruct:
+ mangledName += "struct-";
+ if (typeName)
+ mangledName += *typeName;
+ for (unsigned int i = 0; i < structure->size(); ++i) {
+ mangledName += '-';
+ (*structure)[i].type->buildMangledName(mangledName);
+ }
+ default:
+ break;
+ }
+
+ if (getVectorSize() > 0)
+ mangledName += static_cast<char>('0' + getVectorSize());
+ else {
+ mangledName += static_cast<char>('0' + getMatrixCols());
+ mangledName += static_cast<char>('0' + getMatrixRows());
+ }
+
+ if (arraySizes) {
+ const int maxSize = 11;
+ char buf[maxSize];
+ for (int i = 0; i < arraySizes->getNumDims(); ++i) {
+ if (arraySizes->getDimNode(i)) {
+ if (arraySizes->getDimNode(i)->getAsSymbolNode())
+ snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
+ else
+ snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
+ } else
+ snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i));
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
+ }
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " << type.getBasicTypeString();
+ if (type.isArray()) {
+ infoSink.debug << "[0]";
+ }
+ infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink& infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " " << 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;
+ for (it = level.begin(); it != level.end(); ++it)
+ (*it).second->dump(infoSink);
+}
+
+void TSymbolTable::dump(TInfoSink &infoSink) const
+{
+ for (int level = currentLevel(); level >= 0; --level) {
+ infoSink.debug << "LEVEL " << level << "\n";
+ table[level]->dump(infoSink);
+ }
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+ for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+ delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+ delete (*it).second;
+
+ delete [] defaultPrecision;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ while (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
+ TFunction* function = (*candidate).second->getAsFunction();
+ function->relateToOperator(op);
+ } else
+ break;
+ ++candidate;
+ }
+}
+
+// Make all function overloads of the given name require an extension(s).
+// Should only be used for a version/profile that actually needs the extension(s).
+void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[])
+{
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ while (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
+ TSymbol* symbol = candidate->second;
+ symbol->setExtensions(num, extensions);
+ } else
+ break;
+ ++candidate;
+ }
+}
+
+//
+// Make all symbols in this table level read only.
+//
+void TSymbolTableLevel::readOnly()
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+ (*it).second->makeReadOnly();
+}
+
+//
+// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired.
+//
+TSymbol::TSymbol(const TSymbol& copyOf)
+{
+ name = NewPoolTString(copyOf.name->c_str());
+ uniqueId = copyOf.uniqueId;
+ writable = true;
+}
+
+TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
+{
+ type.deepCopy(copyOf.type);
+ userType = copyOf.userType;
+ numExtensions = 0;
+ extensions = 0;
+ if (copyOf.numExtensions != 0)
+ setExtensions(copyOf.numExtensions, copyOf.extensions);
+
+ if (! copyOf.constArray.empty()) {
+ assert(! copyOf.type.isStruct());
+ TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size());
+ constArray = newArray;
+ }
+
+ // don't support specialization-constant subtrees in cloned tables
+ constSubtree = nullptr;
+}
+
+TVariable* TVariable::clone() const
+{
+ TVariable *variable = new TVariable(*this);
+
+ return variable;
+}
+
+TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
+{
+ for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+ TParameter param;
+ parameters.push_back(param);
+ parameters.back().copyParam(copyOf.parameters[i]);
+ }
+
+ numExtensions = 0;
+ extensions = 0;
+ if (copyOf.extensions != 0)
+ setExtensions(copyOf.numExtensions, copyOf.extensions);
+ returnType.deepCopy(copyOf.returnType);
+ mangledName = copyOf.mangledName;
+ op = copyOf.op;
+ defined = copyOf.defined;
+ prototyped = copyOf.prototyped;
+}
+
+TFunction* TFunction::clone() const
+{
+ TFunction *function = new TFunction(*this);
+
+ return function;
+}
+
+TAnonMember* TAnonMember::clone() const
+{
+ // Anonymous members of a given block should be cloned at a higher level,
+ // where they can all be assured to still end up pointing to a single
+ // copy of the original container.
+ assert(0);
+
+ return 0;
+}
+
+TSymbolTableLevel* TSymbolTableLevel::clone() const
+{
+ TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+ symTableLevel->anonId = anonId;
+ std::vector<bool> containerCopied(anonId, false);
+ tLevel::const_iterator iter;
+ for (iter = level.begin(); iter != level.end(); ++iter) {
+ const TAnonMember* anon = iter->second->getAsAnonMember();
+ if (anon) {
+ // Insert all the anonymous members of this same container at once,
+ // avoid inserting the other members in the future, once this has been done,
+ // allowing them to all be part of the same new container.
+ if (! containerCopied[anon->getAnonId()]) {
+ TVariable* container = anon->getAnonContainer().clone();
+ container->changeName(NewPoolTString(""));
+ // insert the whole container
+ symTableLevel->insert(*container, false);
+ containerCopied[anon->getAnonId()] = true;
+ }
+ } else
+ symTableLevel->insert(*iter->second->clone(), false);
+ }
+
+ return symTableLevel;
+}
+
+void TSymbolTable::copyTable(const TSymbolTable& copyOf)
+{
+ assert(adoptedLevels == copyOf.adoptedLevels);
+
+ uniqueId = copyOf.uniqueId;
+ noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations;
+ separateNameSpaces = copyOf.separateNameSpaces;
+ for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i)
+ table.push_back(copyOf.table[i]->clone());
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.h
new file mode 100644
index 00000000000..9877ab7fae5
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.h
@@ -0,0 +1,694 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing. Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+// 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. 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.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack
+// of symbol tables. Searched from the top, with new inserts going into
+// the top.
+//
+// * Constants: Compile time constant symbols will keep their values
+// in the symbol table. The parser can substitute constants at parse
+// time, including doing constant folding and constant propagation.
+//
+// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
+// are tracked in the intermediate representation, not the symbol table.
+//
+
+#include "../Include/Common.h"
+#include "../Include/intermediate.h"
+#include "../Include/InfoSink.h"
+
+namespace glslang {
+
+//
+// Symbol base class. (Can build functions or variables out of these...)
+//
+
+class TVariable;
+class TFunction;
+class TAnonMember;
+
+class TSymbol {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ explicit TSymbol(const TString *n) : name(n), numExtensions(0), extensions(0), writable(true) { }
+ virtual TSymbol* clone() const = 0;
+ virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
+
+ virtual const TString& getName() const { return *name; }
+ virtual void changeName(const TString* newName) { name = newName; }
+ virtual const TString& getMangledName() const { return getName(); }
+ virtual TFunction* getAsFunction() { return 0; }
+ virtual const TFunction* getAsFunction() const { return 0; }
+ virtual TVariable* getAsVariable() { return 0; }
+ virtual const TVariable* getAsVariable() const { return 0; }
+ virtual const TAnonMember* getAsAnonMember() const { return 0; }
+ virtual const TType& getType() const = 0;
+ virtual TType& getWritableType() = 0;
+ virtual void setUniqueId(int id) { uniqueId = id; }
+ virtual int getUniqueId() const { return uniqueId; }
+ virtual void setExtensions(int num, const char* const exts[])
+ {
+ assert(extensions == 0);
+ assert(num > 0);
+ numExtensions = num;
+ extensions = NewPoolObject(exts[0], num);
+ for (int e = 0; e < num; ++e)
+ extensions[e] = exts[e];
+ }
+ virtual int getNumExtensions() const { return numExtensions; }
+ virtual const char** getExtensions() const { return extensions; }
+ virtual void dump(TInfoSink &infoSink) const = 0;
+
+ virtual bool isReadOnly() const { return ! writable; }
+ virtual void makeReadOnly() { writable = false; }
+
+protected:
+ explicit TSymbol(const TSymbol&);
+ TSymbol& operator=(const TSymbol&);
+
+ const TString *name;
+ unsigned int uniqueId; // For cross-scope comparing during code generation
+
+ // For tracking what extensions must be present
+ // (don't use if correct version/profile is present).
+ int numExtensions;
+ const char** extensions; // an array of pointers to existing constant char strings
+
+ //
+ // N.B.: Non-const functions that will be generally used should assert on this,
+ // to avoid overwriting shared symbol-table information.
+ //
+ bool writable;
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+//
+// There could be a separate class hierarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+ TVariable(const TString *name, const TType& t, bool uT = false )
+ : TSymbol(name),
+ userType(uT),
+ constSubtree(nullptr) { type.shallowCopy(t); }
+ virtual TVariable* clone() const;
+ virtual ~TVariable() { }
+
+ virtual TVariable* getAsVariable() { return this; }
+ virtual const TVariable* getAsVariable() const { return this; }
+ virtual const TType& getType() const { return type; }
+ virtual TType& getWritableType() { assert(writable); return type; }
+ virtual bool isUserType() const { return userType; }
+ virtual const TConstUnionArray& getConstArray() const { return constArray; }
+ virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
+ virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
+ virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
+ virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
+
+ virtual void dump(TInfoSink &infoSink) const;
+
+protected:
+ explicit TVariable(const TVariable&);
+ TVariable& operator=(const TVariable&);
+
+ TType type;
+ bool userType;
+ // we are assuming that Pool Allocator will free the memory allocated to unionArray
+ // when this object is destroyed
+
+ // TODO: these two should be a union
+ // A variable could be a compile-time constant, or a specialization
+ // constant, or neither, but never both.
+ TConstUnionArray constArray; // for compile-time constant value
+ TIntermTyped* constSubtree; // for specialization constant computation
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+ TString *name;
+ TType* type;
+ void copyParam(const TParameter& param)
+ {
+ if (param.name)
+ name = NewPoolTString(param.name->c_str());
+ else
+ name = 0;
+ type = param.type->clone();
+ }
+};
+
+//
+// The function sub-class of a symbol.
+//
+class TFunction : public TSymbol {
+public:
+ explicit TFunction(TOperator o) :
+ TSymbol(0),
+ op(o),
+ defined(false), prototyped(false) { }
+ TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
+ TSymbol(name),
+ mangledName(*name + '('),
+ op(tOp),
+ defined(false), prototyped(false) { returnType.shallowCopy(retType); }
+ virtual TFunction* clone() const;
+ virtual ~TFunction();
+
+ virtual TFunction* getAsFunction() { return this; }
+ virtual const TFunction* getAsFunction() const { return this; }
+
+ virtual void addParameter(TParameter& p)
+ {
+ assert(writable);
+ parameters.push_back(p);
+ p.type->appendMangledName(mangledName);
+ }
+
+ virtual const TString& getMangledName() const { return mangledName; }
+ virtual const TType& getType() const { return returnType; }
+ virtual TType& getWritableType() { return returnType; }
+ virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
+ virtual TOperator getBuiltInOp() const { return op; }
+ virtual void setDefined() { assert(writable); defined = true; }
+ virtual bool isDefined() const { return defined; }
+ virtual void setPrototyped() { assert(writable); prototyped = true; }
+ virtual bool isPrototyped() const { return prototyped; }
+
+ virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
+ virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
+ virtual const TParameter& operator[](int i) const { return parameters[i]; }
+
+ virtual void dump(TInfoSink &infoSink) const;
+
+protected:
+ explicit TFunction(const TFunction&);
+ TFunction& operator=(const TFunction&);
+
+ typedef TVector<TParameter> TParamList;
+ TParamList parameters;
+ TType returnType;
+ TString mangledName;
+ TOperator op;
+ bool defined;
+ bool prototyped;
+};
+
+//
+// Members of anonymous blocks are a kind of TSymbol. They are not hidden in
+// the symbol table behind a container; rather they are visible and point to
+// their anonymous container. (The anonymous container is found through the
+// member, not the other way around.)
+//
+class TAnonMember : public TSymbol {
+public:
+ TAnonMember(const TString* n, unsigned int m, const TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
+ virtual TAnonMember* clone() const;
+ virtual ~TAnonMember() { }
+
+ virtual const TAnonMember* getAsAnonMember() const { return this; }
+ virtual const TVariable& getAnonContainer() const { return anonContainer; }
+ virtual unsigned int getMemberNumber() const { return memberNumber; }
+
+ virtual const TType& getType() const
+ {
+ const TTypeList& types = *anonContainer.getType().getStruct();
+ return *types[memberNumber].type;
+ }
+
+ virtual TType& getWritableType()
+ {
+ assert(writable);
+ const TTypeList& types = *anonContainer.getType().getStruct();
+ return *types[memberNumber].type;
+ }
+
+ virtual int getAnonId() const { return anonId; }
+ virtual void dump(TInfoSink &infoSink) const;
+
+protected:
+ explicit TAnonMember(const TAnonMember&);
+ TAnonMember& operator=(const TAnonMember&);
+
+ const TVariable& anonContainer;
+ unsigned int memberNumber;
+ int anonId;
+};
+
+class TSymbolTableLevel {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+ TSymbolTableLevel() : defaultPrecision(0), anonId(0) { }
+ ~TSymbolTableLevel();
+
+ bool insert(TSymbol& symbol, bool separateNameSpaces)
+ {
+ //
+ // returning true means symbol was added to the table with no semantic errors
+ //
+ tInsertResult result;
+ const TString& name = symbol.getName();
+ if (name == "") {
+ // 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, "%s%d", AnonymousPrefix, anonId);
+ symbol.changeName(NewPoolTString(buf));
+
+ bool isOkay = true;
+ const 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.getAsVariable(), anonId);
+ result = level.insert(tLevelPair(member->getMangledName(), member));
+ if (! result.second)
+ isOkay = false;
+ }
+
+ ++anonId;
+
+ return isOkay;
+ } else {
+ // Check for redefinition errors:
+ // - STL itself will tell us if there is a direct name collision, with name mangling, at this level
+ // - additionally, check for function-redefining-variable name collisions
+ const TString& insertName = symbol.getMangledName();
+ if (symbol.getAsFunction()) {
+ // make sure there isn't a variable of this name
+ if (! separateNameSpaces && level.find(name) != level.end())
+ return false;
+
+ // insert, and whatever happens is okay
+ level.insert(tLevelPair(insertName, &symbol));
+
+ return true;
+ } else {
+ result = level.insert(tLevelPair(insertName, &symbol));
+
+ return result.second;
+ }
+ }
+ }
+
+ TSymbol* find(const TString& name) const
+ {
+ tLevel::const_iterator it = level.find(name);
+ if (it == level.end())
+ return 0;
+ else
+ return (*it).second;
+ }
+
+ void findFunctionNameList(const TString& name, TVector<TFunction*>& list)
+ {
+ size_t parenAt = name.find_first_of('(');
+ TString base(name, 0, parenAt + 1);
+
+ tLevel::const_iterator begin = level.lower_bound(base);
+ base[parenAt] = ')'; // assume ')' is lexically after '('
+ tLevel::const_iterator end = level.upper_bound(base);
+ for (tLevel::const_iterator it = begin; it != end; ++it)
+ list.push_back(it->second->getAsFunction());
+ }
+
+ // See if there is already a function in the table having the given non-function-style name.
+ bool hasFunctionName(const TString& name) const
+ {
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ if (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0)
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // See if there is a variable at this level having the given non-function-style name.
+ // Return true if name is found, and set variable to true if the name was a variable.
+ bool findFunctionVariableName(const TString& name, bool& variable) const
+ {
+ tLevel::const_iterator candidate = level.lower_bound(name);
+ if (candidate != level.end()) {
+ const TString& candidateName = (*candidate).first;
+ TString::size_type parenAt = candidateName.find_first_of('(');
+ if (parenAt == candidateName.npos) {
+ // not a mangled name
+ if (candidateName == name) {
+ // found a variable name match
+ variable = true;
+ return true;
+ }
+ } else {
+ // a mangled name
+ if (candidateName.compare(0, parenAt, name) == 0) {
+ // found a function name match
+ variable = false;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Use this to do a lazy 'push' of precision defaults the first time
+ // a precision statement is seen in a new scope. Leave it at 0 for
+ // when no push was needed. Thus, it is not the current defaults,
+ // it is what to restore the defaults to when popping a level.
+ void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
+ {
+ // can call multiple times at one scope, will only latch on first call,
+ // as we're tracking the previous scope's values, not the current values
+ if (defaultPrecision != 0)
+ return;
+
+ defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
+ for (int t = 0; t < EbtNumTypes; ++t)
+ defaultPrecision[t] = p[t];
+ }
+
+ void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
+ {
+ // can be called for table level pops that didn't set the
+ // defaults
+ if (defaultPrecision == 0 || p == 0)
+ return;
+
+ for (int t = 0; t < EbtNumTypes; ++t)
+ p[t] = defaultPrecision[t];
+ }
+
+ void relateToOperator(const char* name, TOperator op);
+ void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
+ void dump(TInfoSink &infoSink) const;
+ TSymbolTableLevel* clone() const;
+ void readOnly();
+
+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; // named mappings
+ TPrecisionQualifier *defaultPrecision;
+ int anonId;
+};
+
+class TSymbolTable {
+public:
+ TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0)
+ {
+ //
+ // This symbol table cannot be used until push() is called.
+ //
+ }
+ ~TSymbolTable()
+ {
+ // this can be called explicitly; safest to code it so it can be called multiple times
+
+ // don't deallocate levels passed in from elsewhere
+ while (table.size() > adoptedLevels)
+ pop(0);
+ }
+
+ void adoptLevels(TSymbolTable& symTable)
+ {
+ for (unsigned int level = 0; level < symTable.table.size(); ++level) {
+ table.push_back(symTable.table[level]);
+ ++adoptedLevels;
+ }
+ uniqueId = symTable.uniqueId;
+ noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
+ separateNameSpaces = symTable.separateNameSpaces;
+ }
+
+ //
+ // While level adopting is generic, the methods below enact a the following
+ // convention for levels:
+ // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
+ // 1: per-stage built-ins, shared across all compiles, but a different copy per stage
+ // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins
+ // 3: user-shader globals
+ //
+protected:
+ static const int globalLevel = 3;
+ bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
+ bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
+ bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
+public:
+ bool isEmpty() { return table.size() == 0; }
+ bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
+ bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
+
+ void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
+ void setSeparateNameSpaces() { separateNameSpaces = true; }
+
+ void push()
+ {
+ table.push_back(new TSymbolTableLevel);
+ }
+
+ void pop(TPrecisionQualifier *p)
+ {
+ table[currentLevel()]->getPreviousDefaultPrecisions(p);
+ delete table.back();
+ table.pop_back();
+ }
+
+ //
+ // Insert a visible symbol into the symbol table so it can
+ // be found later by name.
+ //
+ // Returns false if the was a name collision.
+ //
+ bool insert(TSymbol& symbol)
+ {
+ symbol.setUniqueId(++uniqueId);
+
+ // make sure there isn't a function of this variable name
+ if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName()))
+ return false;
+
+ // check for not overloading or redefining a built-in function
+ if (noBuiltInRedeclarations) {
+ if (atGlobalLevel() && currentLevel() > 0) {
+ if (table[0]->hasFunctionName(symbol.getName()))
+ return false;
+ if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName()))
+ return false;
+ }
+ }
+
+ return table[currentLevel()]->insert(symbol, separateNameSpaces);
+ }
+
+ //
+ // To allocate an internal temporary, which will need to be uniquely
+ // identified by the consumer of the AST, but never need to
+ // found by doing a symbol table search by name, hence allowed an
+ // arbitrary name in the symbol with no worry of collision.
+ //
+ void makeInternalVariable(TSymbol& symbol)
+ {
+ symbol.setUniqueId(++uniqueId);
+ }
+
+ //
+ // Copy a variable or anonymous member's structure from a shared level so that
+ // it can be added (soon after return) to the symbol table where it can be
+ // modified without impacting other users of the shared table.
+ //
+ TSymbol* copyUpDeferredInsert(TSymbol* shared)
+ {
+ if (shared->getAsVariable()) {
+ TSymbol* copy = shared->clone();
+ copy->setUniqueId(shared->getUniqueId());
+ return copy;
+ } else {
+ const TAnonMember* anon = shared->getAsAnonMember();
+ assert(anon);
+ TVariable* container = anon->getAnonContainer().clone();
+ container->changeName(NewPoolTString(""));
+ container->setUniqueId(anon->getAnonContainer().getUniqueId());
+ return container;
+ }
+ }
+
+ TSymbol* copyUp(TSymbol* shared)
+ {
+ TSymbol* copy = copyUpDeferredInsert(shared);
+ table[globalLevel]->insert(*copy, separateNameSpaces);
+ if (shared->getAsVariable())
+ return copy;
+ else {
+ // return the copy of the anonymous member
+ return table[globalLevel]->find(shared->getName());
+ }
+ }
+
+ TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0)
+ {
+ int level = currentLevel();
+ TSymbol* symbol;
+ do {
+ symbol = table[level]->find(name);
+ --level;
+ } while (symbol == 0 && level >= 0);
+ level++;
+ if (builtIn)
+ *builtIn = isBuiltInLevel(level);
+ if (currentScope)
+ *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals
+
+ return symbol;
+ }
+
+ bool isFunctionNameVariable(const TString& name) const
+ {
+ if (separateNameSpaces)
+ return false;
+
+ int level = currentLevel();
+ do {
+ bool variable;
+ bool found = table[level]->findFunctionVariableName(name, variable);
+ if (found)
+ return variable;
+ --level;
+ } while (level >= 0);
+
+ return false;
+ }
+
+ void findFunctionNameList(const TString& name, TVector<TFunction*>& list, bool& builtIn)
+ {
+ // For user levels, return the set found in the first scope with a match
+ builtIn = false;
+ int level = currentLevel();
+ do {
+ table[level]->findFunctionNameList(name, list);
+ --level;
+ } while (list.empty() && level >= globalLevel);
+
+ if (! list.empty())
+ return;
+
+ // Gather across all built-in levels; they don't hide each other
+ builtIn = true;
+ do {
+ table[level]->findFunctionNameList(name, list);
+ --level;
+ } while (level >= 0);
+ }
+
+ void relateToOperator(const char* name, TOperator op)
+ {
+ for (unsigned int level = 0; level < table.size(); ++level)
+ table[level]->relateToOperator(name, op);
+ }
+
+ void setFunctionExtensions(const char* name, int num, const char* const extensions[])
+ {
+ for (unsigned int level = 0; level < table.size(); ++level)
+ table[level]->setFunctionExtensions(name, num, extensions);
+ }
+
+ void setVariableExtensions(const char* name, int num, const char* const extensions[])
+ {
+ TSymbol* symbol = find(TString(name));
+ if (symbol)
+ symbol->setExtensions(num, extensions);
+ }
+
+ int getMaxSymbolId() { return uniqueId; }
+ void dump(TInfoSink &infoSink) const;
+ void copyTable(const TSymbolTable& copyOf);
+
+ void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
+
+ void readOnly()
+ {
+ for (unsigned int level = 0; level < table.size(); ++level)
+ table[level]->readOnly();
+ }
+
+protected:
+ TSymbolTable(TSymbolTable&);
+ TSymbolTable& operator=(TSymbolTableLevel&);
+
+ int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+
+ std::vector<TSymbolTableLevel*> table;
+ int uniqueId; // for unique identification in code generation
+ bool noBuiltInRedeclarations;
+ bool separateNameSpaces;
+ unsigned int adoptedLevels;
+};
+
+} // end namespace glslang
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp
new file mode 100644
index 00000000000..c1192071b6c
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp
@@ -0,0 +1,677 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Help manage multiple profiles, versions, extensions etc.
+//
+// These don't return error codes, as the presumption is parsing will
+// always continue as if the tested feature were enabled, and thus there
+// is no error recovery needed.
+//
+
+//
+// HOW TO add a feature enabled by an extension.
+//
+// To add a new hypothetical "Feature F" to the front end, where an extension
+// "XXX_extension_X" can be used to enable the feature, do the following.
+//
+// OVERVIEW: Specific features are what are error-checked for, not
+// extensions: A specific Feature F might be enabled by an extension, or a
+// particular version in a particular profile, or a stage, or combinations, etc.
+//
+// The basic mechanism is to use the following to "declare" all the things that
+// enable/disable Feature F, in a code path that implements Feature F:
+//
+// requireProfile()
+// profileRequires()
+// requireStage()
+// checkDeprecated()
+// requireNotRemoved()
+// requireExtensions()
+//
+// Typically, only the first two calls are needed. They go into a code path that
+// implements Feature F, and will log the proper error/warning messages. Parsing
+// will then always continue as if the tested feature was enabled.
+//
+// There is typically no if-testing or conditional parsing, just insertion of the calls above.
+// However, if symbols specific to the extension are added (step 5), they will
+// only be added under tests that the minimum version and profile are present.
+//
+// 1) Add a symbol name for the extension string at the bottom of Versions.h:
+//
+// const char* const XXX_extension_X = "XXX_extension_X";
+//
+// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
+// the first function below:
+//
+// extensionBehavior[XXX_extension_X] = EBhDisable;
+//
+// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
+//
+// "#define XXX_extension_X 1\n"
+//
+// The new-line is important, as that ends preprocess tokens.
+//
+// 4) Insert a profile check in the feature's path (unless all profiles support the feature,
+// for some version level). That is, call requireProfile() to constrain the profiles, e.g.:
+//
+// // ... in a path specific to Feature F...
+// requireProfile(loc,
+// ECoreProfile | ECompatibilityProfile,
+// "Feature F");
+//
+// 5) For each profile that supports the feature, insert version/extension checks:
+//
+// The mostly likely scenario is that Feature F can only be used with a
+// particular profile if XXX_extension_X is present or the version is
+// high enough that the core specification already incorporated it.
+//
+// // following the requireProfile() call...
+// profileRequires(loc,
+// ECoreProfile | ECompatibilityProfile,
+// 420, // 0 if no version incorporated the feature into the core spec.
+// XXX_extension_X, // can be a list of extensions that all add the feature
+// "Feature F Description");
+//
+// This allows the feature if either A) one of the extensions is enabled or
+// B) the version is high enough. If no version yet incorporates the feature
+// into core, pass in 0.
+//
+// This can be called multiple times, if different profiles support the
+// feature starting at different version numbers or with different
+// extensions.
+//
+// This must be called for each profile allowed by the initial call to requireProfile().
+//
+// Profiles are all masks, which can be "or"-ed together.
+//
+// ENoProfile
+// ECoreProfile
+// ECompatibilityProfile
+// EEsProfile
+//
+// The ENoProfile profile is only for desktop, before profiles showed up in version 150;
+// All other #version with no profile default to either es or core, and so have profiles.
+//
+// You can select all but a particular profile using ~. The following basically means "desktop":
+//
+// ~EEsProfile
+//
+// 6) If built-in symbols are added by the extension, add them in Initialize.cpp: Their use
+// will be automatically error checked against the extensions enabled at that moment.
+// see the comment at the top of Initialize.cpp for where to put them. Establish them at
+// the earliest release that supports the extension. Then, tag them with the
+// set of extensions that both enable them and are necessary, given the version of the symbol
+// table. (There is a different symbol table for each version.)
+//
+
+#include "parseVersions.h"
+#include "localintermediate.h"
+
+namespace glslang {
+
+//
+// Initialize all extensions, almost always to 'disable', as once their features
+// are incorporated into a core version, their features are supported through allowing that
+// core version, not through a pseudo-enablement of the extension.
+//
+void TParseVersions::initializeExtensionBehavior()
+{
+ extensionBehavior[E_GL_OES_texture_3D] = EBhDisable;
+ extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
+ extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
+ extensionBehavior[E_GL_OES_EGL_image_external] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_texture_lod] = EBhDisable;
+
+ extensionBehavior[E_GL_ARB_texture_rectangle] = EBhDisable;
+ extensionBehavior[E_GL_3DL_array_objects] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shading_language_420pack] = EBhDisable;
+ extensionBehavior[E_GL_ARB_texture_gather] = EBhDisable;
+ extensionBehavior[E_GL_ARB_gpu_shader5] = EBhDisablePartial;
+ extensionBehavior[E_GL_ARB_separate_shader_objects] = EBhDisable;
+ extensionBehavior[E_GL_ARB_compute_shader] = EBhDisable;
+ extensionBehavior[E_GL_ARB_tessellation_shader] = EBhDisable;
+ extensionBehavior[E_GL_ARB_enhanced_layouts] = EBhDisable;
+ extensionBehavior[E_GL_ARB_texture_cube_map_array] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_texture_lod] = EBhDisable;
+ extensionBehavior[E_GL_ARB_explicit_attrib_location] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable;
+ extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable;
+ extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable;
+ extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable;
+ extensionBehavior[E_GL_ARB_gl_spirv] = EBhDisable;
+ extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable;
+ extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable;
+ extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable;
+// extensionBehavior[E_GL_ARB_cull_distance] = EBhDisable; // present for 4.5, but need extension control over block members
+
+ // #line and #include
+ extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
+ extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable;
+
+ // AEP
+ extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable;
+ extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable;
+ extensionBehavior[E_GL_OES_sample_variables] = EBhDisable;
+ extensionBehavior[E_GL_OES_shader_image_atomic] = EBhDisable;
+ extensionBehavior[E_GL_OES_shader_multisample_interpolation] = EBhDisable;
+ extensionBehavior[E_GL_OES_texture_storage_multisample_2d_array] = EBhDisable;
+ extensionBehavior[E_GL_EXT_geometry_shader] = EBhDisable;
+ extensionBehavior[E_GL_EXT_geometry_point_size] = EBhDisable;
+ extensionBehavior[E_GL_EXT_gpu_shader5] = EBhDisable;
+ extensionBehavior[E_GL_EXT_primitive_bounding_box] = EBhDisable;
+ extensionBehavior[E_GL_EXT_shader_io_blocks] = EBhDisable;
+ extensionBehavior[E_GL_EXT_tessellation_shader] = EBhDisable;
+ extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
+ extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable;
+ extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable;
+
+ // OES matching AEP
+ extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
+ extensionBehavior[E_GL_OES_geometry_point_size] = EBhDisable;
+ extensionBehavior[E_GL_OES_gpu_shader5] = EBhDisable;
+ extensionBehavior[E_GL_OES_primitive_bounding_box] = EBhDisable;
+ extensionBehavior[E_GL_OES_shader_io_blocks] = EBhDisable;
+ extensionBehavior[E_GL_OES_tessellation_shader] = EBhDisable;
+ extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
+ extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
+ extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
+}
+
+// Get code that is not part of a shared symbol table, is specific to this shader,
+// or needed by the preprocessor (which does not use a shared symbol table).
+void TParseVersions::getPreamble(std::string& preamble)
+{
+ if (profile == EEsProfile) {
+ preamble =
+ "#define GL_ES 1\n"
+ "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
+ "#define GL_OES_texture_3D 1\n"
+ "#define GL_OES_standard_derivatives 1\n"
+ "#define GL_EXT_frag_depth 1\n"
+ "#define GL_OES_EGL_image_external 1\n"
+ "#define GL_EXT_shader_texture_lod 1\n"
+
+ // AEP
+ "#define GL_ANDROID_extension_pack_es31a 1\n"
+ "#define GL_KHR_blend_equation_advanced 1\n"
+ "#define GL_OES_sample_variables 1\n"
+ "#define GL_OES_shader_image_atomic 1\n"
+ "#define GL_OES_shader_multisample_interpolation 1\n"
+ "#define GL_OES_texture_storage_multisample_2d_array 1\n"
+ "#define GL_EXT_geometry_shader 1\n"
+ "#define GL_EXT_geometry_point_size 1\n"
+ "#define GL_EXT_gpu_shader5 1\n"
+ "#define GL_EXT_primitive_bounding_box 1\n"
+ "#define GL_EXT_shader_io_blocks 1\n"
+ "#define GL_EXT_tessellation_shader 1\n"
+ "#define GL_EXT_tessellation_point_size 1\n"
+ "#define GL_EXT_texture_buffer 1\n"
+ "#define GL_EXT_texture_cube_map_array 1\n"
+
+ // OES matching AEP
+ "#define GL_OES_geometry_shader 1\n"
+ "#define GL_OES_geometry_point_size 1\n"
+ "#define GL_OES_gpu_shader5 1\n"
+ "#define GL_OES_primitive_bounding_box 1\n"
+ "#define GL_OES_shader_io_blocks 1\n"
+ "#define GL_OES_tessellation_shader 1\n"
+ "#define GL_OES_tessellation_point_size 1\n"
+ "#define GL_OES_texture_buffer 1\n"
+ "#define GL_OES_texture_cube_map_array 1\n"
+ ;
+ } else {
+ preamble =
+ "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
+ "#define GL_ARB_texture_rectangle 1\n"
+ "#define GL_ARB_shading_language_420pack 1\n"
+ "#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_compute_shader 1\n"
+ "#define GL_ARB_tessellation_shader 1\n"
+ "#define GL_ARB_enhanced_layouts 1\n"
+ "#define GL_ARB_texture_cube_map_array 1\n"
+ "#define GL_ARB_shader_texture_lod 1\n"
+ "#define GL_ARB_explicit_attrib_location 1\n"
+ "#define GL_ARB_shader_image_load_store 1\n"
+ "#define GL_ARB_shader_atomic_counters 1\n"
+ "#define GL_ARB_shader_draw_parameters 1\n"
+ "#define GL_ARB_shader_group_vote 1\n"
+ "#define GL_ARB_derivative_control 1\n"
+ "#define GL_ARB_shader_texture_image_samples 1\n"
+ "#define GL_ARB_viewport_array 1\n"
+ "#define GL_ARB_gpu_shader_int64 1\n"
+ "#define GL_ARB_gl_spirv 1\n"
+ "#define GL_ARB_shader_ballot 1\n"
+ "#define GL_ARB_sparse_texture2 1\n"
+ "#define GL_ARB_sparse_texture_clamp 1\n"
+// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
+ ;
+ }
+
+ // #line and #include
+ preamble +=
+ "#define GL_GOOGLE_cpp_style_line_directive 1\n"
+ "#define GL_GOOGLE_include_directive 1\n"
+ ;
+
+ if (vulkan > 0)
+ preamble += "#define VULKAN 100\n";
+}
+
+//
+// When to use requireProfile():
+//
+// Use if only some profiles support a feature. However, if within a profile the feature
+// is version or extension specific, follow this call with calls to profileRequires().
+//
+// Operation: If the current profile is not one of the profileMask,
+// give an error message.
+//
+void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
+{
+ if (! (profile & profileMask))
+ error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
+}
+
+//
+// Map from stage enum to externally readable text name.
+//
+const char* StageName(EShLanguage stage)
+{
+ switch(stage) {
+ case EShLangVertex: return "vertex";
+ case EShLangTessControl: return "tessellation control";
+ case EShLangTessEvaluation: return "tessellation evaluation";
+ case EShLangGeometry: return "geometry";
+ case EShLangFragment: return "fragment";
+ case EShLangCompute: return "compute";
+ default: return "unknown stage";
+ }
+}
+
+//
+// When to use profileRequires():
+//
+// If a set of profiles have the same requirements for what version or extensions
+// are needed to support a feature.
+//
+// It must be called for each profile that needs protection. Use requireProfile() first
+// to reduce that set of profiles.
+//
+// Operation: Will issue warnings/errors based on the current profile, version, and extension
+// behaviors. It only checks extensions when the current profile is one of the profileMask.
+//
+// A minVersion of 0 means no version of the profileMask support this in core,
+// the extension must be present.
+//
+
+// entry point that takes multiple extensions
+void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ if (profile & profileMask) {
+ bool okay = false;
+ if (minVersion > 0 && version >= minVersion)
+ okay = true;
+ for (int i = 0; i < numExtensions; ++i) {
+ switch (getExtensionBehavior(extensions[i])) {
+ case EBhWarn:
+ infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
+ // fall through
+ case EBhRequire:
+ case EBhEnable:
+ okay = true;
+ break;
+ default: break; // some compilers want this
+ }
+ }
+
+ if (! okay)
+ error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
+ }
+}
+
+// entry point for the above that takes a single extension
+void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, const char* featureDesc)
+{
+ profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
+}
+
+//
+// When to use requireStage()
+//
+// If only some stages support a feature.
+//
+// Operation: If the current stage is not present, give an error message.
+//
+void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc)
+{
+ if (((1 << language) & languageMask) == 0)
+ error(loc, "not supported in this stage:", featureDesc, StageName(language));
+}
+
+// If only one stage supports a feature, this can be called. But, all supporting stages
+// must be specified with one call.
+void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc)
+{
+ requireStage(loc, static_cast<EShLanguageMask>(1 << stage), featureDesc);
+}
+
+//
+// Within a set of profiles, see if a feature is deprecated and give an error or warning based on whether
+// a future compatibility context is being use.
+//
+void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int depVersion, const char* featureDesc)
+{
+ if (profile & profileMask) {
+ if (version >= depVersion) {
+ if (forwardCompatible)
+ error(loc, "deprecated, may be removed in future release", featureDesc, "");
+ else if (! suppressWarnings())
+ infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
+ String(depVersion) + "; may be removed in future release").c_str(), loc);
+ }
+ }
+}
+
+//
+// Within a set of profiles, see if a feature has now been removed and if so, give an error.
+// The version argument is the first version no longer having the feature.
+//
+void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, int removedVersion, const char* featureDesc)
+{
+ if (profile & profileMask) {
+ if (version >= removedVersion) {
+ const int maxSize = 60;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName(profile), removedVersion);
+ error(loc, "no longer supported in", featureDesc, buf);
+ }
+ }
+}
+
+// Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false.
+// Warns appropriately if the requested behavior of an extension is "warn".
+bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ // First, see if any of the extensions are enabled
+ for (int i = 0; i < numExtensions; ++i) {
+ TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
+ if (behavior == EBhEnable || behavior == EBhRequire)
+ return true;
+ }
+
+ // See if any extensions want to give a warning on use; give warnings for all such extensions
+ bool warned = false;
+ for (int i = 0; i < numExtensions; ++i) {
+ TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
+ if (behavior == EBhDisable && relaxedErrors()) {
+ infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
+ behavior = EBhWarn;
+ }
+ if (behavior == EBhWarn) {
+ infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
+ warned = true;
+ }
+ }
+ if (warned)
+ return true;
+ return false;
+}
+
+//
+// Use when there are no profile/version to check, it's just an error if one of the
+// extensions is not present.
+//
+void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return;
+
+ // If we get this far, give errors explaining what extensions are needed
+ if (numExtensions == 1)
+ error(loc, "required extension not requested:", featureDesc, extensions[0]);
+ else {
+ error(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
+ for (int i = 0; i < numExtensions; ++i)
+ infoSink.info.message(EPrefixNone, extensions[i]);
+ }
+}
+
+//
+// Use by preprocessor when there are no profile/version to check, it's just an error if one of the
+// extensions is not present.
+//
+void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
+{
+ if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return;
+
+ // If we get this far, give errors explaining what extensions are needed
+ if (numExtensions == 1)
+ ppError(loc, "required extension not requested:", featureDesc, extensions[0]);
+ else {
+ ppError(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
+ for (int i = 0; i < numExtensions; ++i)
+ infoSink.info.message(EPrefixNone, extensions[i]);
+ }
+}
+
+TExtensionBehavior TParseVersions::getExtensionBehavior(const char* extension)
+{
+ auto iter = extensionBehavior.find(TString(extension));
+ if (iter == extensionBehavior.end())
+ return EBhMissing;
+ else
+ return iter->second;
+}
+
+// Returns true if the given extension is set to enable, require, or warn.
+bool TParseVersions::extensionTurnedOn(const char* const extension)
+{
+ switch (getExtensionBehavior(extension)) {
+ case EBhEnable:
+ case EBhRequire:
+ case EBhWarn:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+// See if any of the extensions are set to enable, require, or warn.
+bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[])
+{
+ for (int i = 0; i < numExtensions; ++i) {
+ if (extensionTurnedOn(extensions[i])) return true;
+ }
+ return false;
+}
+
+//
+// Change the current state of an extension's behavior.
+//
+void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString)
+{
+ // Translate from text string of extension's behavior to an enum.
+ TExtensionBehavior behavior = EBhDisable;
+ if (! strcmp("require", behaviorString))
+ behavior = EBhRequire;
+ else if (! strcmp("enable", behaviorString))
+ behavior = EBhEnable;
+ else if (! strcmp("disable", behaviorString))
+ behavior = EBhDisable;
+ else if (! strcmp("warn", behaviorString))
+ behavior = EBhWarn;
+ else {
+ error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
+ return;
+ }
+
+ // update the requested extension
+ updateExtensionBehavior(extension, behavior);
+
+ // see if need to propagate to implicitly modified things
+ if (strcmp(extension, "GL_ANDROID_extension_pack_es31a") == 0) {
+ // to everything in AEP
+ updateExtensionBehavior(line, "GL_KHR_blend_equation_advanced", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_sample_variables", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_shader_image_atomic", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_shader_multisample_interpolation", behaviorString);
+ updateExtensionBehavior(line, "GL_OES_texture_storage_multisample_2d_array", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_geometry_shader", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_gpu_shader5", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_primitive_bounding_box", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_tessellation_shader", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_texture_buffer", behaviorString);
+ updateExtensionBehavior(line, "GL_EXT_texture_cube_map_array", behaviorString);
+ }
+ // geometry to io_blocks
+ else if (strcmp(extension, "GL_EXT_geometry_shader") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
+ else if (strcmp(extension, "GL_OES_geometry_shader") == 0)
+ updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
+ // tessellation to io_blocks
+ else if (strcmp(extension, "GL_EXT_tessellation_shader") == 0)
+ updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
+ else if (strcmp(extension, "GL_OES_tessellation_shader") == 0)
+ updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
+ else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0)
+ updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString);
+ // SPIR-V
+ else if (strcmp(extension, "GL_ARB_gl_spirv") == 0)
+ spv = 100;
+}
+
+void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
+{
+ // Update the current behavior
+ if (strcmp(extension, "all") == 0) {
+ // special case for the 'all' extension; apply it to every extension present
+ if (behavior == EBhRequire || behavior == EBhEnable) {
+ error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", "");
+ return;
+ } else {
+ for (auto iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter)
+ iter->second = behavior;
+ }
+ } else {
+ // Do the update for this single extension
+ auto iter = extensionBehavior.find(TString(extension));
+ if (iter == extensionBehavior.end()) {
+ switch (behavior) {
+ case EBhRequire:
+ error(getCurrentLoc(), "extension not supported:", "#extension", extension);
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ warn(getCurrentLoc(), "extension not supported:", "#extension", extension);
+ break;
+ default:
+ assert(0 && "unexpected behavior");
+ }
+
+ return;
+ } else {
+ if (iter->second == EBhDisablePartial)
+ warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
+ if (behavior == EBhEnable || behavior == EBhRequire)
+ intermediate.addRequestedExtension(extension);
+ iter->second = behavior;
+ }
+ }
+}
+
+// Call for any operation needing full GLSL integer data-type support.
+void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
+{
+ profileRequires(loc, ENoProfile, 130, nullptr, op);
+ profileRequires(loc, EEsProfile, 300, nullptr, op);
+}
+
+// Call for any operation needing GLSL double data-type support.
+void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
+{
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+ profileRequires(loc, ECoreProfile, 400, nullptr, op);
+ profileRequires(loc, ECompatibilityProfile, 400, nullptr, op);
+}
+
+// Call for any operation needing GLSL 64-bit integer data-type support.
+void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+ if (! builtIn) {
+ requireExtensions(loc, 1, &E_GL_ARB_gpu_shader_int64, "shader int64");
+ requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+ profileRequires(loc, ECoreProfile, 450, nullptr, op);
+ profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
+ }
+}
+
+// Call for any operation removed because SPIR-V is in use.
+void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
+{
+ if (spv > 0)
+ error(loc, "not allowed when generating SPIR-V", op, "");
+}
+
+// Call for any operation removed because Vulkan SPIR-V is being generated.
+void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
+{
+ if (vulkan > 0)
+ error(loc, "not allowed when using GLSL for Vulkan", op, "");
+}
+
+// Call for any operation that requires Vulkan.
+void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op)
+{
+ if (vulkan == 0)
+ error(loc, "only allowed when using GLSL for Vulkan", op, "");
+}
+
+// Call for any operation that requires SPIR-V.
+void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
+{
+ if (spv == 0)
+ error(loc, "only allowed when generating SPIR-V", op, "");
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.h
new file mode 100644
index 00000000000..ba08ca3c00d
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/Versions.h
@@ -0,0 +1,185 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _VERSIONS_INCLUDED_
+#define _VERSIONS_INCLUDED_
+
+//
+// Help manage multiple profiles, versions, extensions etc.
+//
+
+//
+// Profiles are set up for masking operations, so queries can be done on multiple
+// profiles at the same time.
+//
+// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
+// defects from mixing the two different forms.
+//
+typedef enum {
+ EBadProfile = 0,
+ ENoProfile = (1 << 0), // only for desktop, before profiles showed up
+ ECoreProfile = (1 << 1),
+ ECompatibilityProfile = (1 << 2),
+ EEsProfile = (1 << 3)
+} EProfile;
+
+namespace glslang {
+
+//
+// Map from profile enum to externally readable text name.
+//
+inline const char* ProfileName(EProfile profile)
+{
+ switch (profile) {
+ case ENoProfile: return "none";
+ case ECoreProfile: return "core";
+ case ECompatibilityProfile: return "compatibility";
+ case EEsProfile: return "es";
+ default: return "unknown profile";
+ }
+}
+
+//
+// The behaviors from the GLSL "#extension extension_name : behavior"
+//
+typedef enum {
+ EBhMissing = 0,
+ EBhRequire,
+ EBhEnable,
+ EBhWarn,
+ EBhDisable,
+ EBhDisablePartial // use as initial state of an extension that is only partially implemented
+} TExtensionBehavior;
+
+//
+// Symbolic names for extensions. Strings may be directly used when calling the
+// functions, but better to have the compiler do spelling checks.
+//
+const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D";
+const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives";
+const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth";
+const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
+const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod";
+
+const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle";
+const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects";
+const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack";
+const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather";
+const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5";
+const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects";
+const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader";
+const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader";
+const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts";
+const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array";
+const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod";
+const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location";
+const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store";
+const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters";
+const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters";
+const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote";
+const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control";
+const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples";
+const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array";
+const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64";
+const char* const E_GL_ARB_gl_spirv = "GL_ARB_gl_spirv";
+const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot";
+const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2";
+const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp";
+//const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members
+
+// #line and #include
+const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
+const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive";
+
+// AEP
+const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a";
+const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced";
+const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables";
+const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic";
+const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation";
+const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array";
+const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader";
+const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size";
+const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5";
+const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box";
+const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks";
+const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader";
+const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size";
+const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
+const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
+
+// OES matching AEP
+const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
+const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size";
+const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5";
+const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box";
+const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks";
+const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader";
+const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size";
+const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer";
+const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array";
+
+// Arrays of extensions for the above AEP duplications
+
+const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };
+const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]);
+
+const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size };
+const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]);
+
+const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 };
+const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]);
+
+const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box };
+const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]);
+
+const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks };
+const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]);
+
+const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader };
+const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]);
+
+const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size };
+const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]);
+
+const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer };
+const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]);
+
+const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array };
+const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]);
+
+} // end namespace glslang
+
+#endif // _VERSIONS_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/gl_types.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/gl_types.h
new file mode 100644
index 00000000000..9e877d37dc3
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/gl_types.h
@@ -0,0 +1,160 @@
+/*
+** Copyright (c) 2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+
+#define GL_INT 0x1404
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+
+#define GL_INT64_ARB 0x140E
+#define GL_INT64_VEC2_ARB 0x8FE9
+#define GL_INT64_VEC3_ARB 0x8FEA
+#define GL_INT64_VEC4_ARB 0x8FEB
+
+#define GL_UNSIGNED_INT64_ARB 0x140F
+#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5
+#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6
+#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7
+
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang.y b/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang.y
new file mode 100644
index 00000000000..4f8e3fc108c
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang.y
@@ -0,0 +1,2703 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+/**
+ * This is bison grammar and productions for parsing all versions of the
+ * GLSL shading languages.
+ */
+%{
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../Public/ShaderLang.h"
+
+using namespace glslang;
+
+%}
+
+%union {
+ struct {
+ glslang::TSourceLoc loc;
+ union {
+ glslang::TString *string;
+ int i;
+ unsigned int u;
+ long long i64;
+ unsigned long long u64;
+ bool b;
+ double d;
+ };
+ glslang::TSymbol* symbol;
+ } lex;
+ struct {
+ glslang::TSourceLoc loc;
+ glslang::TOperator op;
+ union {
+ TIntermNode* intermNode;
+ glslang::TIntermNodePair nodePair;
+ glslang::TIntermTyped* intermTypedNode;
+ };
+ union {
+ glslang::TPublicType type;
+ glslang::TFunction* function;
+ glslang::TParameter param;
+ glslang::TTypeLoc typeLine;
+ glslang::TTypeList* typeList;
+ glslang::TArraySizes* arraySizes;
+ glslang::TIdentifierList* identifierList;
+ };
+ } interm;
+}
+
+%{
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4065)
+ #pragma warning(disable : 4127)
+ #pragma warning(disable : 4244)
+#endif
+
+#define parseContext (*pParseContext)
+#define yyerror(context, msg) context->parserError(msg)
+
+extern int yylex(YYSTYPE*, TParseContext&);
+
+%}
+
+%parse-param {glslang::TParseContext* pParseContext}
+%lex-param {parseContext}
+%pure-parser // enable thread safety
+%expect 1 // One shift reduce conflict because of if | else
+
+%token <lex> ATTRIBUTE VARYING
+%token <lex> CONST BOOL FLOAT DOUBLE INT UINT INT64_T UINT64_T
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT SUBROUTINE
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 I64VEC2 I64VEC3 I64VEC4 UVEC2 UVEC3 UVEC4 U64VEC2 U64VEC3 U64VEC4 VEC2 VEC3 VEC4
+%token <lex> MAT2 MAT3 MAT4 CENTROID IN OUT INOUT
+%token <lex> UNIFORM PATCH SAMPLE BUFFER SHARED
+%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY
+%token <lex> DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4
+%token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT
+
+%token <lex> MAT2X2 MAT2X3 MAT2X4
+%token <lex> MAT3X2 MAT3X3 MAT3X4
+%token <lex> MAT4X2 MAT4X3 MAT4X4
+%token <lex> DMAT2X2 DMAT2X3 DMAT2X4
+%token <lex> DMAT3X2 DMAT3X3 DMAT3X4
+%token <lex> DMAT4X2 DMAT4X3 DMAT4X4
+%token <lex> ATOMIC_UINT
+
+// combined image/sampler
+%token <lex> SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW
+%token <lex> SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW
+%token <lex> SAMPLER2DARRAYSHADOW ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE
+%token <lex> ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D
+%token <lex> USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY
+%token <lex> SAMPLER2DRECT SAMPLER2DRECTSHADOW ISAMPLER2DRECT USAMPLER2DRECT
+%token <lex> SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER
+%token <lex> SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW
+%token <lex> ISAMPLERCUBEARRAY USAMPLERCUBEARRAY
+%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
+%token <lex> SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
+%token <lex> SAMPLEREXTERNALOES
+
+// pure sampler
+%token <lex> SAMPLER SAMPLERSHADOW
+
+// texture without sampler
+%token <lex> TEXTURE1D TEXTURE2D TEXTURE3D TEXTURECUBE
+%token <lex> TEXTURE1DARRAY TEXTURE2DARRAY
+%token <lex> ITEXTURE1D ITEXTURE2D ITEXTURE3D ITEXTURECUBE
+%token <lex> ITEXTURE1DARRAY ITEXTURE2DARRAY UTEXTURE1D UTEXTURE2D UTEXTURE3D
+%token <lex> UTEXTURECUBE UTEXTURE1DARRAY UTEXTURE2DARRAY
+%token <lex> TEXTURE2DRECT ITEXTURE2DRECT UTEXTURE2DRECT
+%token <lex> TEXTUREBUFFER ITEXTUREBUFFER UTEXTUREBUFFER
+%token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY
+%token <lex> TEXTURE2DMS ITEXTURE2DMS UTEXTURE2DMS
+%token <lex> TEXTURE2DMSARRAY ITEXTURE2DMSARRAY UTEXTURE2DMSARRAY
+
+// input attachments
+%token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
+
+%token <lex> IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D
+%token <lex> UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D
+%token <lex> IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT
+%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
+%token <lex> IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
+%token <lex> IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY
+%token <lex> IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
+%token <lex> IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY
+%token <lex> IMAGE2DMS IIMAGE2DMS UIMAGE2DMS
+%token <lex> IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY
+
+%token <lex> STRUCT VOID WHILE
+
+%token <lex> IDENTIFIER TYPE_NAME
+%token <lex> FLOATCONSTANT DOUBLECONSTANT INTCONSTANT UINTCONSTANT INT64CONSTANT UINT64CONSTANT BOOLCONSTANT
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%token <lex> INVARIANT PRECISE
+%token <lex> HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+
+%token <lex> PACKED RESOURCE SUPERP
+
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer initializer_list condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermNode> statement_list switch_statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> switch_statement case_label
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_scoped
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+
+%type <interm> array_specifier
+%type <interm.type> precise_qualifier invariant_qualifier interpolation_qualifier storage_qualifier precision_qualifier
+%type <interm.type> layout_qualifier layout_qualifier_id_list layout_qualifier_id
+
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> single_type_qualifier
+%type <interm.type> type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list type_name_list
+%type <interm> block_structure
+%type <interm.function> function_header function_declarator
+%type <interm.function> function_header_with_parameters
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method function_identifier function_call_header
+
+%type <interm.identifierList> identifier_list
+
+%start translation_unit
+%%
+
+variable_identifier
+ : IDENTIFIER {
+ $$ = parseContext.handleVariable($1.loc, $1.symbol, $1.string);
+ }
+ ;
+
+primary_expression
+ : variable_identifier {
+ $$ = $1;
+ }
+ | INTCONSTANT {
+ $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
+ }
+ | UINTCONSTANT {
+ parseContext.fullIntegerCheck($1.loc, "unsigned literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
+ }
+ | INT64CONSTANT {
+ parseContext.int64Check($1.loc, "64-bit integer literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.i64, $1.loc, true);
+ }
+ | UINT64CONSTANT {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.u64, $1.loc, true);
+ }
+ | FLOATCONSTANT {
+ $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
+ }
+ | DOUBLECONSTANT {
+ parseContext.doubleCheck($1.loc, "double literal");
+ $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true);
+ }
+ | BOOLCONSTANT {
+ $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
+ }
+ | LEFT_PAREN expression RIGHT_PAREN {
+ $$ = $2;
+ if ($$->getAsConstantUnion())
+ $$->getAsConstantUnion()->setExpression();
+ }
+ ;
+
+postfix_expression
+ : primary_expression {
+ $$ = $1;
+ }
+ | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+ $$ = parseContext.handleBracketDereference($2.loc, $1, $3);
+ }
+ | function_call {
+ $$ = $1;
+ }
+ | postfix_expression DOT IDENTIFIER {
+ $$ = parseContext.handleDotDereference($3.loc, $1, *$3.string);
+ }
+ | postfix_expression INC_OP {
+ parseContext.variableCheck($1);
+ parseContext.lValueErrorCheck($2.loc, "++", $1);
+ $$ = parseContext.handleUnaryMath($2.loc, "++", EOpPostIncrement, $1);
+ }
+ | postfix_expression DEC_OP {
+ parseContext.variableCheck($1);
+ parseContext.lValueErrorCheck($2.loc, "--", $1);
+ $$ = parseContext.handleUnaryMath($2.loc, "--", EOpPostDecrement, $1);
+ }
+ ;
+
+integer_expression
+ : expression {
+ parseContext.integerCheck($1, "[]");
+ $$ = $1;
+ }
+ ;
+
+function_call
+ : function_call_or_method {
+ $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode);
+ delete $1.function;
+ }
+ ;
+
+function_call_or_method
+ : function_call_generic {
+ $$ = $1;
+ }
+ ;
+
+function_call_generic
+ : function_call_header_with_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.loc = $2.loc;
+ }
+ | function_call_header_no_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.loc = $2.loc;
+ }
+ ;
+
+function_call_header_no_parameters
+ : function_call_header VOID {
+ $$ = $1;
+ }
+ | function_call_header {
+ $$ = $1;
+ }
+ ;
+
+function_call_header_with_parameters
+ : function_call_header assignment_expression {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy($2->getType());
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = $2;
+ }
+ | function_call_header_with_parameters COMMA assignment_expression {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy($3->getType());
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc);
+ }
+ ;
+
+function_call_header
+ : function_identifier LEFT_PAREN {
+ $$ = $1;
+ }
+ ;
+
+// Grammar Note: Constructors look like functions, but are recognized as types.
+
+function_identifier
+ : type_specifier {
+ // Constructor
+ $$.intermNode = 0;
+ $$.function = parseContext.handleConstructorCall($1.loc, $1);
+ }
+ | postfix_expression {
+ //
+ // Should be a method or subroutine call, but we haven't recognized the arguments yet.
+ //
+ $$.function = 0;
+ $$.intermNode = 0;
+
+ TIntermMethod* method = $1->getAsMethodNode();
+ if (method) {
+ $$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength);
+ $$.intermNode = method->getObject();
+ } else {
+ TIntermSymbol* symbol = $1->getAsSymbolNode();
+ if (symbol) {
+ parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName());
+ TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid));
+ $$.function = function;
+ } else
+ parseContext.error($1->getLoc(), "function call, method, or subroutine call expected", "", "");
+ }
+
+ if ($$.function == 0) {
+ // error recover
+ TString empty("");
+ $$.function = new TFunction(&empty, TType(EbtVoid), EOpNull);
+ }
+ }
+ ;
+
+unary_expression
+ : postfix_expression {
+ parseContext.variableCheck($1);
+ $$ = $1;
+ if (TIntermMethod* method = $1->getAsMethodNode())
+ parseContext.error($1->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), "");
+ }
+ | INC_OP unary_expression {
+ parseContext.lValueErrorCheck($1.loc, "++", $2);
+ $$ = parseContext.handleUnaryMath($1.loc, "++", EOpPreIncrement, $2);
+ }
+ | DEC_OP unary_expression {
+ parseContext.lValueErrorCheck($1.loc, "--", $2);
+ $$ = parseContext.handleUnaryMath($1.loc, "--", EOpPreDecrement, $2);
+ }
+ | unary_operator unary_expression {
+ if ($1.op != EOpNull) {
+ char errorOp[2] = {0, 0};
+ switch($1.op) {
+ case EOpNegative: errorOp[0] = '-'; break;
+ case EOpLogicalNot: errorOp[0] = '!'; break;
+ case EOpBitwiseNot: errorOp[0] = '~'; break;
+ default: break; // some compilers want this
+ }
+ $$ = parseContext.handleUnaryMath($1.loc, errorOp, $1.op, $2);
+ } else {
+ $$ = $2;
+ if ($$->getAsConstantUnion())
+ $$->getAsConstantUnion()->setExpression();
+ }
+ }
+ ;
+// Grammar Note: No traditional style type casts.
+
+unary_operator
+ : PLUS { $$.loc = $1.loc; $$.op = EOpNull; }
+ | DASH { $$.loc = $1.loc; $$.op = EOpNegative; }
+ | BANG { $$.loc = $1.loc; $$.op = EOpLogicalNot; }
+ | TILDE { $$.loc = $1.loc; $$.op = EOpBitwiseNot;
+ parseContext.fullIntegerCheck($1.loc, "bitwise not"); }
+ ;
+// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+
+multiplicative_expression
+ : unary_expression { $$ = $1; }
+ | multiplicative_expression STAR unary_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "*", EOpMul, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | multiplicative_expression SLASH unary_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "/", EOpDiv, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | multiplicative_expression PERCENT unary_expression {
+ parseContext.fullIntegerCheck($2.loc, "%");
+ $$ = parseContext.handleBinaryMath($2.loc, "%", EOpMod, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+additive_expression
+ : multiplicative_expression { $$ = $1; }
+ | additive_expression PLUS multiplicative_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "+", EOpAdd, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | additive_expression DASH multiplicative_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "-", EOpSub, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+shift_expression
+ : additive_expression { $$ = $1; }
+ | shift_expression LEFT_OP additive_expression {
+ parseContext.fullIntegerCheck($2.loc, "bit shift left");
+ $$ = parseContext.handleBinaryMath($2.loc, "<<", EOpLeftShift, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ | shift_expression RIGHT_OP additive_expression {
+ parseContext.fullIntegerCheck($2.loc, "bit shift right");
+ $$ = parseContext.handleBinaryMath($2.loc, ">>", EOpRightShift, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+relational_expression
+ : shift_expression { $$ = $1; }
+ | relational_expression LEFT_ANGLE shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "<", EOpLessThan, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | relational_expression RIGHT_ANGLE shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, ">", EOpGreaterThan, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | relational_expression LE_OP shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "<=", EOpLessThanEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | relational_expression GE_OP shift_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, ">=", EOpGreaterThanEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+equality_expression
+ : relational_expression { $$ = $1; }
+ | equality_expression EQ_OP relational_expression {
+ parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
+ parseContext.opaqueCheck($2.loc, $1->getType(), "==");
+ parseContext.specializationCheck($2.loc, $1->getType(), "==");
+ $$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ | equality_expression NE_OP relational_expression {
+ parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
+ parseContext.opaqueCheck($2.loc, $1->getType(), "!=");
+ parseContext.specializationCheck($2.loc, $1->getType(), "!=");
+ $$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+and_expression
+ : equality_expression { $$ = $1; }
+ | and_expression AMPERSAND equality_expression {
+ parseContext.fullIntegerCheck($2.loc, "bitwise and");
+ $$ = parseContext.handleBinaryMath($2.loc, "&", EOpAnd, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+exclusive_or_expression
+ : and_expression { $$ = $1; }
+ | exclusive_or_expression CARET and_expression {
+ parseContext.fullIntegerCheck($2.loc, "bitwise exclusive or");
+ $$ = parseContext.handleBinaryMath($2.loc, "^", EOpExclusiveOr, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+inclusive_or_expression
+ : exclusive_or_expression { $$ = $1; }
+ | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+ parseContext.fullIntegerCheck($2.loc, "bitwise inclusive or");
+ $$ = parseContext.handleBinaryMath($2.loc, "|", EOpInclusiveOr, $1, $3);
+ if ($$ == 0)
+ $$ = $1;
+ }
+ ;
+
+logical_and_expression
+ : inclusive_or_expression { $$ = $1; }
+ | logical_and_expression AND_OP inclusive_or_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "&&", EOpLogicalAnd, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+logical_xor_expression
+ : logical_and_expression { $$ = $1; }
+ | logical_xor_expression XOR_OP logical_and_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "^^", EOpLogicalXor, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+logical_or_expression
+ : logical_xor_expression { $$ = $1; }
+ | logical_or_expression OR_OP logical_xor_expression {
+ $$ = parseContext.handleBinaryMath($2.loc, "||", EOpLogicalOr, $1, $3);
+ if ($$ == 0)
+ $$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
+ }
+ ;
+
+conditional_expression
+ : logical_or_expression { $$ = $1; }
+ | logical_or_expression QUESTION {
+ ++parseContext.controlFlowNestingLevel;
+ }
+ expression COLON assignment_expression {
+ --parseContext.controlFlowNestingLevel;
+ parseContext.boolCheck($2.loc, $1);
+ parseContext.rValueErrorCheck($2.loc, "?", $1);
+ parseContext.rValueErrorCheck($5.loc, ":", $4);
+ parseContext.rValueErrorCheck($5.loc, ":", $6);
+ $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString());
+ $$ = $6;
+ }
+ }
+ ;
+
+assignment_expression
+ : conditional_expression { $$ = $1; }
+ | unary_expression assignment_operator assignment_expression {
+ parseContext.arrayObjectCheck($2.loc, $1->getType(), "array assignment");
+ parseContext.opaqueCheck($2.loc, $1->getType(), "=");
+ parseContext.specializationCheck($2.loc, $1->getType(), "=");
+ parseContext.lValueErrorCheck($2.loc, "assign", $1);
+ parseContext.rValueErrorCheck($2.loc, "assign", $3);
+ $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc);
+ if ($$ == 0) {
+ parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
+ $$ = $1;
+ }
+ }
+ ;
+
+assignment_operator
+ : EQUAL {
+ $$.loc = $1.loc;
+ $$.op = EOpAssign;
+ }
+ | MUL_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpMulAssign;
+ }
+ | DIV_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpDivAssign;
+ }
+ | MOD_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "%=");
+ $$.loc = $1.loc;
+ $$.op = EOpModAssign;
+ }
+ | ADD_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpAddAssign;
+ }
+ | SUB_ASSIGN {
+ $$.loc = $1.loc;
+ $$.op = EOpSubAssign;
+ }
+ | LEFT_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bit-shift left assign");
+ $$.loc = $1.loc; $$.op = EOpLeftShiftAssign;
+ }
+ | RIGHT_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bit-shift right assign");
+ $$.loc = $1.loc; $$.op = EOpRightShiftAssign;
+ }
+ | AND_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bitwise-and assign");
+ $$.loc = $1.loc; $$.op = EOpAndAssign;
+ }
+ | XOR_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bitwise-xor assign");
+ $$.loc = $1.loc; $$.op = EOpExclusiveOrAssign;
+ }
+ | OR_ASSIGN {
+ parseContext.fullIntegerCheck($1.loc, "bitwise-or assign");
+ $$.loc = $1.loc; $$.op = EOpInclusiveOrAssign;
+ }
+ ;
+
+expression
+ : assignment_expression {
+ $$ = $1;
+ }
+ | expression COMMA assignment_expression {
+ $$ = parseContext.intermediate.addComma($1, $3, $2.loc);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString());
+ $$ = $3;
+ }
+ }
+ ;
+
+constant_expression
+ : conditional_expression {
+ parseContext.constantValueCheck($1, "");
+ $$ = $1;
+ }
+ ;
+
+declaration
+ : function_prototype SEMICOLON {
+ parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */);
+ $$ = 0;
+ // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
+ }
+ | init_declarator_list SEMICOLON {
+ if ($1.intermNode && $1.intermNode->getAsAggregate())
+ $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
+ $$ = $1.intermNode;
+ }
+ | PRECISION precision_qualifier type_specifier SEMICOLON {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "precision statement");
+
+ // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope
+ parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]);
+ parseContext.setDefaultPrecision($1.loc, $3, $2.qualifier.precision);
+ $$ = 0;
+ }
+ | block_structure SEMICOLON {
+ parseContext.declareBlock($1.loc, *$1.typeList);
+ $$ = 0;
+ }
+ | block_structure IDENTIFIER SEMICOLON {
+ parseContext.declareBlock($1.loc, *$1.typeList, $2.string);
+ $$ = 0;
+ }
+ | block_structure IDENTIFIER array_specifier SEMICOLON {
+ parseContext.declareBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes);
+ $$ = 0;
+ }
+ | type_qualifier SEMICOLON {
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ parseContext.updateStandaloneQualifierDefaults($1.loc, $1);
+ $$ = 0;
+ }
+ | type_qualifier IDENTIFIER SEMICOLON {
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string);
+ $$ = 0;
+ }
+ | type_qualifier IDENTIFIER identifier_list SEMICOLON {
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ $3->push_back($2.string);
+ parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3);
+ $$ = 0;
+ }
+ ;
+
+block_structure
+ : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
+ --parseContext.structNestingLevel;
+ parseContext.blockName = $2.string;
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.currentBlockQualifier = $1.qualifier;
+ $$.loc = $1.loc;
+ $$.typeList = $5;
+ }
+
+identifier_list
+ : COMMA IDENTIFIER {
+ $$ = new TIdentifierList;
+ $$->push_back($2.string);
+ }
+ | identifier_list COMMA IDENTIFIER {
+ $$ = $1;
+ $$->push_back($3.string);
+ }
+ ;
+
+function_prototype
+ : function_declarator RIGHT_PAREN {
+ $$.function = $1;
+ $$.loc = $2.loc;
+ }
+ ;
+
+function_declarator
+ : function_header {
+ $$ = $1;
+ }
+ | function_header_with_parameters {
+ $$ = $1;
+ }
+ ;
+
+
+function_header_with_parameters
+ : function_header parameter_declaration {
+ // Add the parameter
+ $$ = $1;
+ if ($2.param.type->getBasicType() != EbtVoid)
+ $1->addParameter($2.param);
+ else
+ delete $2.param.type;
+ }
+ | function_header_with_parameters COMMA parameter_declaration {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ($3.param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ parseContext.error($2.loc, "cannot be an argument type except for '(void)'", "void", "");
+ delete $3.param.type;
+ } else {
+ // Add the parameter
+ $$ = $1;
+ $1->addParameter($3.param);
+ }
+ }
+ ;
+
+function_header
+ : fully_specified_type IDENTIFIER LEFT_PAREN {
+ if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) {
+ parseContext.error($2.loc, "no qualifiers allowed for function return",
+ GetStorageQualifierString($1.qualifier.storage), "");
+ }
+ if ($1.arraySizes)
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type($1);
+ function = new TFunction($2.string, type);
+ $$ = function;
+ }
+ ;
+
+parameter_declarator
+ // Type + name
+ : type_specifier IDENTIFIER {
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+ if ($1.basicType == EbtVoid) {
+ parseContext.error($2.loc, "illegal use of type 'void'", $2.string->c_str(), "");
+ }
+ parseContext.reservedErrorCheck($2.loc, *$2.string);
+
+ TParameter param = {$2.string, new TType($1)};
+ $$.loc = $2.loc;
+ $$.param = param;
+ }
+ | type_specifier IDENTIFIER array_specifier {
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+ parseContext.arrayDimCheck($2.loc, $1.arraySizes, $3.arraySizes);
+
+ parseContext.arraySizeRequiredCheck($3.loc, *$3.arraySizes);
+ parseContext.reservedErrorCheck($2.loc, *$2.string);
+
+ $1.arraySizes = $3.arraySizes;
+
+ TParameter param = { $2.string, new TType($1)};
+ $$.loc = $2.loc;
+ $$.param = param;
+ }
+ ;
+
+parameter_declaration
+ //
+ // With name
+ //
+ : type_qualifier parameter_declarator {
+ $$ = $2;
+ if ($1.qualifier.precision != EpqNone)
+ $$.param.type->getQualifier().precision = $1.qualifier.precision;
+ parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type);
+ parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type);
+
+ }
+ | parameter_declarator {
+ $$ = $1;
+
+ parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type);
+ parseContext.paramCheckFix($1.loc, EvqTemporary, *$$.param.type);
+ parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+ }
+ //
+ // Without name
+ //
+ | type_qualifier parameter_type_specifier {
+ $$ = $2;
+ if ($1.qualifier.precision != EpqNone)
+ $$.param.type->getQualifier().precision = $1.qualifier.precision;
+ parseContext.precisionQualifierCheck($1.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type);
+ parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type);
+ }
+ | parameter_type_specifier {
+ $$ = $1;
+
+ parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type);
+ parseContext.paramCheckFix($1.loc, EvqTemporary, *$$.param.type);
+ parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier());
+ }
+ ;
+
+parameter_type_specifier
+ : type_specifier {
+ TParameter param = { 0, new TType($1) };
+ $$.param = param;
+ if ($1.arraySizes)
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+ ;
+
+init_declarator_list
+ : single_declaration {
+ $$ = $1;
+ }
+ | init_declarator_list COMMA IDENTIFIER {
+ $$ = $1;
+ parseContext.declareVariable($3.loc, *$3.string, $1.type);
+ }
+ | init_declarator_list COMMA IDENTIFIER array_specifier {
+ $$ = $1;
+ parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes);
+ }
+ | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer {
+ $$.type = $1.type;
+ TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes, $6);
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $5.loc);
+ }
+ | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+ $$.type = $1.type;
+ TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, 0, $5);
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $4.loc);
+ }
+ ;
+
+single_declaration
+ : fully_specified_type {
+ $$.type = $1;
+ $$.intermNode = 0;
+ parseContext.declareTypeDefaults($$.loc, $$.type);
+ }
+ | fully_specified_type IDENTIFIER {
+ $$.type = $1;
+ $$.intermNode = 0;
+ parseContext.declareVariable($2.loc, *$2.string, $1);
+ }
+ | fully_specified_type IDENTIFIER array_specifier {
+ $$.type = $1;
+ $$.intermNode = 0;
+ parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes);
+ }
+ | fully_specified_type IDENTIFIER array_specifier EQUAL initializer {
+ $$.type = $1;
+ TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes, $5);
+ $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $4.loc);
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ $$.type = $1;
+ TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4);
+ $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $3.loc);
+ }
+
+// Grammar Note: No 'enum', or 'typedef'.
+
+fully_specified_type
+ : type_specifier {
+ $$ = $1;
+
+ parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $$);
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ }
+
+ parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier);
+ }
+ | type_qualifier type_specifier {
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2);
+
+ if ($2.arraySizes) {
+ parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
+ }
+
+ if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier))
+ $2.arraySizes = 0;
+
+ parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers);
+ $2.shaderQualifiers.merge($1.shaderQualifiers);
+ parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true);
+ parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier);
+
+ $$ = $2;
+
+ if (! $$.qualifier.isInterpolation() &&
+ ((parseContext.language == EShLangVertex && $$.qualifier.storage == EvqVaryingOut) ||
+ (parseContext.language == EShLangFragment && $$.qualifier.storage == EvqVaryingIn)))
+ $$.qualifier.smooth = true;
+ }
+ ;
+
+invariant_qualifier
+ : INVARIANT {
+ parseContext.globalCheck($1.loc, "invariant");
+ parseContext.profileRequires($$.loc, ENoProfile, 120, 0, "invariant");
+ $$.init($1.loc);
+ $$.qualifier.invariant = true;
+ }
+ ;
+
+interpolation_qualifier
+ : SMOOTH {
+ parseContext.globalCheck($1.loc, "smooth");
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "smooth");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "smooth");
+ $$.init($1.loc);
+ $$.qualifier.smooth = true;
+ }
+ | FLAT {
+ parseContext.globalCheck($1.loc, "flat");
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "flat");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "flat");
+ $$.init($1.loc);
+ $$.qualifier.flat = true;
+ }
+ | NOPERSPECTIVE {
+ parseContext.globalCheck($1.loc, "noperspective");
+ parseContext.requireProfile($1.loc, ~EEsProfile, "noperspective");
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "noperspective");
+ $$.init($1.loc);
+ $$.qualifier.nopersp = true;
+ }
+ ;
+
+layout_qualifier
+ : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
+ $$ = $3;
+ }
+ ;
+
+layout_qualifier_id_list
+ : layout_qualifier_id {
+ $$ = $1;
+ }
+ | layout_qualifier_id_list COMMA layout_qualifier_id {
+ $$ = $1;
+ $$.shaderQualifiers.merge($3.shaderQualifiers);
+ parseContext.mergeObjectLayoutQualifiers($$.qualifier, $3.qualifier, false);
+ }
+
+layout_qualifier_id
+ : IDENTIFIER {
+ $$.init($1.loc);
+ parseContext.setLayoutQualifier($1.loc, $$, *$1.string);
+ }
+ | IDENTIFIER EQUAL constant_expression {
+ $$.init($1.loc);
+ parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3);
+ }
+ | SHARED { // because "shared" is both an identifier and a keyword
+ $$.init($1.loc);
+ TString strShared("shared");
+ parseContext.setLayoutQualifier($1.loc, $$, strShared);
+ }
+ ;
+
+precise_qualifier
+ : PRECISE {
+ parseContext.profileRequires($$.loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise");
+ parseContext.profileRequires($1.loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise");
+ $$.init($1.loc);
+ $$.qualifier.noContraction = true;
+ }
+ ;
+
+type_qualifier
+ : single_type_qualifier {
+ $$ = $1;
+ }
+ | type_qualifier single_type_qualifier {
+ $$ = $1;
+ if ($$.basicType == EbtVoid)
+ $$.basicType = $2.basicType;
+
+ $$.shaderQualifiers.merge($2.shaderQualifiers);
+ parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false);
+ }
+ ;
+
+single_type_qualifier
+ : storage_qualifier {
+ $$ = $1;
+ }
+ | layout_qualifier {
+ $$ = $1;
+ }
+ | precision_qualifier {
+ $$ = $1;
+ }
+ | interpolation_qualifier {
+ // allow inheritance of storage qualifier from block declaration
+ $$ = $1;
+ }
+ | invariant_qualifier {
+ // allow inheritance of storage qualifier from block declaration
+ $$ = $1;
+ }
+ | precise_qualifier {
+ // allow inheritance of storage qualifier from block declaration
+ $$ = $1;
+ }
+ ;
+
+storage_qualifier
+ : CONST {
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant
+ }
+ | ATTRIBUTE {
+ parseContext.requireStage($1.loc, EShLangVertex, "attribute");
+ parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "attribute");
+ parseContext.checkDeprecated($1.loc, ENoProfile, 130, "attribute");
+ parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "attribute");
+ parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "attribute");
+
+ parseContext.globalCheck($1.loc, "attribute");
+
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqVaryingIn;
+ }
+ | VARYING {
+ parseContext.checkDeprecated($1.loc, ENoProfile, 130, "varying");
+ parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "varying");
+ parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "varying");
+ parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "varying");
+
+ parseContext.globalCheck($1.loc, "varying");
+
+ $$.init($1.loc);
+ if (parseContext.language == EShLangVertex)
+ $$.qualifier.storage = EvqVaryingOut;
+ else
+ $$.qualifier.storage = EvqVaryingIn;
+ }
+ | INOUT {
+ parseContext.globalCheck($1.loc, "inout");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqInOut;
+ }
+ | IN {
+ parseContext.globalCheck($1.loc, "in");
+ $$.init($1.loc);
+ // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later
+ $$.qualifier.storage = EvqIn;
+ }
+ | OUT {
+ parseContext.globalCheck($1.loc, "out");
+ $$.init($1.loc);
+ // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later
+ $$.qualifier.storage = EvqOut;
+ }
+ | CENTROID {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, 0, "centroid");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "centroid");
+ parseContext.globalCheck($1.loc, "centroid");
+ $$.init($1.loc);
+ $$.qualifier.centroid = true;
+ }
+ | PATCH {
+ parseContext.globalCheck($1.loc, "patch");
+ parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch");
+ $$.init($1.loc);
+ $$.qualifier.patch = true;
+ }
+ | SAMPLE {
+ parseContext.globalCheck($1.loc, "sample");
+ $$.init($1.loc);
+ $$.qualifier.sample = true;
+ }
+ | UNIFORM {
+ parseContext.globalCheck($1.loc, "uniform");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqUniform;
+ }
+ | BUFFER {
+ parseContext.globalCheck($1.loc, "buffer");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqBuffer;
+ }
+ | SHARED {
+ parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared");
+ parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared");
+ parseContext.requireStage($1.loc, EShLangCompute, "shared");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqShared;
+ }
+ | COHERENT {
+ $$.init($1.loc);
+ $$.qualifier.coherent = true;
+ }
+ | VOLATILE {
+ $$.init($1.loc);
+ $$.qualifier.volatil = true;
+ }
+ | RESTRICT {
+ $$.init($1.loc);
+ $$.qualifier.restrict = true;
+ }
+ | READONLY {
+ $$.init($1.loc);
+ $$.qualifier.readonly = true;
+ }
+ | WRITEONLY {
+ $$.init($1.loc);
+ $$.qualifier.writeonly = true;
+ }
+ | SUBROUTINE {
+ parseContext.spvRemoved($1.loc, "subroutine");
+ parseContext.globalCheck($1.loc, "subroutine");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqUniform;
+ }
+ | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN {
+ parseContext.spvRemoved($1.loc, "subroutine");
+ parseContext.globalCheck($1.loc, "subroutine");
+ $$.init($1.loc);
+ $$.qualifier.storage = EvqUniform;
+ // TODO: 4.0 semantics: subroutines
+ // 1) make sure each identifier is a type declared earlier with SUBROUTINE
+ // 2) save all of the identifiers for future comparison with the declared function
+ }
+ ;
+
+type_name_list
+ : TYPE_NAME {
+ // TODO: 4.0 functionality: subroutine type to list
+ }
+ | type_name_list COMMA TYPE_NAME {
+ }
+ ;
+
+type_specifier
+ : type_specifier_nonarray {
+ $$ = $1;
+ $$.qualifier.precision = parseContext.getDefaultPrecision($$);
+ }
+ | type_specifier_nonarray array_specifier {
+ parseContext.arrayDimCheck($2.loc, $2.arraySizes, 0);
+ $$ = $1;
+ $$.qualifier.precision = parseContext.getDefaultPrecision($$);
+ $$.arraySizes = $2.arraySizes;
+ }
+ ;
+
+array_specifier
+ : LEFT_BRACKET RIGHT_BRACKET {
+ $$.loc = $1.loc;
+ $$.arraySizes = new TArraySizes;
+ $$.arraySizes->addInnerSize();
+ }
+ | LEFT_BRACKET conditional_expression RIGHT_BRACKET {
+ $$.loc = $1.loc;
+ $$.arraySizes = new TArraySizes;
+
+ TArraySize size;
+ parseContext.arraySizeCheck($2->getLoc(), $2, size);
+ $$.arraySizes->addInnerSize(size);
+ }
+ | array_specifier LEFT_BRACKET RIGHT_BRACKET {
+ $$ = $1;
+ $$.arraySizes->addInnerSize();
+ }
+ | array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET {
+ $$ = $1;
+
+ TArraySize size;
+ parseContext.arraySizeCheck($3->getLoc(), $3, size);
+ $$.arraySizes->addInnerSize(size);
+ }
+ ;
+
+type_specifier_nonarray
+ : VOID {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtVoid;
+ }
+ | FLOAT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ }
+ | DOUBLE {
+ parseContext.doubleCheck($1.loc, "double");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ }
+ | INT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ }
+ | UINT {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ }
+ | INT64_T {
+ parseContext.int64Check($1.loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ }
+ | UINT64_T {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ }
+ | BOOL {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ }
+ | VEC2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(2);
+ }
+ | VEC3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(3);
+ }
+ | VEC4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setVector(4);
+ }
+ | DVEC2 {
+ parseContext.doubleCheck($1.loc, "double vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(2);
+ }
+ | DVEC3 {
+ parseContext.doubleCheck($1.loc, "double vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(3);
+ }
+ | DVEC4 {
+ parseContext.doubleCheck($1.loc, "double vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setVector(4);
+ }
+ | BVEC2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ $$.setVector(2);
+ }
+ | BVEC3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ $$.setVector(3);
+ }
+ | BVEC4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtBool;
+ $$.setVector(4);
+ }
+ | IVEC2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(2);
+ }
+ | IVEC3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(3);
+ }
+ | IVEC4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt;
+ $$.setVector(4);
+ }
+ | I64VEC2 {
+ parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ $$.setVector(2);
+ }
+ | I64VEC3 {
+ parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ $$.setVector(3);
+ }
+ | I64VEC4 {
+ parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtInt64;
+ $$.setVector(4);
+ }
+ | UVEC2 {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(2);
+ }
+ | UVEC3 {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(3);
+ }
+ | UVEC4 {
+ parseContext.fullIntegerCheck($1.loc, "unsigned integer vector");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint;
+ $$.setVector(4);
+ }
+ | U64VEC2 {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ $$.setVector(2);
+ }
+ | U64VEC3 {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ $$.setVector(3);
+ }
+ | U64VEC4 {
+ parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtUint64;
+ $$.setVector(4);
+ }
+ | MAT2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 2);
+ }
+ | MAT3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 3);
+ }
+ | MAT4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 4);
+ }
+ | MAT2X2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 2);
+ }
+ | MAT2X3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 3);
+ }
+ | MAT2X4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(2, 4);
+ }
+ | MAT3X2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 2);
+ }
+ | MAT3X3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 3);
+ }
+ | MAT3X4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(3, 4);
+ }
+ | MAT4X2 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 2);
+ }
+ | MAT4X3 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 3);
+ }
+ | MAT4X4 {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtFloat;
+ $$.setMatrix(4, 4);
+ }
+ | DMAT2 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 2);
+ }
+ | DMAT3 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 3);
+ }
+ | DMAT4 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 4);
+ }
+ | DMAT2X2 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 2);
+ }
+ | DMAT2X3 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 3);
+ }
+ | DMAT2X4 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(2, 4);
+ }
+ | DMAT3X2 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 2);
+ }
+ | DMAT3X3 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 3);
+ }
+ | DMAT3X4 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(3, 4);
+ }
+ | DMAT4X2 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 2);
+ }
+ | DMAT4X3 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 3);
+ }
+ | DMAT4X4 {
+ parseContext.doubleCheck($1.loc, "double matrix");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtDouble;
+ $$.setMatrix(4, 4);
+ }
+ | ATOMIC_UINT {
+ parseContext.vulkanRemoved($1.loc, "atomic counter types");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtAtomicUint;
+ }
+ | SAMPLER1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D);
+ }
+ | SAMPLER2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D);
+ }
+ | SAMPLER3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd3D);
+ }
+ | SAMPLERCUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube);
+ }
+ | SAMPLER1DSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D, false, true);
+ }
+ | SAMPLER2DSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, false, true);
+ }
+ | SAMPLERCUBESHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube, false, true);
+ }
+ | SAMPLER1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D, true);
+ }
+ | SAMPLER2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, true);
+ }
+ | SAMPLER1DARRAYSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd1D, true, true);
+ }
+ | SAMPLER2DARRAYSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, true, true);
+ }
+ | SAMPLERCUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube, true);
+ }
+ | SAMPLERCUBEARRAYSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdCube, true, true);
+ }
+ | ISAMPLER1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd1D);
+ }
+ | ISAMPLER2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D);
+ }
+ | ISAMPLER3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd3D);
+ }
+ | ISAMPLERCUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdCube);
+ }
+ | ISAMPLER1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd1D, true);
+ }
+ | ISAMPLER2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D, true);
+ }
+ | ISAMPLERCUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdCube, true);
+ }
+ | USAMPLER1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd1D);
+ }
+ | USAMPLER2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D);
+ }
+ | USAMPLER3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd3D);
+ }
+ | USAMPLERCUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdCube);
+ }
+ | USAMPLER1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd1D, true);
+ }
+ | USAMPLER2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D, true);
+ }
+ | USAMPLERCUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdCube, true);
+ }
+ | SAMPLER2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdRect);
+ }
+ | SAMPLER2DRECTSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdRect, false, true);
+ }
+ | ISAMPLER2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdRect);
+ }
+ | USAMPLER2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdRect);
+ }
+ | SAMPLERBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, EsdBuffer);
+ }
+ | ISAMPLERBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, EsdBuffer);
+ }
+ | USAMPLERBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, EsdBuffer);
+ }
+ | SAMPLER2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, false, false, true);
+ }
+ | ISAMPLER2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D, false, false, true);
+ }
+ | USAMPLER2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D, false, false, true);
+ }
+ | SAMPLER2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D, true, false, true);
+ }
+ | ISAMPLER2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtInt, Esd2D, true, false, true);
+ }
+ | USAMPLER2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtUint, Esd2D, true, false, true);
+ }
+ | SAMPLER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setPureSampler(false);
+ }
+ | SAMPLERSHADOW {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setPureSampler(true);
+ }
+ | TEXTURE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd1D);
+ }
+ | TEXTURE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D);
+ }
+ | TEXTURE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd3D);
+ }
+ | TEXTURECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdCube);
+ }
+ | TEXTURE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd1D, true);
+ }
+ | TEXTURE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D, true);
+ }
+ | TEXTURECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdCube, true);
+ }
+ | ITEXTURE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd1D);
+ }
+ | ITEXTURE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D);
+ }
+ | ITEXTURE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd3D);
+ }
+ | ITEXTURECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdCube);
+ }
+ | ITEXTURE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd1D, true);
+ }
+ | ITEXTURE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D, true);
+ }
+ | ITEXTURECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdCube, true);
+ }
+ | UTEXTURE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd1D);
+ }
+ | UTEXTURE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D);
+ }
+ | UTEXTURE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd3D);
+ }
+ | UTEXTURECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdCube);
+ }
+ | UTEXTURE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd1D, true);
+ }
+ | UTEXTURE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D, true);
+ }
+ | UTEXTURECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdCube, true);
+ }
+ | TEXTURE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdRect);
+ }
+ | ITEXTURE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdRect);
+ }
+ | UTEXTURE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdRect);
+ }
+ | TEXTUREBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, EsdBuffer);
+ }
+ | ITEXTUREBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, EsdBuffer);
+ }
+ | UTEXTUREBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, EsdBuffer);
+ }
+ | TEXTURE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D, false, false, true);
+ }
+ | ITEXTURE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D, false, false, true);
+ }
+ | UTEXTURE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D, false, false, true);
+ }
+ | TEXTURE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtFloat, Esd2D, true, false, true);
+ }
+ | ITEXTURE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtInt, Esd2D, true, false, true);
+ }
+ | UTEXTURE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setTexture(EbtUint, Esd2D, true, false, true);
+ }
+ | IMAGE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd1D);
+ }
+ | IIMAGE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd1D);
+ }
+ | UIMAGE1D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd1D);
+ }
+ | IMAGE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D);
+ }
+ | IIMAGE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D);
+ }
+ | UIMAGE2D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D);
+ }
+ | IMAGE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd3D);
+ }
+ | IIMAGE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd3D);
+ }
+ | UIMAGE3D {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd3D);
+ }
+ | IMAGE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdRect);
+ }
+ | IIMAGE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdRect);
+ }
+ | UIMAGE2DRECT {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdRect);
+ }
+ | IMAGECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdCube);
+ }
+ | IIMAGECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdCube);
+ }
+ | UIMAGECUBE {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdCube);
+ }
+ | IMAGEBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdBuffer);
+ }
+ | IIMAGEBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdBuffer);
+ }
+ | UIMAGEBUFFER {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdBuffer);
+ }
+ | IMAGE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd1D, true);
+ }
+ | IIMAGE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd1D, true);
+ }
+ | UIMAGE1DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd1D, true);
+ }
+ | IMAGE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D, true);
+ }
+ | IIMAGE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D, true);
+ }
+ | UIMAGE2DARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D, true);
+ }
+ | IMAGECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, EsdCube, true);
+ }
+ | IIMAGECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, EsdCube, true);
+ }
+ | UIMAGECUBEARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, EsdCube, true);
+ }
+ | IMAGE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D, false, false, true);
+ }
+ | IIMAGE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D, false, false, true);
+ }
+ | UIMAGE2DMS {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D, false, false, true);
+ }
+ | IMAGE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtFloat, Esd2D, true, false, true);
+ }
+ | IIMAGE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtInt, Esd2D, true, false, true);
+ }
+ | UIMAGE2DMSARRAY {
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setImage(EbtUint, Esd2D, true, false, true);
+ }
+ | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.set(EbtFloat, Esd2D);
+ $$.sampler.external = true;
+ }
+ | SUBPASSINPUT {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtFloat);
+ }
+ | SUBPASSINPUTMS {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtFloat, true);
+ }
+ | ISUBPASSINPUT {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtInt);
+ }
+ | ISUBPASSINPUTMS {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtInt, true);
+ }
+ | USUBPASSINPUT {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtUint);
+ }
+ | USUBPASSINPUTMS {
+ parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtSampler;
+ $$.sampler.setSubpass(EbtUint, true);
+ }
+ | struct_specifier {
+ $$ = $1;
+ $$.qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ parseContext.structTypeCheck($$.loc, $$);
+ }
+ | TYPE_NAME {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ if (const TVariable* variable = ($1.symbol)->getAsVariable()) {
+ const TType& structure = variable->getType();
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ $$.basicType = EbtStruct;
+ $$.userDef = &structure;
+ } else
+ parseContext.error($1.loc, "expected type name", $1.string->c_str(), "");
+ }
+ ;
+
+precision_qualifier
+ : HIGH_PRECISION {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ if (parseContext.profile == EEsProfile)
+ $$.qualifier.precision = EpqHigh;
+ }
+ | MEDIUM_PRECISION {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ if (parseContext.profile == EEsProfile)
+ $$.qualifier.precision = EpqMedium;
+ }
+ | LOW_PRECISION {
+ parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier");
+ $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+ if (parseContext.profile == EEsProfile)
+ $$.qualifier.precision = EpqLow;
+ }
+ ;
+
+struct_specifier
+ : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($5, *$2.string);
+ parseContext.structArrayCheck($2.loc, *structure);
+ TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+ if (! parseContext.symbolTable.insert(*userTypeDef))
+ parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");
+ $$.init($1.loc);
+ $$.basicType = EbtStruct;
+ $$.userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+ | STRUCT LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($4, TString(""));
+ $$.init($1.loc);
+ $$.basicType = EbtStruct;
+ $$.userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+ ;
+
+struct_declaration_list
+ : struct_declaration {
+ $$ = $1;
+ }
+ | struct_declaration_list struct_declaration {
+ $$ = $1;
+ for (unsigned int i = 0; i < $2->size(); ++i) {
+ for (unsigned int j = 0; j < $$->size(); ++j) {
+ if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName())
+ parseContext.error((*$2)[i].loc, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
+ }
+ $$->push_back((*$2)[i]);
+ }
+ }
+ ;
+
+struct_declaration
+ : type_specifier struct_declarator_list SEMICOLON {
+ if ($1.arraySizes) {
+ parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.profile == EEsProfile)
+ parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes);
+ }
+
+ $$ = $2;
+
+ parseContext.voidErrorCheck($1.loc, (*$2)[0].type->getFieldName(), $1.basicType);
+ parseContext.precisionQualifierCheck($1.loc, $1.basicType, $1.qualifier);
+
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ parseContext.arrayDimCheck($1.loc, (*$$)[i].type, $1.arraySizes);
+ (*$$)[i].type->mergeType($1);
+ }
+ }
+ | type_qualifier type_specifier struct_declarator_list SEMICOLON {
+ parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
+ if ($2.arraySizes) {
+ parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.profile == EEsProfile)
+ parseContext.arraySizeRequiredCheck($2.loc, *$2.arraySizes);
+ }
+
+ $$ = $3;
+
+ parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
+ parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType);
+ parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true);
+ parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier);
+
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ parseContext.arrayDimCheck($1.loc, (*$$)[i].type, $2.arraySizes);
+ (*$$)[i].type->mergeType($2);
+ }
+ }
+ ;
+
+struct_declarator_list
+ : struct_declarator {
+ $$ = new TTypeList;
+ $$->push_back($1);
+ }
+ | struct_declarator_list COMMA struct_declarator {
+ $$->push_back($3);
+ }
+ ;
+
+struct_declarator
+ : IDENTIFIER {
+ $$.type = new TType(EbtVoid);
+ $$.loc = $1.loc;
+ $$.type->setFieldName(*$1.string);
+ }
+ | IDENTIFIER array_specifier {
+ parseContext.arrayDimCheck($1.loc, $2.arraySizes, 0);
+
+ $$.type = new TType(EbtVoid);
+ $$.loc = $1.loc;
+ $$.type->setFieldName(*$1.string);
+ $$.type->newArraySizes(*$2.arraySizes);
+ }
+ ;
+
+initializer
+ : assignment_expression {
+ $$ = $1;
+ }
+ | LEFT_BRACE initializer_list RIGHT_BRACE {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile($1.loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ $$ = $2;
+ }
+ | LEFT_BRACE initializer_list COMMA RIGHT_BRACE {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile($1.loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ $$ = $2;
+ }
+ ;
+
+initializer_list
+ : initializer {
+ $$ = parseContext.intermediate.growAggregate(0, $1, $1->getLoc());
+ }
+ | initializer_list COMMA initializer {
+ $$ = parseContext.intermediate.growAggregate($1, $3);
+ }
+ ;
+
+declaration_statement
+ : declaration { $$ = $1; }
+ ;
+
+statement
+ : compound_statement { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+// Grammar Note: labeled statements for switch statements only; 'goto' is not supported.
+
+simple_statement
+ : declaration_statement { $$ = $1; }
+ | expression_statement { $$ = $1; }
+ | selection_statement { $$ = $1; }
+ | switch_statement { $$ = $1; }
+ | case_label { $$ = $1; }
+ | iteration_statement { $$ = $1; }
+ | jump_statement { $$ = $1; }
+ ;
+
+compound_statement
+ : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+ | LEFT_BRACE {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ }
+ statement_list {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ }
+ RIGHT_BRACE {
+ if ($3 && $3->getAsAggregate())
+ $3->getAsAggregate()->setOperator(EOpSequence);
+ $$ = $3;
+ }
+ ;
+
+statement_no_new_scope
+ : compound_statement_no_new_scope { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+statement_scoped
+ : {
+ ++parseContext.controlFlowNestingLevel;
+ }
+ compound_statement {
+ --parseContext.controlFlowNestingLevel;
+ $$ = $2;
+ }
+ | {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ simple_statement {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ $$ = $2;
+ }
+
+compound_statement_no_new_scope
+ // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+ : LEFT_BRACE RIGHT_BRACE {
+ $$ = 0;
+ }
+ | LEFT_BRACE statement_list RIGHT_BRACE {
+ if ($2 && $2->getAsAggregate())
+ $2->getAsAggregate()->setOperator(EOpSequence);
+ $$ = $2;
+ }
+ ;
+
+statement_list
+ : statement {
+ $$ = parseContext.intermediate.makeAggregate($1);
+ if ($1 && $1->getAsBranchNode() && ($1->getAsBranchNode()->getFlowOp() == EOpCase ||
+ $1->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence(0, $1);
+ $$ = 0; // start a fresh subsequence for what's after this case
+ }
+ }
+ | statement_list statement {
+ if ($2 && $2->getAsBranchNode() && ($2->getAsBranchNode()->getFlowOp() == EOpCase ||
+ $2->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence($1 ? $1->getAsAggregate() : 0, $2);
+ $$ = 0; // start a fresh subsequence for what's after this case
+ } else
+ $$ = parseContext.intermediate.growAggregate($1, $2);
+ }
+ ;
+
+expression_statement
+ : SEMICOLON { $$ = 0; }
+ | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
+ ;
+
+selection_statement
+ : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+ parseContext.boolCheck($1.loc, $3);
+ $$ = parseContext.intermediate.addSelection($3, $5, $1.loc);
+ }
+ ;
+
+selection_rest_statement
+ : statement_scoped ELSE statement_scoped {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ | statement_scoped {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ ;
+
+condition
+ // In 1996 c++ draft, conditions can include single declarations
+ : expression {
+ $$ = $1;
+ parseContext.boolCheck($1->getLoc(), $1);
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ parseContext.boolCheck($2.loc, $1);
+
+ TType type($1);
+ TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4);
+ if (initNode)
+ $$ = initNode->getAsTyped();
+ else
+ $$ = 0;
+ }
+ ;
+
+switch_statement
+ : SWITCH LEFT_PAREN expression RIGHT_PAREN {
+ // start new switch sequence on the switch stack
+ ++parseContext.controlFlowNestingLevel;
+ ++parseContext.statementNestingLevel;
+ parseContext.switchSequenceStack.push_back(new TIntermSequence);
+ parseContext.switchLevel.push_back(parseContext.statementNestingLevel);
+ parseContext.symbolTable.push();
+ }
+ LEFT_BRACE switch_statement_list RIGHT_BRACE {
+ $$ = parseContext.addSwitch($1.loc, $3, $7 ? $7->getAsAggregate() : 0);
+ delete parseContext.switchSequenceStack.back();
+ parseContext.switchSequenceStack.pop_back();
+ parseContext.switchLevel.pop_back();
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ ;
+
+switch_statement_list
+ : /* nothing */ {
+ $$ = 0;
+ }
+ | statement_list {
+ $$ = $1;
+ }
+ ;
+
+case_label
+ : CASE expression COLON {
+ $$ = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error($1.loc, "cannot appear outside switch statement", "case", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error($1.loc, "cannot be nested inside control flow", "case", "");
+ else {
+ parseContext.constantValueCheck($2, "case");
+ parseContext.integerCheck($2, "case");
+ $$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc);
+ }
+ }
+ | DEFAULT COLON {
+ $$ = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error($1.loc, "cannot appear outside switch statement", "default", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error($1.loc, "cannot be nested inside control flow", "default", "");
+ else
+ $$ = parseContext.intermediate.addBranch(EOpDefault, $1.loc);
+ }
+ ;
+
+iteration_statement
+ : WHILE LEFT_PAREN {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error($1.loc, "while loops not available", "limitation", "");
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ condition RIGHT_PAREN statement_no_new_scope {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ | DO {
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error($1.loc, "do-while loops not available", "limitation", "");
+
+ parseContext.boolCheck($8.loc, $6);
+
+ $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ | FOR LEFT_PAREN {
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+ for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ $$ = parseContext.intermediate.makeAggregate($4, $2.loc);
+ TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc);
+ if (! parseContext.limits.nonInductiveForLoops)
+ parseContext.inductiveLoopCheck($1.loc, $4, forLoop);
+ $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
+ $$->getAsAggregate()->setOperator(EOpSequence);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+ ;
+
+for_init_statement
+ : expression_statement {
+ $$ = $1;
+ }
+ | declaration_statement {
+ $$ = $1;
+ }
+ ;
+
+conditionopt
+ : condition {
+ $$ = $1;
+ }
+ | /* May be null */ {
+ $$ = 0;
+ }
+ ;
+
+for_rest_statement
+ : conditionopt SEMICOLON {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ | conditionopt SEMICOLON expression {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ ;
+
+jump_statement
+ : CONTINUE SEMICOLON {
+ if (parseContext.loopNestingLevel <= 0)
+ parseContext.error($1.loc, "continue statement only allowed in loops", "", "");
+ $$ = parseContext.intermediate.addBranch(EOpContinue, $1.loc);
+ }
+ | BREAK SEMICOLON {
+ if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
+ parseContext.error($1.loc, "break statement only allowed in switch and loops", "", "");
+ $$ = parseContext.intermediate.addBranch(EOpBreak, $1.loc);
+ }
+ | RETURN SEMICOLON {
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $1.loc);
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
+ parseContext.error($1.loc, "non-void function must return a value", "return", "");
+ if (parseContext.inMain)
+ parseContext.postMainReturn = true;
+ }
+ | RETURN expression SEMICOLON {
+ parseContext.functionReturnsValue = true;
+ if (parseContext.currentFunctionType->getBasicType() == EbtVoid) {
+ parseContext.error($1.loc, "void function cannot return a value", "return", "");
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $1.loc);
+ } else if (*(parseContext.currentFunctionType) != $2->getType()) {
+ TIntermTyped* converted = parseContext.intermediate.addConversion(EOpReturn, *parseContext.currentFunctionType, $2);
+ if (converted) {
+ if (parseContext.version < 420)
+ parseContext.warn($1.loc, "type conversion on return values was not explicitly allowed until version 420", "return", "");
+ $$ = parseContext.intermediate.addBranch(EOpReturn, converted, $1.loc);
+ } else {
+ parseContext.error($1.loc, "type does not match, or is not convertible to, the function's return type", "return", "");
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.loc);
+ }
+ } else
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.loc);
+ }
+ | DISCARD SEMICOLON {
+ parseContext.requireStage($1.loc, EShLangFragment, "discard");
+ $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc);
+ }
+ ;
+
+// Grammar Note: No 'goto'. Gotos are not supported.
+
+translation_unit
+ : external_declaration {
+ $$ = $1;
+ parseContext.intermediate.setTreeRoot($$);
+ }
+ | translation_unit external_declaration {
+ $$ = parseContext.intermediate.growAggregate($1, $2);
+ parseContext.intermediate.setTreeRoot($$);
+ }
+ ;
+
+external_declaration
+ : function_definition {
+ $$ = $1;
+ }
+ | declaration {
+ $$ = $1;
+ }
+ ;
+
+function_definition
+ : function_prototype {
+ $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */);
+ $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function);
+ }
+ compound_statement_no_new_scope {
+ // May be best done as post process phase on intermediate code
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
+ parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str());
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ $$ = parseContext.intermediate.growAggregate($1.intermNode, $3);
+ parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc);
+ $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
+ $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+ $$->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable);
+ }
+ ;
+
+%%
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp
new file mode 100644
index 00000000000..a284fda43f7
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp
@@ -0,0 +1,7685 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 41 "MachineIndependent/glslang.y" /* yacc.c:339 */
+
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../Public/ShaderLang.h"
+
+using namespace glslang;
+
+
+#line 91 "MachineIndependent/glslang_tab.cpp" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "glslang_tab.cpp.h". */
+#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ ATTRIBUTE = 258,
+ VARYING = 259,
+ CONST = 260,
+ BOOL = 261,
+ FLOAT = 262,
+ DOUBLE = 263,
+ INT = 264,
+ UINT = 265,
+ INT64_T = 266,
+ UINT64_T = 267,
+ BREAK = 268,
+ CONTINUE = 269,
+ DO = 270,
+ ELSE = 271,
+ FOR = 272,
+ IF = 273,
+ DISCARD = 274,
+ RETURN = 275,
+ SWITCH = 276,
+ CASE = 277,
+ DEFAULT = 278,
+ SUBROUTINE = 279,
+ BVEC2 = 280,
+ BVEC3 = 281,
+ BVEC4 = 282,
+ IVEC2 = 283,
+ IVEC3 = 284,
+ IVEC4 = 285,
+ I64VEC2 = 286,
+ I64VEC3 = 287,
+ I64VEC4 = 288,
+ UVEC2 = 289,
+ UVEC3 = 290,
+ UVEC4 = 291,
+ U64VEC2 = 292,
+ U64VEC3 = 293,
+ U64VEC4 = 294,
+ VEC2 = 295,
+ VEC3 = 296,
+ VEC4 = 297,
+ MAT2 = 298,
+ MAT3 = 299,
+ MAT4 = 300,
+ CENTROID = 301,
+ IN = 302,
+ OUT = 303,
+ INOUT = 304,
+ UNIFORM = 305,
+ PATCH = 306,
+ SAMPLE = 307,
+ BUFFER = 308,
+ SHARED = 309,
+ COHERENT = 310,
+ VOLATILE = 311,
+ RESTRICT = 312,
+ READONLY = 313,
+ WRITEONLY = 314,
+ DVEC2 = 315,
+ DVEC3 = 316,
+ DVEC4 = 317,
+ DMAT2 = 318,
+ DMAT3 = 319,
+ DMAT4 = 320,
+ NOPERSPECTIVE = 321,
+ FLAT = 322,
+ SMOOTH = 323,
+ LAYOUT = 324,
+ MAT2X2 = 325,
+ MAT2X3 = 326,
+ MAT2X4 = 327,
+ MAT3X2 = 328,
+ MAT3X3 = 329,
+ MAT3X4 = 330,
+ MAT4X2 = 331,
+ MAT4X3 = 332,
+ MAT4X4 = 333,
+ DMAT2X2 = 334,
+ DMAT2X3 = 335,
+ DMAT2X4 = 336,
+ DMAT3X2 = 337,
+ DMAT3X3 = 338,
+ DMAT3X4 = 339,
+ DMAT4X2 = 340,
+ DMAT4X3 = 341,
+ DMAT4X4 = 342,
+ ATOMIC_UINT = 343,
+ SAMPLER1D = 344,
+ SAMPLER2D = 345,
+ SAMPLER3D = 346,
+ SAMPLERCUBE = 347,
+ SAMPLER1DSHADOW = 348,
+ SAMPLER2DSHADOW = 349,
+ SAMPLERCUBESHADOW = 350,
+ SAMPLER1DARRAY = 351,
+ SAMPLER2DARRAY = 352,
+ SAMPLER1DARRAYSHADOW = 353,
+ SAMPLER2DARRAYSHADOW = 354,
+ ISAMPLER1D = 355,
+ ISAMPLER2D = 356,
+ ISAMPLER3D = 357,
+ ISAMPLERCUBE = 358,
+ ISAMPLER1DARRAY = 359,
+ ISAMPLER2DARRAY = 360,
+ USAMPLER1D = 361,
+ USAMPLER2D = 362,
+ USAMPLER3D = 363,
+ USAMPLERCUBE = 364,
+ USAMPLER1DARRAY = 365,
+ USAMPLER2DARRAY = 366,
+ SAMPLER2DRECT = 367,
+ SAMPLER2DRECTSHADOW = 368,
+ ISAMPLER2DRECT = 369,
+ USAMPLER2DRECT = 370,
+ SAMPLERBUFFER = 371,
+ ISAMPLERBUFFER = 372,
+ USAMPLERBUFFER = 373,
+ SAMPLERCUBEARRAY = 374,
+ SAMPLERCUBEARRAYSHADOW = 375,
+ ISAMPLERCUBEARRAY = 376,
+ USAMPLERCUBEARRAY = 377,
+ SAMPLER2DMS = 378,
+ ISAMPLER2DMS = 379,
+ USAMPLER2DMS = 380,
+ SAMPLER2DMSARRAY = 381,
+ ISAMPLER2DMSARRAY = 382,
+ USAMPLER2DMSARRAY = 383,
+ SAMPLEREXTERNALOES = 384,
+ SAMPLER = 385,
+ SAMPLERSHADOW = 386,
+ TEXTURE1D = 387,
+ TEXTURE2D = 388,
+ TEXTURE3D = 389,
+ TEXTURECUBE = 390,
+ TEXTURE1DARRAY = 391,
+ TEXTURE2DARRAY = 392,
+ ITEXTURE1D = 393,
+ ITEXTURE2D = 394,
+ ITEXTURE3D = 395,
+ ITEXTURECUBE = 396,
+ ITEXTURE1DARRAY = 397,
+ ITEXTURE2DARRAY = 398,
+ UTEXTURE1D = 399,
+ UTEXTURE2D = 400,
+ UTEXTURE3D = 401,
+ UTEXTURECUBE = 402,
+ UTEXTURE1DARRAY = 403,
+ UTEXTURE2DARRAY = 404,
+ TEXTURE2DRECT = 405,
+ ITEXTURE2DRECT = 406,
+ UTEXTURE2DRECT = 407,
+ TEXTUREBUFFER = 408,
+ ITEXTUREBUFFER = 409,
+ UTEXTUREBUFFER = 410,
+ TEXTURECUBEARRAY = 411,
+ ITEXTURECUBEARRAY = 412,
+ UTEXTURECUBEARRAY = 413,
+ TEXTURE2DMS = 414,
+ ITEXTURE2DMS = 415,
+ UTEXTURE2DMS = 416,
+ TEXTURE2DMSARRAY = 417,
+ ITEXTURE2DMSARRAY = 418,
+ UTEXTURE2DMSARRAY = 419,
+ SUBPASSINPUT = 420,
+ SUBPASSINPUTMS = 421,
+ ISUBPASSINPUT = 422,
+ ISUBPASSINPUTMS = 423,
+ USUBPASSINPUT = 424,
+ USUBPASSINPUTMS = 425,
+ IMAGE1D = 426,
+ IIMAGE1D = 427,
+ UIMAGE1D = 428,
+ IMAGE2D = 429,
+ IIMAGE2D = 430,
+ UIMAGE2D = 431,
+ IMAGE3D = 432,
+ IIMAGE3D = 433,
+ UIMAGE3D = 434,
+ IMAGE2DRECT = 435,
+ IIMAGE2DRECT = 436,
+ UIMAGE2DRECT = 437,
+ IMAGECUBE = 438,
+ IIMAGECUBE = 439,
+ UIMAGECUBE = 440,
+ IMAGEBUFFER = 441,
+ IIMAGEBUFFER = 442,
+ UIMAGEBUFFER = 443,
+ IMAGE1DARRAY = 444,
+ IIMAGE1DARRAY = 445,
+ UIMAGE1DARRAY = 446,
+ IMAGE2DARRAY = 447,
+ IIMAGE2DARRAY = 448,
+ UIMAGE2DARRAY = 449,
+ IMAGECUBEARRAY = 450,
+ IIMAGECUBEARRAY = 451,
+ UIMAGECUBEARRAY = 452,
+ IMAGE2DMS = 453,
+ IIMAGE2DMS = 454,
+ UIMAGE2DMS = 455,
+ IMAGE2DMSARRAY = 456,
+ IIMAGE2DMSARRAY = 457,
+ UIMAGE2DMSARRAY = 458,
+ STRUCT = 459,
+ VOID = 460,
+ WHILE = 461,
+ IDENTIFIER = 462,
+ TYPE_NAME = 463,
+ FLOATCONSTANT = 464,
+ DOUBLECONSTANT = 465,
+ INTCONSTANT = 466,
+ UINTCONSTANT = 467,
+ INT64CONSTANT = 468,
+ UINT64CONSTANT = 469,
+ BOOLCONSTANT = 470,
+ LEFT_OP = 471,
+ RIGHT_OP = 472,
+ INC_OP = 473,
+ DEC_OP = 474,
+ LE_OP = 475,
+ GE_OP = 476,
+ EQ_OP = 477,
+ NE_OP = 478,
+ AND_OP = 479,
+ OR_OP = 480,
+ XOR_OP = 481,
+ MUL_ASSIGN = 482,
+ DIV_ASSIGN = 483,
+ ADD_ASSIGN = 484,
+ MOD_ASSIGN = 485,
+ LEFT_ASSIGN = 486,
+ RIGHT_ASSIGN = 487,
+ AND_ASSIGN = 488,
+ XOR_ASSIGN = 489,
+ OR_ASSIGN = 490,
+ SUB_ASSIGN = 491,
+ LEFT_PAREN = 492,
+ RIGHT_PAREN = 493,
+ LEFT_BRACKET = 494,
+ RIGHT_BRACKET = 495,
+ LEFT_BRACE = 496,
+ RIGHT_BRACE = 497,
+ DOT = 498,
+ COMMA = 499,
+ COLON = 500,
+ EQUAL = 501,
+ SEMICOLON = 502,
+ BANG = 503,
+ DASH = 504,
+ TILDE = 505,
+ PLUS = 506,
+ STAR = 507,
+ SLASH = 508,
+ PERCENT = 509,
+ LEFT_ANGLE = 510,
+ RIGHT_ANGLE = 511,
+ VERTICAL_BAR = 512,
+ CARET = 513,
+ AMPERSAND = 514,
+ QUESTION = 515,
+ INVARIANT = 516,
+ PRECISE = 517,
+ HIGH_PRECISION = 518,
+ MEDIUM_PRECISION = 519,
+ LOW_PRECISION = 520,
+ PRECISION = 521,
+ PACKED = 522,
+ RESOURCE = 523,
+ SUPERP = 524
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 66 "MachineIndependent/glslang.y" /* yacc.c:355 */
+
+ struct {
+ glslang::TSourceLoc loc;
+ union {
+ glslang::TString *string;
+ int i;
+ unsigned int u;
+ long long i64;
+ unsigned long long u64;
+ bool b;
+ double d;
+ };
+ glslang::TSymbol* symbol;
+ } lex;
+ struct {
+ glslang::TSourceLoc loc;
+ glslang::TOperator op;
+ union {
+ TIntermNode* intermNode;
+ glslang::TIntermNodePair nodePair;
+ glslang::TIntermTyped* intermTypedNode;
+ };
+ union {
+ glslang::TPublicType type;
+ glslang::TFunction* function;
+ glslang::TParameter param;
+ glslang::TTypeLoc typeLine;
+ glslang::TTypeList* typeList;
+ glslang::TArraySizes* arraySizes;
+ glslang::TIdentifierList* identifierList;
+ };
+ } interm;
+
+#line 435 "MachineIndependent/glslang_tab.cpp" /* yacc.c:355 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int yyparse (glslang::TParseContext* pParseContext);
+
+#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
+
+/* Copy the second part of user declarations. */
+#line 100 "MachineIndependent/glslang.y" /* yacc.c:358 */
+
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4065)
+ #pragma warning(disable : 4127)
+ #pragma warning(disable : 4244)
+#endif
+
+#define parseContext (*pParseContext)
+#define yyerror(context, msg) context->parserError(msg)
+
+extern int yylex(YYSTYPE*, TParseContext&);
+
+
+#line 466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:358 */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 248
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 5943
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 270
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 100
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 421
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 553
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 524
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint16 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+ 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
+ 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
+ 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269
+};
+
+#if YYDEBUG
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 246, 246, 252, 255, 258, 262, 266, 270, 273,
+ 277, 280, 288, 291, 294, 297, 300, 305, 313, 320,
+ 327, 333, 337, 344, 347, 353, 360, 370, 378, 383,
+ 413, 419, 423, 427, 447, 448, 449, 450, 456, 457,
+ 462, 467, 476, 477, 482, 490, 491, 497, 506, 507,
+ 512, 517, 522, 530, 531, 539, 550, 551, 560, 561,
+ 570, 571, 580, 581, 589, 590, 598, 599, 607, 608,
+ 608, 626, 627, 642, 646, 650, 654, 659, 663, 667,
+ 671, 675, 679, 683, 690, 693, 703, 710, 715, 720,
+ 728, 732, 736, 740, 745, 750, 759, 759, 770, 774,
+ 781, 788, 791, 798, 806, 826, 844, 859, 882, 893,
+ 903, 913, 923, 932, 935, 939, 943, 948, 956, 961,
+ 966, 971, 976, 985, 996, 1023, 1032, 1039, 1046, 1056,
+ 1062, 1065, 1072, 1076, 1080, 1088, 1097, 1100, 1111, 1114,
+ 1117, 1120, 1124, 1128, 1135, 1139, 1151, 1165, 1170, 1176,
+ 1182, 1189, 1195, 1200, 1205, 1210, 1217, 1221, 1225, 1229,
+ 1233, 1237, 1243, 1255, 1258, 1263, 1267, 1276, 1281, 1289,
+ 1293, 1303, 1307, 1311, 1316, 1320, 1325, 1330, 1335, 1339,
+ 1344, 1349, 1354, 1360, 1366, 1372, 1377, 1382, 1387, 1392,
+ 1397, 1402, 1408, 1414, 1420, 1426, 1432, 1438, 1444, 1450,
+ 1456, 1461, 1466, 1471, 1476, 1481, 1486, 1491, 1496, 1501,
+ 1506, 1511, 1516, 1522, 1528, 1534, 1540, 1546, 1552, 1558,
+ 1564, 1570, 1576, 1582, 1588, 1593, 1598, 1603, 1608, 1613,
+ 1618, 1623, 1628, 1633, 1638, 1643, 1648, 1653, 1658, 1663,
+ 1668, 1673, 1678, 1683, 1688, 1693, 1698, 1703, 1708, 1713,
+ 1718, 1723, 1728, 1733, 1738, 1743, 1748, 1753, 1758, 1763,
+ 1768, 1773, 1778, 1783, 1788, 1793, 1798, 1803, 1808, 1813,
+ 1818, 1823, 1828, 1833, 1838, 1843, 1848, 1853, 1858, 1863,
+ 1868, 1873, 1878, 1883, 1888, 1893, 1898, 1903, 1908, 1913,
+ 1918, 1923, 1928, 1933, 1938, 1943, 1948, 1953, 1958, 1963,
+ 1968, 1973, 1978, 1983, 1988, 1993, 1998, 2003, 2008, 2013,
+ 2018, 2023, 2028, 2033, 2038, 2043, 2048, 2053, 2058, 2063,
+ 2068, 2073, 2078, 2083, 2088, 2093, 2098, 2103, 2108, 2113,
+ 2118, 2123, 2128, 2133, 2139, 2145, 2151, 2157, 2163, 2169,
+ 2175, 2180, 2196, 2202, 2208, 2217, 2217, 2228, 2228, 2238,
+ 2241, 2254, 2272, 2296, 2300, 2306, 2311, 2322, 2325, 2331,
+ 2340, 2343, 2349, 2353, 2354, 2360, 2361, 2362, 2363, 2364,
+ 2365, 2366, 2370, 2371, 2375, 2371, 2387, 2388, 2392, 2392,
+ 2399, 2399, 2413, 2416, 2424, 2432, 2443, 2444, 2448, 2455,
+ 2459, 2467, 2471, 2484, 2484, 2504, 2507, 2513, 2525, 2537,
+ 2537, 2552, 2552, 2568, 2568, 2589, 2592, 2598, 2601, 2607,
+ 2611, 2618, 2623, 2628, 2635, 2653, 2662, 2666, 2673, 2676,
+ 2682, 2682
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "ATTRIBUTE", "VARYING", "CONST", "BOOL",
+ "FLOAT", "DOUBLE", "INT", "UINT", "INT64_T", "UINT64_T", "BREAK",
+ "CONTINUE", "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "SWITCH",
+ "CASE", "DEFAULT", "SUBROUTINE", "BVEC2", "BVEC3", "BVEC4", "IVEC2",
+ "IVEC3", "IVEC4", "I64VEC2", "I64VEC3", "I64VEC4", "UVEC2", "UVEC3",
+ "UVEC4", "U64VEC2", "U64VEC3", "U64VEC4", "VEC2", "VEC3", "VEC4", "MAT2",
+ "MAT3", "MAT4", "CENTROID", "IN", "OUT", "INOUT", "UNIFORM", "PATCH",
+ "SAMPLE", "BUFFER", "SHARED", "COHERENT", "VOLATILE", "RESTRICT",
+ "READONLY", "WRITEONLY", "DVEC2", "DVEC3", "DVEC4", "DMAT2", "DMAT3",
+ "DMAT4", "NOPERSPECTIVE", "FLAT", "SMOOTH", "LAYOUT", "MAT2X2", "MAT2X3",
+ "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", "MAT4X2", "MAT4X3", "MAT4X4",
+ "DMAT2X2", "DMAT2X3", "DMAT2X4", "DMAT3X2", "DMAT3X3", "DMAT3X4",
+ "DMAT4X2", "DMAT4X3", "DMAT4X4", "ATOMIC_UINT", "SAMPLER1D", "SAMPLER2D",
+ "SAMPLER3D", "SAMPLERCUBE", "SAMPLER1DSHADOW", "SAMPLER2DSHADOW",
+ "SAMPLERCUBESHADOW", "SAMPLER1DARRAY", "SAMPLER2DARRAY",
+ "SAMPLER1DARRAYSHADOW", "SAMPLER2DARRAYSHADOW", "ISAMPLER1D",
+ "ISAMPLER2D", "ISAMPLER3D", "ISAMPLERCUBE", "ISAMPLER1DARRAY",
+ "ISAMPLER2DARRAY", "USAMPLER1D", "USAMPLER2D", "USAMPLER3D",
+ "USAMPLERCUBE", "USAMPLER1DARRAY", "USAMPLER2DARRAY", "SAMPLER2DRECT",
+ "SAMPLER2DRECTSHADOW", "ISAMPLER2DRECT", "USAMPLER2DRECT",
+ "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLERCUBEARRAY",
+ "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY",
+ "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY",
+ "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES",
+ "SAMPLER", "SAMPLERSHADOW", "TEXTURE1D", "TEXTURE2D", "TEXTURE3D",
+ "TEXTURECUBE", "TEXTURE1DARRAY", "TEXTURE2DARRAY", "ITEXTURE1D",
+ "ITEXTURE2D", "ITEXTURE3D", "ITEXTURECUBE", "ITEXTURE1DARRAY",
+ "ITEXTURE2DARRAY", "UTEXTURE1D", "UTEXTURE2D", "UTEXTURE3D",
+ "UTEXTURECUBE", "UTEXTURE1DARRAY", "UTEXTURE2DARRAY", "TEXTURE2DRECT",
+ "ITEXTURE2DRECT", "UTEXTURE2DRECT", "TEXTUREBUFFER", "ITEXTUREBUFFER",
+ "UTEXTUREBUFFER", "TEXTURECUBEARRAY", "ITEXTURECUBEARRAY",
+ "UTEXTURECUBEARRAY", "TEXTURE2DMS", "ITEXTURE2DMS", "UTEXTURE2DMS",
+ "TEXTURE2DMSARRAY", "ITEXTURE2DMSARRAY", "UTEXTURE2DMSARRAY",
+ "SUBPASSINPUT", "SUBPASSINPUTMS", "ISUBPASSINPUT", "ISUBPASSINPUTMS",
+ "USUBPASSINPUT", "USUBPASSINPUTMS", "IMAGE1D", "IIMAGE1D", "UIMAGE1D",
+ "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D", "IIMAGE3D", "UIMAGE3D",
+ "IMAGE2DRECT", "IIMAGE2DRECT", "UIMAGE2DRECT", "IMAGECUBE", "IIMAGECUBE",
+ "UIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER",
+ "IMAGE1DARRAY", "IIMAGE1DARRAY", "UIMAGE1DARRAY", "IMAGE2DARRAY",
+ "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBEARRAY", "IIMAGECUBEARRAY",
+ "UIMAGECUBEARRAY", "IMAGE2DMS", "IIMAGE2DMS", "UIMAGE2DMS",
+ "IMAGE2DMSARRAY", "IIMAGE2DMSARRAY", "UIMAGE2DMSARRAY", "STRUCT", "VOID",
+ "WHILE", "IDENTIFIER", "TYPE_NAME", "FLOATCONSTANT", "DOUBLECONSTANT",
+ "INTCONSTANT", "UINTCONSTANT", "INT64CONSTANT", "UINT64CONSTANT",
+ "BOOLCONSTANT", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP",
+ "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN",
+ "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN",
+ "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN",
+ "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE",
+ "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG",
+ "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE",
+ "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION",
+ "INVARIANT", "PRECISE", "HIGH_PRECISION", "MEDIUM_PRECISION",
+ "LOW_PRECISION", "PRECISION", "PACKED", "RESOURCE", "SUPERP", "$accept",
+ "variable_identifier", "primary_expression", "postfix_expression",
+ "integer_expression", "function_call", "function_call_or_method",
+ "function_call_generic", "function_call_header_no_parameters",
+ "function_call_header_with_parameters", "function_call_header",
+ "function_identifier", "unary_expression", "unary_operator",
+ "multiplicative_expression", "additive_expression", "shift_expression",
+ "relational_expression", "equality_expression", "and_expression",
+ "exclusive_or_expression", "inclusive_or_expression",
+ "logical_and_expression", "logical_xor_expression",
+ "logical_or_expression", "conditional_expression", "$@1",
+ "assignment_expression", "assignment_operator", "expression",
+ "constant_expression", "declaration", "block_structure", "$@2",
+ "identifier_list", "function_prototype", "function_declarator",
+ "function_header_with_parameters", "function_header",
+ "parameter_declarator", "parameter_declaration",
+ "parameter_type_specifier", "init_declarator_list", "single_declaration",
+ "fully_specified_type", "invariant_qualifier", "interpolation_qualifier",
+ "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id",
+ "precise_qualifier", "type_qualifier", "single_type_qualifier",
+ "storage_qualifier", "type_name_list", "type_specifier",
+ "array_specifier", "type_specifier_nonarray", "precision_qualifier",
+ "struct_specifier", "$@3", "$@4", "struct_declaration_list",
+ "struct_declaration", "struct_declarator_list", "struct_declarator",
+ "initializer", "initializer_list", "declaration_statement", "statement",
+ "simple_statement", "compound_statement", "$@5", "$@6",
+ "statement_no_new_scope", "statement_scoped", "$@7", "$@8",
+ "compound_statement_no_new_scope", "statement_list",
+ "expression_statement", "selection_statement",
+ "selection_rest_statement", "condition", "switch_statement", "$@9",
+ "switch_statement_list", "case_label", "iteration_statement", "$@10",
+ "$@11", "$@12", "for_init_statement", "conditionopt",
+ "for_rest_statement", "jump_statement", "translation_unit",
+ "external_declaration", "function_definition", "$@13", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
+ 415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
+ 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
+ 435, 436, 437, 438, 439, 440, 441, 442, 443, 444,
+ 445, 446, 447, 448, 449, 450, 451, 452, 453, 454,
+ 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 468, 469, 470, 471, 472, 473, 474,
+ 475, 476, 477, 478, 479, 480, 481, 482, 483, 484,
+ 485, 486, 487, 488, 489, 490, 491, 492, 493, 494,
+ 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
+ 505, 506, 507, 508, 509, 510, 511, 512, 513, 514,
+ 515, 516, 517, 518, 519, 520, 521, 522, 523, 524
+};
+# endif
+
+#define YYPACT_NINF -496
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-496)))
+
+#define YYTABLE_NINF -379
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
+{
+ 2394, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -199, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -187, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -180, -496, -496, -496, -496, -496, -496, -496, -134,
+ -496, -191, -181, -155, -131, 3871, -133, -496, -69, -496,
+ -496, -496, -496, 2900, -496, -496, -496, -92, -496, -496,
+ 546, -496, -496, -68, -45, -91, -496, 5735, -200, -496,
+ -496, -85, -496, 3871, -496, -496, -496, 3871, -50, -49,
+ -496, -209, -193, -496, -496, -496, 4323, -80, -496, -496,
+ -496, -202, -496, -86, -171, -496, -496, 3871, -84, -496,
+ -198, 810, -496, -496, -496, -496, -92, -214, -496, 4558,
+ -176, -496, -46, -496, -127, -496, -496, -496, -496, -496,
+ -496, -496, -496, 5271, 5271, 5271, -496, -496, -496, -496,
+ -496, -496, -496, -175, -496, -496, -496, -73, -169, 5503,
+ -71, -496, 5271, -118, -170, -195, -197, -90, -89, -87,
+ -88, -57, -58, -208, -67, -496, 4804, -496, -36, 5271,
+ -496, -45, 3871, 3871, -33, 3145, -496, -496, -496, -72,
+ -70, -496, -61, -59, -66, 5039, -55, 5271, -62, -51,
+ -54, -496, -496, -141, -496, -496, -125, -496, -181, -48,
+ -496, -496, -496, -496, 1074, -496, -496, -496, -496, -496,
+ -496, -80, 4558, -174, 4558, -496, -496, 4558, 3871, -496,
+ -23, -496, -496, -496, -167, -496, -496, 5271, -20, -496,
+ -496, 5271, -43, -496, -496, -496, 5271, 5271, 5271, 5271,
+ 5271, 5271, 5271, 5271, 5271, 5271, 5271, 5271, 5271, 5271,
+ 5271, 5271, 5271, 5271, 5271, -496, -496, -496, -44, -496,
+ -496, -496, -496, 3387, -33, -92, -121, -496, -496, -496,
+ -496, -496, 1338, -496, 5271, -496, -496, -120, 5271, -102,
+ -496, -496, -496, 1338, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, 5271, 5271, -496, -496, -496,
+ -496, 4558, -496, -105, -496, 3629, -496, -496, -42, -52,
+ -496, -496, -496, -496, -496, -118, -118, -170, -170, -195,
+ -195, -195, -195, -197, -197, -90, -89, -87, -88, -57,
+ -58, 5271, -496, -496, -119, -80, -33, -496, -16, 2130,
+ -164, -496, -160, -496, 2637, 1338, -496, -496, -496, -496,
+ 4077, -496, -496, -99, -496, -496, -40, -496, -496, 2637,
+ -41, -496, -52, -8, 3871, -35, -38, -496, -496, 5271,
+ 5271, -496, -39, -32, 191, -31, 1866, -496, -30, -34,
+ 1602, -496, -496, -138, 5271, 1602, -41, -496, -496, 1338,
+ 4558, -496, -496, -496, -29, -52, -496, -496, 1338, -27,
+ -496, -496, -496
+};
+
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 0, 145, 146, 144, 178, 172, 173, 174, 175, 176,
+ 177, 161, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 179, 180, 181,
+ 200, 201, 202, 150, 148, 149, 147, 153, 151, 152,
+ 154, 155, 156, 157, 158, 159, 160, 182, 183, 184,
+ 212, 213, 214, 128, 127, 126, 0, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 215, 216, 217, 218,
+ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 238, 239, 240,
+ 241, 242, 243, 245, 246, 247, 248, 249, 250, 252,
+ 253, 254, 255, 256, 257, 258, 236, 237, 244, 251,
+ 259, 260, 261, 262, 263, 264, 333, 265, 266, 267,
+ 268, 269, 270, 271, 272, 274, 275, 276, 277, 278,
+ 279, 281, 282, 283, 284, 285, 286, 288, 289, 290,
+ 291, 292, 293, 273, 280, 287, 294, 295, 296, 297,
+ 298, 299, 334, 335, 336, 337, 338, 339, 300, 301,
+ 302, 303, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, 318, 319, 320, 321,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 0, 171, 341, 125, 135, 342, 343, 344, 0,
+ 419, 0, 420, 0, 102, 101, 0, 113, 118, 142,
+ 141, 139, 143, 0, 136, 138, 123, 165, 140, 340,
+ 0, 416, 418, 0, 0, 0, 347, 0, 0, 90,
+ 87, 0, 100, 0, 109, 103, 111, 0, 112, 0,
+ 88, 119, 0, 93, 137, 124, 0, 166, 1, 417,
+ 163, 0, 134, 132, 0, 130, 345, 0, 0, 91,
+ 0, 0, 421, 104, 108, 110, 106, 114, 105, 0,
+ 120, 96, 0, 94, 0, 2, 8, 9, 4, 5,
+ 6, 7, 10, 0, 0, 0, 167, 36, 35, 37,
+ 34, 3, 12, 30, 14, 19, 20, 0, 0, 24,
+ 0, 38, 0, 42, 45, 48, 53, 56, 58, 60,
+ 62, 64, 66, 68, 0, 28, 0, 162, 0, 0,
+ 129, 0, 0, 0, 0, 0, 349, 89, 92, 0,
+ 0, 401, 0, 0, 0, 0, 0, 0, 0, 0,
+ 373, 382, 386, 38, 71, 84, 0, 362, 0, 123,
+ 365, 384, 364, 363, 0, 366, 367, 368, 369, 370,
+ 371, 107, 0, 115, 0, 357, 122, 0, 0, 98,
+ 0, 95, 31, 32, 0, 16, 17, 0, 0, 22,
+ 21, 0, 171, 25, 27, 33, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 69, 168, 169, 0, 164,
+ 86, 133, 131, 0, 0, 355, 0, 353, 348, 350,
+ 412, 411, 0, 403, 0, 415, 413, 0, 0, 0,
+ 398, 399, 372, 0, 74, 75, 77, 76, 79, 80,
+ 81, 82, 83, 78, 73, 0, 0, 387, 383, 385,
+ 117, 0, 360, 0, 121, 0, 99, 11, 0, 18,
+ 15, 26, 39, 40, 41, 44, 43, 46, 47, 51,
+ 52, 49, 50, 54, 55, 57, 59, 61, 63, 65,
+ 67, 0, 170, 346, 0, 356, 0, 351, 0, 0,
+ 0, 414, 0, 397, 0, 374, 72, 85, 116, 358,
+ 0, 97, 13, 0, 352, 354, 0, 406, 405, 408,
+ 380, 393, 391, 0, 0, 0, 0, 359, 361, 0,
+ 0, 407, 0, 0, 390, 0, 0, 388, 0, 0,
+ 0, 375, 70, 0, 409, 0, 380, 379, 381, 395,
+ 0, 377, 400, 376, 0, 410, 404, 389, 396, 0,
+ 392, 402, 394
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -496, -496, -496, -496, -496, -496, -496, -496, -496, -496,
+ -496, -496, -53, -496, -237, -288, -286, -243, -183, -179,
+ -184, -177, -168, -185, -496, -234, -496, -266, -496, -280,
+ -496, 4, -496, -496, -496, 6, -496, -496, -496, -15,
+ -10, -9, -496, -496, -475, -496, -496, -496, -496, -83,
+ -496, -204, -211, -496, -496, 0, -221, -496, 33, -496,
+ -496, -496, -308, -314, -178, -247, -349, -496, -248, -346,
+ -495, -283, -496, -496, -292, -291, -496, -496, 13, -423,
+ -242, -496, -496, -263, -496, -496, -496, -496, -496, -496,
+ -496, -496, -496, -496, -496, -496, -496, 28, -496, -496
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 291, 292, 293, 458, 294, 295, 296, 297, 298,
+ 299, 300, 343, 302, 303, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 344, 481, 345, 445, 346,
+ 411, 347, 201, 368, 274, 348, 203, 204, 205, 234,
+ 235, 236, 206, 207, 208, 209, 210, 211, 254, 255,
+ 212, 213, 214, 215, 251, 315, 247, 217, 218, 219,
+ 322, 257, 325, 326, 416, 417, 366, 453, 350, 351,
+ 352, 353, 433, 516, 542, 524, 525, 526, 543, 354,
+ 355, 356, 527, 515, 357, 528, 549, 358, 359, 494,
+ 422, 489, 509, 522, 523, 360, 220, 221, 222, 231
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
+{
+ 216, 237, 244, 365, 200, 374, 202, 260, 449, 252,
+ 495, 419, 314, 450, 413, 452, 228, 404, 454, 513,
+ 270, 391, 392, 393, 394, 246, 244, 225, 268, 237,
+ 246, 538, 362, 383, 513, 541, 317, 269, 223, 246,
+ 541, 316, 318, 375, 376, 361, 363, 259, 271, 328,
+ 224, 272, 405, 323, 273, 427, 229, 429, 395, 396,
+ 455, 226, -29, 316, 377, 316, 230, 320, 378, 380,
+ 367, 457, 451, 321, 510, 381, 488, 446, 511, 389,
+ 446, 390, 408, 232, 446, 410, 434, 435, 436, 437,
+ 438, 439, 440, 441, 442, 443, 365, 459, 365, 419,
+ 544, 365, 498, 467, 468, 444, 446, 469, 470, 471,
+ 472, 239, 244, 233, 240, 461, 548, 370, 323, 446,
+ 371, 323, 447, 486, 446, 486, 487, 491, 504, 196,
+ 197, 198, 397, 398, 386, 387, 388, 499, 241, 500,
+ 250, 419, 446, 493, 490, 446, 519, 246, 492, 449,
+ 256, 518, 465, 466, 473, 474, 261, 266, 267, 316,
+ 319, 369, 253, 327, 323, 379, 384, 402, 403, 401,
+ 399, 400, 409, 406, 415, 420, 423, 421, 424, 496,
+ 497, 425, 428, 430, 456, 365, 431, 460, 432, -28,
+ 506, 550, 446, 301, 485, -23, 482, 520, 502, 529,
+ -378, 503, 449, 530, 531, 238, 535, 536, 534, 323,
+ 340, 539, 540, 245, 512, 552, 475, 477, 551, 480,
+ 216, 476, 264, 263, 200, 478, 202, 258, 265, 512,
+ 372, 373, 227, 238, 365, 479, 484, 238, 412, 505,
+ 533, 507, 537, 546, 262, 547, 521, 508, 249, 385,
+ 0, 323, 0, 532, 545, 0, 0, 324, 0, 0,
+ 0, 349, 0, 301, 0, 0, 301, 0, 0, 0,
+ 0, 0, 0, 0, 365, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 514, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 244, 0, 514, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 324, 414, 0, 324, 0, 0, 0, 0,
+ 0, 0, 0, 462, 463, 464, 301, 301, 301, 301,
+ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301,
+ 301, 301, 0, 0, 349, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 324, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 324, 0, 0, 0, 0, 0, 0,
+ 0, 0, 349, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 349, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 324, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 349,
+ 0, 0, 0, 0, 349, 349, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 349,
+ 0, 0, 0, 0, 245, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 349, 0, 0, 0,
+ 349, 0, 0, 0, 0, 349, 0, 0, 0, 349,
+ 0, 0, 0, 0, 0, 0, 248, 0, 349, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+ 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 0, 0, 193, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 194, 195, 196,
+ 197, 198, 199, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 329, 330, 331, 0, 332, 333, 334,
+ 335, 336, 337, 338, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 339, 275, 193, 276,
+ 277, 278, 279, 280, 281, 282, 0, 0, 283, 284,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 285, 0, 0,
+ 0, 340, 341, 0, 0, 0, 0, 342, 287, 288,
+ 289, 290, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 194, 195, 196, 197, 198, 199, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 329, 330, 331,
+ 0, 332, 333, 334, 335, 336, 337, 338, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 339, 275, 193, 276, 277, 278, 279, 280, 281, 282,
+ 0, 0, 283, 284, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 285, 0, 0, 0, 340, 448, 0, 0, 0,
+ 0, 342, 287, 288, 289, 290, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 194, 195, 196, 197, 198,
+ 199, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 329, 330, 331, 0, 332, 333, 334, 335, 336,
+ 337, 338, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 339, 275, 193, 276, 277, 278,
+ 279, 280, 281, 282, 0, 0, 283, 284, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 285, 0, 0, 0, 340,
+ 0, 0, 0, 0, 0, 342, 287, 288, 289, 290,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 194,
+ 195, 196, 197, 198, 199, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 329, 330, 331, 0, 332,
+ 333, 334, 335, 336, 337, 338, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187, 188, 189, 190, 191, 192, 339, 275,
+ 193, 276, 277, 278, 279, 280, 281, 282, 0, 0,
+ 283, 284, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 285,
+ 0, 0, 0, 261, 0, 0, 0, 0, 0, 342,
+ 287, 288, 289, 290, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 194, 195, 196, 197, 198, 199, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 329,
+ 330, 331, 0, 332, 333, 334, 335, 336, 337, 338,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+ 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 339, 275, 193, 276, 277, 278, 279, 280,
+ 281, 282, 0, 0, 283, 284, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 285, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 342, 287, 288, 289, 290, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 194, 195, 196,
+ 197, 198, 199, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 0, 275, 193, 276,
+ 277, 278, 279, 280, 281, 282, 0, 0, 283, 284,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 285, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 342, 287, 288,
+ 289, 290, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 194, 195, 196, 197, 198, 199, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 0, 0, 193, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 0, 0, 0, 0, 0, 194, 195, 196, 197, 198,
+ 199, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 0, 275, 193, 276, 277, 278, 279,
+ 280, 281, 282, 0, 0, 283, 284, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 285, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 287, 288, 289, 290, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 194, 195,
+ 196, 197, 198, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 0, 242, 193, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 243, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 10, 0, 0,
+ 0, 194, 195, 196, 197, 198, 0, 0, 0, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 0, 0, 193, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 418, 0, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 0, 0, 0, 0, 0, 0, 194, 195, 196, 197,
+ 198, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 0, 0, 193, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 483,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 0, 0, 0, 0, 0, 0, 194, 195,
+ 196, 197, 198, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 0, 0, 193, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 501, 0, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 0, 0, 0, 0, 0, 0,
+ 194, 195, 196, 197, 198, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 0, 0, 193,
+ 0, 0, 0, 4, 5, 6, 7, 8, 9, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 194, 195, 196, 197, 198, 47, 48, 49,
+ 50, 51, 52, 0, 0, 0, 0, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 0, 275, 193, 276, 277, 278, 279,
+ 280, 281, 282, 0, 0, 283, 284, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 285, 0, 0, 0, 364, 517,
+ 0, 0, 0, 0, 0, 287, 288, 289, 290, 4,
+ 5, 6, 7, 8, 9, 10, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 47, 48, 49, 50, 51, 52, 0,
+ 0, 0, 0, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 0,
+ 275, 193, 276, 277, 278, 279, 280, 281, 282, 0,
+ 0, 283, 284, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 285, 0, 0, 286, 4, 5, 6, 7, 8, 9,
+ 10, 287, 288, 289, 290, 0, 0, 0, 0, 0,
+ 0, 0, 0, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 47, 48,
+ 49, 50, 51, 52, 0, 0, 0, 0, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 0, 275, 193, 276, 277, 278,
+ 279, 280, 281, 282, 0, 0, 283, 284, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 285, 0, 0, 0, 364,
+ 0, 0, 0, 0, 0, 0, 287, 288, 289, 290,
+ 4, 5, 6, 7, 8, 9, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 48, 49, 50, 51, 52,
+ 0, 0, 0, 0, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 0, 275, 193, 276, 277, 278, 279, 280, 281, 282,
+ 0, 0, 283, 284, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 285, 0, 0, 407, 4, 5, 6, 7, 8,
+ 9, 10, 287, 288, 289, 290, 0, 0, 0, 0,
+ 0, 0, 0, 0, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 47,
+ 48, 49, 50, 51, 52, 0, 0, 0, 0, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 0, 275, 193, 276, 277,
+ 278, 279, 280, 281, 282, 0, 0, 283, 284, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 285, 4, 5, 6,
+ 7, 8, 9, 10, 0, 0, 426, 287, 288, 289,
+ 290, 0, 0, 0, 0, 0, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 47, 48, 49, 50, 51, 52, 0, 0, 0,
+ 0, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 0, 275, 193,
+ 276, 277, 278, 279, 280, 281, 282, 0, 0, 283,
+ 284, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 285, 4,
+ 5, 6, 7, 8, 9, 10, 0, 0, 0, 287,
+ 288, 289, 290, 0, 0, 0, 0, 0, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 47, 48, 49, 50, 51, 52, 0,
+ 0, 0, 0, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 382, 0,
+ 275, 193, 276, 277, 278, 279, 280, 281, 282, 0,
+ 0, 283, 284, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 285, 4, 5, 6, 7, 8, 9, 10, 0, 0,
+ 0, 287, 288, 289, 290, 0, 0, 0, 0, 0,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 47, 48, 49, 50, 51,
+ 52, 0, 0, 0, 0, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 0, 0, 193
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 0, 205, 213, 269, 0, 285, 0, 228, 354, 54,
+ 433, 325, 246, 362, 322, 364, 207, 225, 367, 494,
+ 241, 216, 217, 220, 221, 239, 237, 207, 237, 233,
+ 239, 526, 246, 299, 509, 530, 238, 246, 237, 239,
+ 535, 239, 244, 218, 219, 266, 267, 247, 241, 247,
+ 237, 244, 260, 257, 247, 335, 247, 337, 255, 256,
+ 368, 241, 237, 239, 239, 239, 247, 238, 243, 238,
+ 246, 238, 246, 244, 238, 244, 422, 244, 238, 249,
+ 244, 251, 316, 238, 244, 319, 227, 228, 229, 230,
+ 231, 232, 233, 234, 235, 236, 362, 377, 364, 413,
+ 238, 367, 451, 391, 392, 246, 244, 393, 394, 395,
+ 396, 244, 323, 244, 247, 381, 539, 244, 322, 244,
+ 247, 325, 247, 244, 244, 244, 247, 247, 247, 263,
+ 264, 265, 222, 223, 252, 253, 254, 242, 207, 244,
+ 208, 455, 244, 245, 424, 244, 245, 239, 428, 495,
+ 241, 500, 389, 390, 397, 398, 241, 207, 207, 239,
+ 246, 207, 207, 247, 368, 238, 237, 224, 226, 257,
+ 259, 258, 208, 240, 207, 247, 237, 247, 237, 445,
+ 446, 247, 237, 245, 207, 451, 237, 207, 242, 237,
+ 206, 540, 244, 246, 415, 238, 240, 237, 240, 207,
+ 241, 481, 548, 238, 242, 205, 238, 16, 247, 413,
+ 241, 241, 246, 213, 494, 242, 399, 401, 247, 404,
+ 220, 400, 237, 233, 220, 402, 220, 227, 237, 509,
+ 283, 284, 199, 233, 500, 403, 414, 237, 321, 486,
+ 520, 489, 525, 535, 231, 536, 509, 489, 220, 302,
+ -1, 455, -1, 519, 534, -1, -1, 257, -1, -1,
+ -1, 261, -1, 316, -1, -1, 319, -1, -1, -1,
+ -1, -1, -1, -1, 540, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 494, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 514, -1, 509, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 322, 323, -1, 325, -1, -1, -1, -1,
+ -1, -1, -1, 386, 387, 388, 389, 390, 391, 392,
+ 393, 394, 395, 396, 397, 398, 399, 400, 401, 402,
+ 403, 404, -1, -1, 354, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 368, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 413, -1, -1, -1, -1, -1, -1,
+ -1, -1, 422, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 433, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 455, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 489,
+ -1, -1, -1, -1, 494, 495, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 509,
+ -1, -1, -1, -1, 514, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 526, -1, -1, -1,
+ 530, -1, -1, -1, -1, 535, -1, -1, -1, 539,
+ -1, -1, -1, -1, -1, -1, 0, -1, 548, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, -1, -1, 208, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 261, 262, 263,
+ 264, 265, 266, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, -1, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, -1, -1, 218, 219,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 237, -1, -1,
+ -1, 241, 242, -1, -1, -1, -1, 247, 248, 249,
+ 250, 251, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 261, 262, 263, 264, 265, 266, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ -1, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ -1, -1, 218, 219, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 237, -1, -1, -1, 241, 242, -1, -1, -1,
+ -1, 247, 248, 249, 250, 251, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 261, 262, 263, 264, 265,
+ 266, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, -1, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, -1, -1, 218, 219, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 237, -1, -1, -1, 241,
+ -1, -1, -1, -1, -1, 247, 248, 249, 250, 251,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 261,
+ 262, 263, 264, 265, 266, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, -1, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, -1, -1,
+ 218, 219, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 237,
+ -1, -1, -1, 241, -1, -1, -1, -1, -1, 247,
+ 248, 249, 250, 251, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 261, 262, 263, 264, 265, 266, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, -1, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, -1, -1, 218, 219, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 237, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 247, 248, 249, 250, 251, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 261, 262, 263,
+ 264, 265, 266, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, -1, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, -1, -1, 218, 219,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 237, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 247, 248, 249,
+ 250, 251, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 261, 262, 263, 264, 265, 266, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ -1, -1, 208, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ -1, -1, -1, -1, -1, 261, 262, 263, 264, 265,
+ 266, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, -1, 207, 208, 209, 210, 211, 212,
+ 213, 214, 215, -1, -1, 218, 219, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 237, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 248, 249, 250, 251, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 261, 262,
+ 263, 264, 265, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, -1, 207, 208, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 247, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, -1, -1,
+ -1, 261, 262, 263, 264, 265, -1, -1, -1, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, -1, -1, 208, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 242, -1, -1,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ -1, -1, -1, -1, -1, -1, 261, 262, 263, 264,
+ 265, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, -1, -1, 208, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 242,
+ -1, -1, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, -1, -1, -1, -1, -1, -1, 261, 262,
+ 263, 264, 265, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+ 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+ 201, 202, 203, 204, 205, -1, -1, 208, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 242, -1, -1, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, -1, -1, -1, -1, -1, -1,
+ 261, 262, 263, 264, 265, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, -1, -1, 208,
+ -1, -1, -1, 6, 7, 8, 9, 10, 11, 12,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 261, 262, 263, 264, 265, 60, 61, 62,
+ 63, 64, 65, -1, -1, -1, -1, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, -1, 207, 208, 209, 210, 211, 212,
+ 213, 214, 215, -1, -1, 218, 219, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 237, -1, -1, -1, 241, 242,
+ -1, -1, -1, -1, -1, 248, 249, 250, 251, 6,
+ 7, 8, 9, 10, 11, 12, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, -1,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, -1,
+ -1, 218, 219, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 237, -1, -1, 240, 6, 7, 8, 9, 10, 11,
+ 12, 248, 249, 250, 251, -1, -1, -1, -1, -1,
+ -1, -1, -1, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 60, 61,
+ 62, 63, 64, 65, -1, -1, -1, -1, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, -1, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, -1, -1, 218, 219, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 237, -1, -1, -1, 241,
+ -1, -1, -1, -1, -1, -1, 248, 249, 250, 251,
+ 6, 7, 8, 9, 10, 11, 12, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 60, 61, 62, 63, 64, 65,
+ -1, -1, -1, -1, 70, 71, 72, 73, 74, 75,
+ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
+ -1, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ -1, -1, 218, 219, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 237, -1, -1, 240, 6, 7, 8, 9, 10,
+ 11, 12, 248, 249, 250, 251, -1, -1, -1, -1,
+ -1, -1, -1, -1, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 60,
+ 61, 62, 63, 64, 65, -1, -1, -1, -1, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+ 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+ 201, 202, 203, 204, 205, -1, 207, 208, 209, 210,
+ 211, 212, 213, 214, 215, -1, -1, 218, 219, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 237, 6, 7, 8,
+ 9, 10, 11, 12, -1, -1, 247, 248, 249, 250,
+ 251, -1, -1, -1, -1, -1, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 60, 61, 62, 63, 64, 65, -1, -1, -1,
+ -1, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, -1, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, -1, -1, 218,
+ 219, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 237, 6,
+ 7, 8, 9, 10, 11, 12, -1, -1, -1, 248,
+ 249, 250, 251, -1, -1, -1, -1, -1, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 202, 203, 204, 205, -1,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, -1,
+ -1, 218, 219, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 237, 6, 7, 8, 9, 10, 11, 12, -1, -1,
+ -1, 248, 249, 250, 251, -1, -1, -1, -1, -1,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 60, 61, 62, 63, 64,
+ 65, -1, -1, -1, -1, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+ 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, -1, -1, 208
+};
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint16 yystos[] =
+{
+ 0, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, 208, 261, 262, 263, 264, 265, 266,
+ 301, 302, 305, 306, 307, 308, 312, 313, 314, 315,
+ 316, 317, 320, 321, 322, 323, 325, 327, 328, 329,
+ 366, 367, 368, 237, 237, 207, 241, 328, 207, 247,
+ 247, 369, 238, 244, 309, 310, 311, 321, 325, 244,
+ 247, 207, 207, 247, 322, 325, 239, 326, 0, 367,
+ 208, 324, 54, 207, 318, 319, 241, 331, 325, 247,
+ 326, 241, 348, 310, 309, 311, 207, 207, 237, 246,
+ 326, 241, 244, 247, 304, 207, 209, 210, 211, 212,
+ 213, 214, 215, 218, 219, 237, 240, 248, 249, 250,
+ 251, 271, 272, 273, 275, 276, 277, 278, 279, 280,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 325, 239, 238, 244, 246,
+ 238, 244, 330, 321, 325, 332, 333, 247, 247, 13,
+ 14, 15, 17, 18, 19, 20, 21, 22, 23, 206,
+ 241, 242, 247, 282, 295, 297, 299, 301, 305, 325,
+ 338, 339, 340, 341, 349, 350, 351, 354, 357, 358,
+ 365, 326, 246, 326, 241, 297, 336, 246, 303, 207,
+ 244, 247, 282, 282, 299, 218, 219, 239, 243, 238,
+ 238, 244, 205, 297, 237, 282, 252, 253, 254, 249,
+ 251, 216, 217, 220, 221, 255, 256, 222, 223, 259,
+ 258, 257, 224, 226, 225, 260, 240, 240, 295, 208,
+ 295, 300, 319, 332, 325, 207, 334, 335, 242, 333,
+ 247, 247, 360, 237, 237, 247, 247, 299, 237, 299,
+ 245, 237, 242, 342, 227, 228, 229, 230, 231, 232,
+ 233, 234, 235, 236, 246, 298, 244, 247, 242, 339,
+ 336, 246, 336, 337, 336, 332, 207, 238, 274, 299,
+ 207, 297, 282, 282, 282, 284, 284, 285, 285, 286,
+ 286, 286, 286, 287, 287, 288, 289, 290, 291, 292,
+ 293, 296, 240, 242, 334, 326, 244, 247, 339, 361,
+ 299, 247, 299, 245, 359, 349, 297, 297, 336, 242,
+ 244, 242, 240, 299, 247, 335, 206, 338, 350, 362,
+ 238, 238, 299, 314, 321, 353, 343, 242, 336, 245,
+ 237, 353, 363, 364, 345, 346, 347, 352, 355, 207,
+ 238, 242, 297, 299, 247, 238, 16, 341, 340, 241,
+ 246, 340, 344, 348, 238, 299, 344, 345, 349, 356,
+ 336, 247, 242
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint16 yyr1[] =
+{
+ 0, 270, 271, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 273, 273, 273, 273, 273, 273, 274, 275,
+ 276, 277, 277, 278, 278, 279, 279, 280, 281, 281,
+ 282, 282, 282, 282, 283, 283, 283, 283, 284, 284,
+ 284, 284, 285, 285, 285, 286, 286, 286, 287, 287,
+ 287, 287, 287, 288, 288, 288, 289, 289, 290, 290,
+ 291, 291, 292, 292, 293, 293, 294, 294, 295, 296,
+ 295, 297, 297, 298, 298, 298, 298, 298, 298, 298,
+ 298, 298, 298, 298, 299, 299, 300, 301, 301, 301,
+ 301, 301, 301, 301, 301, 301, 303, 302, 304, 304,
+ 305, 306, 306, 307, 307, 308, 309, 309, 310, 310,
+ 310, 310, 311, 312, 312, 312, 312, 312, 313, 313,
+ 313, 313, 313, 314, 314, 315, 316, 316, 316, 317,
+ 318, 318, 319, 319, 319, 320, 321, 321, 322, 322,
+ 322, 322, 322, 322, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323,
+ 323, 323, 323, 324, 324, 325, 325, 326, 326, 326,
+ 326, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 327, 327, 327, 327, 327,
+ 327, 327, 328, 328, 328, 330, 329, 331, 329, 332,
+ 332, 333, 333, 334, 334, 335, 335, 336, 336, 336,
+ 337, 337, 338, 339, 339, 340, 340, 340, 340, 340,
+ 340, 340, 341, 342, 343, 341, 344, 344, 346, 345,
+ 347, 345, 348, 348, 349, 349, 350, 350, 351, 352,
+ 352, 353, 353, 355, 354, 356, 356, 357, 357, 359,
+ 358, 360, 358, 361, 358, 362, 362, 363, 363, 364,
+ 364, 365, 365, 365, 365, 365, 366, 366, 367, 367,
+ 369, 368
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 3, 1, 4, 1, 3, 2, 2, 1, 1,
+ 1, 2, 2, 2, 1, 2, 3, 2, 1, 1,
+ 1, 2, 2, 2, 1, 1, 1, 1, 1, 3,
+ 3, 3, 1, 3, 3, 1, 3, 3, 1, 3,
+ 3, 3, 3, 1, 3, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 1, 3, 1, 0,
+ 6, 1, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 1, 2, 2, 4,
+ 2, 3, 4, 2, 3, 4, 0, 6, 2, 3,
+ 2, 1, 1, 2, 3, 3, 2, 3, 2, 1,
+ 2, 1, 1, 1, 3, 4, 6, 5, 1, 2,
+ 3, 5, 4, 1, 2, 1, 1, 1, 1, 4,
+ 1, 3, 1, 3, 1, 1, 1, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 4, 1, 3, 1, 2, 2, 3, 3,
+ 4, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 6, 0, 5, 1,
+ 2, 3, 4, 1, 3, 1, 2, 1, 3, 4,
+ 1, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 0, 0, 5, 1, 1, 0, 2,
+ 0, 2, 2, 3, 1, 2, 1, 2, 5, 3,
+ 1, 1, 4, 0, 8, 0, 1, 3, 2, 0,
+ 6, 0, 8, 0, 7, 1, 1, 1, 0, 2,
+ 3, 2, 2, 2, 3, 2, 1, 2, 1, 1,
+ 0, 3
+};
+
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (pParseContext, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (0)
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, pParseContext); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (pParseContext);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, pParseContext);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, glslang::TParseContext* pParseContext)
+{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , pParseContext);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule, pParseContext); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, glslang::TParseContext* pParseContext)
+{
+ YYUSE (yyvaluep);
+ YYUSE (pParseContext);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YYUSE (yytype);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (glslang::TParseContext* pParseContext)
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = yylex (&yylval, parseContext);
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 246 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string);
+ }
+#line 3174 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 3:
+#line 252 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3182 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 4:
+#line 255 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
+ }
+#line 3190 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 5:
+#line 258 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
+ }
+#line 3199 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 262 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true);
+ }
+#line 3208 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 266 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true);
+ }
+#line 3217 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 270 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true);
+ }
+#line 3225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 9:
+#line 273 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal");
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true);
+ }
+#line 3234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 10:
+#line 277 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true);
+ }
+#line 3242 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 11:
+#line 280 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
+ if ((yyval.interm.intermTypedNode)->getAsConstantUnion())
+ (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression();
+ }
+#line 3252 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 288 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3260 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 13:
+#line 291 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 3268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 14:
+#line 294 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 297 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string);
+ }
+#line 3284 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 16:
+#line 300 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode));
+ parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 3294 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 17:
+#line 305 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode));
+ parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode));
+ }
+#line 3304 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 18:
+#line 313 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]");
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3313 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 19:
+#line 320 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode);
+ delete (yyvsp[0].interm).function;
+ }
+#line 3322 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 20:
+#line 327 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ }
+#line 3330 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 21:
+#line 333 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ }
+#line 3339 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 22:
+#line 337 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ }
+#line 3348 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 23:
+#line 344 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ }
+#line 3356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 24:
+#line 347 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ }
+#line 3364 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 25:
+#line 353 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType());
+ (yyvsp[-1].interm).function->addParameter(param);
+ (yyval.interm).function = (yyvsp[-1].interm).function;
+ (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 26:
+#line 360 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TParameter param = { 0, new TType };
+ param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType());
+ (yyvsp[-2].interm).function->addParameter(param);
+ (yyval.interm).function = (yyvsp[-2].interm).function;
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
+ }
+#line 3388 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 27:
+#line 370 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-1].interm);
+ }
+#line 3396 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 28:
+#line 378 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // Constructor
+ (yyval.interm).intermNode = 0;
+ (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type));
+ }
+#line 3406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 29:
+#line 383 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ //
+ // Should be a method or subroutine call, but we haven't recognized the arguments yet.
+ //
+ (yyval.interm).function = 0;
+ (yyval.interm).intermNode = 0;
+
+ TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode();
+ if (method) {
+ (yyval.interm).function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength);
+ (yyval.interm).intermNode = method->getObject();
+ } else {
+ TIntermSymbol* symbol = (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode();
+ if (symbol) {
+ parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName());
+ TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid));
+ (yyval.interm).function = function;
+ } else
+ parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "function call, method, or subroutine call expected", "", "");
+ }
+
+ if ((yyval.interm).function == 0) {
+ // error recover
+ TString empty("");
+ (yyval.interm).function = new TFunction(&empty, TType(EbtVoid), EOpNull);
+ }
+ }
+#line 3438 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 30:
+#line 413 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.variableCheck((yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode())
+ parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), "");
+ }
+#line 3449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 31:
+#line 419 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode));
+ }
+#line 3458 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 32:
+#line 423 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode));
+ }
+#line 3467 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 33:
+#line 427 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm).op != EOpNull) {
+ char errorOp[2] = {0, 0};
+ switch((yyvsp[-1].interm).op) {
+ case EOpNegative: errorOp[0] = '-'; break;
+ case EOpLogicalNot: errorOp[0] = '!'; break;
+ case EOpBitwiseNot: errorOp[0] = '~'; break;
+ default: break; // some compilers want this
+ }
+ (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].interm).loc, errorOp, (yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode));
+ } else {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ if ((yyval.interm.intermTypedNode)->getAsConstantUnion())
+ (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression();
+ }
+ }
+#line 3488 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 34:
+#line 447 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; }
+#line 3494 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 35:
+#line 448 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; }
+#line 3500 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 36:
+#line 449 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; }
+#line 3506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 37:
+#line 450 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot;
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); }
+#line 3513 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 38:
+#line 456 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3519 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 39:
+#line 457 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 40:
+#line 462 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3539 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 41:
+#line 467 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3550 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 42:
+#line 476 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 43:
+#line 477 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 44:
+#line 482 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 45:
+#line 490 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3582 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 46:
+#line 491 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3593 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 47:
+#line 497 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3604 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 48:
+#line 506 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3610 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 49:
+#line 507 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3620 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 50:
+#line 512 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3630 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 51:
+#line 517 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3640 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 52:
+#line 522 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 53:
+#line 530 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3656 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 54:
+#line 531 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison");
+ parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "==");
+ parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "==");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "==", EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 55:
+#line 539 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison");
+ parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!=");
+ parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!=");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "!=", EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 56:
+#line 550 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3688 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 57:
+#line 551 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3699 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 58:
+#line 560 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3705 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 59:
+#line 561 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 60:
+#line 570 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3722 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 61:
+#line 571 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or");
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 3733 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 62:
+#line 580 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3739 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 63:
+#line 581 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3749 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 64:
+#line 589 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3755 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 65:
+#line 590 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3765 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 66:
+#line 598 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 67:
+#line 599 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ if ((yyval.interm.intermTypedNode) == 0)
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
+ }
+#line 3781 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 68:
+#line 607 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3787 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 69:
+#line 608 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 3795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 70:
+#line 611 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ --parseContext.controlFlowNestingLevel;
+ parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-4].lex).loc, "?", (yyvsp[-5].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+ }
+#line 3812 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 71:
+#line 626 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
+#line 3818 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 72:
+#line 627 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment");
+ parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=");
+ parseContext.specializationCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=");
+ parseContext.lValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode));
+ parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].interm).loc);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+ }
+#line 3835 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 73:
+#line 642 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpAssign;
+ }
+#line 3844 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 74:
+#line 646 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpMulAssign;
+ }
+#line 3853 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 75:
+#line 650 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpDivAssign;
+ }
+#line 3862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 76:
+#line 654 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%=");
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpModAssign;
+ }
+#line 3872 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 77:
+#line 659 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpAddAssign;
+ }
+#line 3881 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 78:
+#line 663 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).op = EOpSubAssign;
+ }
+#line 3890 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 79:
+#line 667 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign;
+ }
+#line 3899 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 80:
+#line 671 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign;
+ }
+#line 3908 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 81:
+#line 675 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign;
+ }
+#line 3917 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 82:
+#line 679 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign;
+ }
+#line 3926 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 83:
+#line 683 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign");
+ (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign;
+ }
+#line 3935 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 84:
+#line 690 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3943 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 85:
+#line 693 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+ }
+#line 3955 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 86:
+#line 703 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), "");
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 3964 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 87:
+#line 710 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */);
+ (yyval.interm.intermNode) = 0;
+ // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
+ }
+#line 3974 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 88:
+#line 715 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate())
+ (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence);
+ (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode;
+ }
+#line 3984 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 89:
+#line 720 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement");
+
+ // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope
+ parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]);
+ parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 3997 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 90:
+#line 728 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 4006 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 91:
+#line 732 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 4015 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 92:
+#line 736 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 4024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 93:
+#line 740 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
+ parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type));
+ (yyval.interm.intermNode) = 0;
+ }
+#line 4034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 94:
+#line 745 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers);
+ parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string);
+ (yyval.interm.intermNode) = 0;
+ }
+#line 4044 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 95:
+#line 750 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers);
+ (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string);
+ parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList));
+ (yyval.interm.intermNode) = 0;
+ }
+#line 4055 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 96:
+#line 759 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); }
+#line 4061 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 97:
+#line 759 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ --parseContext.structNestingLevel;
+ parseContext.blockName = (yyvsp[-4].lex).string;
+ parseContext.globalQualifierFixCheck((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).qualifier);
+ parseContext.checkNoShaderLayouts((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).shaderQualifiers);
+ parseContext.currentBlockQualifier = (yyvsp[-5].interm.type).qualifier;
+ (yyval.interm).loc = (yyvsp[-5].interm.type).loc;
+ (yyval.interm).typeList = (yyvsp[-1].interm.typeList);
+ }
+#line 4075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 98:
+#line 770 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.identifierList) = new TIdentifierList;
+ (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string);
+ }
+#line 4084 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 99:
+#line 774 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList);
+ (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string);
+ }
+#line 4093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 100:
+#line 781 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).function = (yyvsp[-1].interm.function);
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ }
+#line 4102 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 101:
+#line 788 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.function) = (yyvsp[0].interm.function);
+ }
+#line 4110 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 102:
+#line 791 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.function) = (yyvsp[0].interm.function);
+ }
+#line 4118 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 103:
+#line 798 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // Add the parameter
+ (yyval.interm.function) = (yyvsp[-1].interm.function);
+ if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid)
+ (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param);
+ else
+ delete (yyvsp[0].interm).param.type;
+ }
+#line 4131 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 104:
+#line 806 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ parseContext.error((yyvsp[-1].lex).loc, "cannot be an argument type except for '(void)'", "void", "");
+ delete (yyvsp[0].interm).param.type;
+ } else {
+ // Add the parameter
+ (yyval.interm.function) = (yyvsp[-2].interm.function);
+ (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param);
+ }
+ }
+#line 4153 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 105:
+#line 826 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) {
+ parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return",
+ GetStorageQualifierString((yyvsp[-2].interm.type).qualifier.storage), "");
+ }
+ if ((yyvsp[-2].interm.type).arraySizes)
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type((yyvsp[-2].interm.type));
+ function = new TFunction((yyvsp[-1].lex).string, type);
+ (yyval.interm.function) = function;
+ }
+#line 4172 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 106:
+#line 844 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-1].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck((yyvsp[-1].interm.type).loc, *(yyvsp[-1].interm.type).arraySizes);
+ }
+ if ((yyvsp[-1].interm.type).basicType == EbtVoid) {
+ parseContext.error((yyvsp[0].lex).loc, "illegal use of type 'void'", (yyvsp[0].lex).string->c_str(), "");
+ }
+ parseContext.reservedErrorCheck((yyvsp[0].lex).loc, *(yyvsp[0].lex).string);
+
+ TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))};
+ (yyval.interm).loc = (yyvsp[0].lex).loc;
+ (yyval.interm).param = param;
+ }
+#line 4192 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 107:
+#line 859 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+ }
+ parseContext.arrayDimCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.type).arraySizes, (yyvsp[0].interm).arraySizes);
+
+ parseContext.arraySizeRequiredCheck((yyvsp[0].interm).loc, *(yyvsp[0].interm).arraySizes);
+ parseContext.reservedErrorCheck((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string);
+
+ (yyvsp[-2].interm.type).arraySizes = (yyvsp[0].interm).arraySizes;
+
+ TParameter param = { (yyvsp[-1].lex).string, new TType((yyvsp[-2].interm.type))};
+ (yyval.interm).loc = (yyvsp[-1].lex).loc;
+ (yyval.interm).param = param;
+ }
+#line 4214 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 108:
+#line 882 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone)
+ (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision;
+ parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers);
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type);
+ parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type);
+
+ }
+#line 4230 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 109:
+#line 893 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type);
+ parseContext.paramCheckFix((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type);
+ parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+ }
+#line 4242 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 110:
+#line 903 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone)
+ (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision;
+ parseContext.precisionQualifierCheck((yyvsp[-1].interm.type).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+
+ parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers);
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type);
+ parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type);
+ }
+#line 4257 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 111:
+#line 913 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+
+ parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type);
+ parseContext.paramCheckFix((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type);
+ parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
+ }
+#line 4269 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 112:
+#line 923 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TParameter param = { 0, new TType((yyvsp[0].interm.type)) };
+ (yyval.interm).param = param;
+ if ((yyvsp[0].interm.type).arraySizes)
+ parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes);
+ }
+#line 4280 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 113:
+#line 932 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[0].interm);
+ }
+#line 4288 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 114:
+#line 935 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-2].interm);
+ parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type);
+ }
+#line 4297 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 115:
+#line 939 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-3].interm);
+ parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes);
+ }
+#line 4306 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 116:
+#line 943 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-5].interm).type;
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 4316 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 117:
+#line 948 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-4].interm).type;
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 4326 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 118:
+#line 956 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[0].interm.type);
+ (yyval.interm).intermNode = 0;
+ parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type);
+ }
+#line 4336 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 119:
+#line 961 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-1].interm.type);
+ (yyval.interm).intermNode = 0;
+ parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type));
+ }
+#line 4346 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 120:
+#line 966 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-2].interm.type);
+ (yyval.interm).intermNode = 0;
+ parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes);
+ }
+#line 4356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 121:
+#line 971 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-4].interm.type);
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 4366 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 122:
+#line 976 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).type = (yyvsp[-3].interm.type);
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode));
+ (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc);
+ }
+#line 4376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 123:
+#line 985 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+
+ parseContext.globalQualifierTypeCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyval.interm.type));
+ if ((yyvsp[0].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ }
+
+ parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier);
+ }
+#line 4392 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 124:
+#line 996 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
+ parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type));
+
+ if ((yyvsp[0].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ }
+
+ if ((yyvsp[0].interm.type).arraySizes && parseContext.arrayQualifierError((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).qualifier))
+ (yyvsp[0].interm.type).arraySizes = 0;
+
+ parseContext.checkNoShaderLayouts((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers);
+ (yyvsp[0].interm.type).shaderQualifiers.merge((yyvsp[-1].interm.type).shaderQualifiers);
+ parseContext.mergeQualifiers((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyvsp[-1].interm.type).qualifier, true);
+ parseContext.precisionQualifierCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).basicType, (yyvsp[0].interm.type).qualifier);
+
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+
+ if (! (yyval.interm.type).qualifier.isInterpolation() &&
+ ((parseContext.language == EShLangVertex && (yyval.interm.type).qualifier.storage == EvqVaryingOut) ||
+ (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn)))
+ (yyval.interm.type).qualifier.smooth = true;
+ }
+#line 4421 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 125:
+#line 1023 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "invariant");
+ parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.invariant = true;
+ }
+#line 4432 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 126:
+#line 1032 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "smooth");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "smooth");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.smooth = true;
+ }
+#line 4444 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 127:
+#line 1039 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "flat");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "flat");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.flat = true;
+ }
+#line 4456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 128:
+#line 1046 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective");
+ parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "noperspective");
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "noperspective");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.nopersp = true;
+ }
+#line 4468 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 129:
+#line 1056 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-1].interm.type);
+ }
+#line 4476 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 130:
+#line 1062 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4484 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 131:
+#line 1065 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-2].interm.type);
+ (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers);
+ parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false);
+ }
+#line 4494 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 132:
+#line 1072 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string);
+ }
+#line 4503 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 133:
+#line 1076 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[-2].lex).loc);
+ parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode));
+ }
+#line 4512 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 134:
+#line 1080 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { // because "shared" is both an identifier and a keyword
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ TString strShared("shared");
+ parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared);
+ }
+#line 4522 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 135:
+#line 1088 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.noContraction = true;
+ }
+#line 4533 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 136:
+#line 1097 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 137:
+#line 1100 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[-1].interm.type);
+ if ((yyval.interm.type).basicType == EbtVoid)
+ (yyval.interm.type).basicType = (yyvsp[0].interm.type).basicType;
+
+ (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers);
+ parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false);
+ }
+#line 4554 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 138:
+#line 1111 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4562 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 139:
+#line 1114 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4570 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 140:
+#line 1117 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4578 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 141:
+#line 1120 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // allow inheritance of storage qualifier from block declaration
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 142:
+#line 1124 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // allow inheritance of storage qualifier from block declaration
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 143:
+#line 1128 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // allow inheritance of storage qualifier from block declaration
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ }
+#line 4605 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 144:
+#line 1135 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant
+ }
+#line 4614 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 145:
+#line 1139 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute");
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute");
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "attribute");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "attribute");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "attribute");
+
+ parseContext.globalCheck((yyvsp[0].lex).loc, "attribute");
+
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqVaryingIn;
+ }
+#line 4631 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 146:
+#line 1151 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying");
+ parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "varying");
+ parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "varying");
+
+ parseContext.globalCheck((yyvsp[0].lex).loc, "varying");
+
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ if (parseContext.language == EShLangVertex)
+ (yyval.interm.type).qualifier.storage = EvqVaryingOut;
+ else
+ (yyval.interm.type).qualifier.storage = EvqVaryingIn;
+ }
+#line 4650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 147:
+#line 1165 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "inout");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqInOut;
+ }
+#line 4660 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 148:
+#line 1170 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "in");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later
+ (yyval.interm.type).qualifier.storage = EvqIn;
+ }
+#line 4671 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 149:
+#line 1176 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "out");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later
+ (yyval.interm.type).qualifier.storage = EvqOut;
+ }
+#line 4682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 150:
+#line 1182 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid");
+ parseContext.globalCheck((yyvsp[0].lex).loc, "centroid");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.centroid = true;
+ }
+#line 4694 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 151:
+#line 1189 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "patch");
+ parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.patch = true;
+ }
+#line 4705 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 152:
+#line 1195 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "sample");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.sample = true;
+ }
+#line 4715 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 153:
+#line 1200 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "uniform");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqUniform;
+ }
+#line 4725 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 154:
+#line 1205 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalCheck((yyvsp[0].lex).loc, "buffer");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqBuffer;
+ }
+#line 4735 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 155:
+#line 1210 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared");
+ parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 310, 0, "shared");
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangCompute, "shared");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqShared;
+ }
+#line 4747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 156:
+#line 1217 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.coherent = true;
+ }
+#line 4756 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 157:
+#line 1221 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.volatil = true;
+ }
+#line 4765 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 158:
+#line 1225 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.restrict = true;
+ }
+#line 4774 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 159:
+#line 1229 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.readonly = true;
+ }
+#line 4783 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 160:
+#line 1233 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.writeonly = true;
+ }
+#line 4792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 161:
+#line 1237 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine");
+ parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine");
+ (yyval.interm.type).init((yyvsp[0].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqUniform;
+ }
+#line 4803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 162:
+#line 1243 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine");
+ parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine");
+ (yyval.interm.type).init((yyvsp[-3].lex).loc);
+ (yyval.interm.type).qualifier.storage = EvqUniform;
+ // TODO: 4.0 semantics: subroutines
+ // 1) make sure each identifier is a type declared earlier with SUBROUTINE
+ // 2) save all of the identifiers for future comparison with the declared function
+ }
+#line 4817 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 163:
+#line 1255 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // TODO: 4.0 functionality: subroutine type to list
+ }
+#line 4825 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 164:
+#line 1258 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ }
+#line 4832 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 165:
+#line 1263 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type));
+ }
+#line 4841 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 166:
+#line 1267 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayDimCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes, 0);
+ (yyval.interm.type) = (yyvsp[-1].interm.type);
+ (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type));
+ (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes;
+ }
+#line 4852 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 167:
+#line 1276 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[-1].lex).loc;
+ (yyval.interm).arraySizes = new TArraySizes;
+ (yyval.interm).arraySizes->addInnerSize();
+ }
+#line 4862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 168:
+#line 1281 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm).loc = (yyvsp[-2].lex).loc;
+ (yyval.interm).arraySizes = new TArraySizes;
+
+ TArraySize size;
+ parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size);
+ (yyval.interm).arraySizes->addInnerSize(size);
+ }
+#line 4875 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 169:
+#line 1289 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-2].interm);
+ (yyval.interm).arraySizes->addInnerSize();
+ }
+#line 4884 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 170:
+#line 1293 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm) = (yyvsp[-3].interm);
+
+ TArraySize size;
+ parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size);
+ (yyval.interm).arraySizes->addInnerSize(size);
+ }
+#line 4896 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 171:
+#line 1303 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtVoid;
+ }
+#line 4905 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 172:
+#line 1307 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ }
+#line 4914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 173:
+#line 1311 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ }
+#line 4924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 174:
+#line 1316 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ }
+#line 4933 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 175:
+#line 1320 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ }
+#line 4943 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 176:
+#line 1325 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ }
+#line 4953 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 177:
+#line 1330 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ }
+#line 4963 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 178:
+#line 1335 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ }
+#line 4972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 179:
+#line 1339 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(2);
+ }
+#line 4982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 180:
+#line 1344 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(3);
+ }
+#line 4992 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 181:
+#line 1349 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5002 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 182:
+#line 1354 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(2);
+ }
+#line 5013 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 183:
+#line 1360 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(3);
+ }
+#line 5024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 184:
+#line 1366 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5035 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 185:
+#line 1372 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ (yyval.interm.type).setVector(2);
+ }
+#line 5045 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 186:
+#line 1377 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ (yyval.interm.type).setVector(3);
+ }
+#line 5055 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 187:
+#line 1382 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtBool;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5065 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 188:
+#line 1387 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(2);
+ }
+#line 5075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 189:
+#line 1392 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(3);
+ }
+#line 5085 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 190:
+#line 1397 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5095 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 191:
+#line 1402 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ (yyval.interm.type).setVector(2);
+ }
+#line 5106 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 192:
+#line 1408 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ (yyval.interm.type).setVector(3);
+ }
+#line 5117 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 193:
+#line 1414 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtInt64;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5128 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 194:
+#line 1420 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(2);
+ }
+#line 5139 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 195:
+#line 1426 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(3);
+ }
+#line 5150 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 196:
+#line 1432 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5161 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 197:
+#line 1438 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ (yyval.interm.type).setVector(2);
+ }
+#line 5172 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 198:
+#line 1444 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ (yyval.interm.type).setVector(3);
+ }
+#line 5183 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 199:
+#line 1450 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtUint64;
+ (yyval.interm.type).setVector(4);
+ }
+#line 5194 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 200:
+#line 1456 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 5204 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 201:
+#line 1461 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 5214 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 202:
+#line 1466 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 5224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 203:
+#line 1471 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 5234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 204:
+#line 1476 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 5244 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 205:
+#line 1481 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 5254 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 206:
+#line 1486 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 5264 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 207:
+#line 1491 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 5274 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 208:
+#line 1496 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 5284 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 209:
+#line 1501 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 5294 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 210:
+#line 1506 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 5304 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 211:
+#line 1511 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtFloat;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 5314 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 212:
+#line 1516 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 5325 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 213:
+#line 1522 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 5336 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 214:
+#line 1528 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 5347 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 215:
+#line 1534 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 2);
+ }
+#line 5358 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 216:
+#line 1540 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 3);
+ }
+#line 5369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 217:
+#line 1546 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(2, 4);
+ }
+#line 5380 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 218:
+#line 1552 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 2);
+ }
+#line 5391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 219:
+#line 1558 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 3);
+ }
+#line 5402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 220:
+#line 1564 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(3, 4);
+ }
+#line 5413 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 221:
+#line 1570 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 2);
+ }
+#line 5424 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 222:
+#line 1576 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 3);
+ }
+#line 5435 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 223:
+#line 1582 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtDouble;
+ (yyval.interm.type).setMatrix(4, 4);
+ }
+#line 5446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 224:
+#line 1588 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtAtomicUint;
+ }
+#line 5456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 225:
+#line 1593 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D);
+ }
+#line 5466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 226:
+#line 1598 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
+ }
+#line 5476 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 227:
+#line 1603 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd3D);
+ }
+#line 5486 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 228:
+#line 1608 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube);
+ }
+#line 5496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 229:
+#line 1613 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true);
+ }
+#line 5506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 230:
+#line 1618 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true);
+ }
+#line 5516 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 231:
+#line 1623 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true);
+ }
+#line 5526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 232:
+#line 1628 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true);
+ }
+#line 5536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 233:
+#line 1633 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true);
+ }
+#line 5546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 234:
+#line 1638 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true);
+ }
+#line 5556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 235:
+#line 1643 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true);
+ }
+#line 5566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 236:
+#line 1648 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true);
+ }
+#line 5576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 237:
+#line 1653 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true);
+ }
+#line 5586 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 238:
+#line 1658 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd1D);
+ }
+#line 5596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 239:
+#line 1663 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D);
+ }
+#line 5606 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 240:
+#line 1668 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd3D);
+ }
+#line 5616 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 241:
+#line 1673 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdCube);
+ }
+#line 5626 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 242:
+#line 1678 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd1D, true);
+ }
+#line 5636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 243:
+#line 1683 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D, true);
+ }
+#line 5646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 244:
+#line 1688 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdCube, true);
+ }
+#line 5656 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 245:
+#line 1693 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd1D);
+ }
+#line 5666 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 246:
+#line 1698 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D);
+ }
+#line 5676 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 247:
+#line 1703 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd3D);
+ }
+#line 5686 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 248:
+#line 1708 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdCube);
+ }
+#line 5696 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 249:
+#line 1713 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd1D, true);
+ }
+#line 5706 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 250:
+#line 1718 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D, true);
+ }
+#line 5716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 251:
+#line 1723 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdCube, true);
+ }
+#line 5726 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 252:
+#line 1728 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdRect);
+ }
+#line 5736 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 253:
+#line 1733 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true);
+ }
+#line 5746 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 254:
+#line 1738 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdRect);
+ }
+#line 5756 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 255:
+#line 1743 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdRect);
+ }
+#line 5766 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 256:
+#line 1748 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer);
+ }
+#line 5776 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 257:
+#line 1753 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, EsdBuffer);
+ }
+#line 5786 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 258:
+#line 1758 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, EsdBuffer);
+ }
+#line 5796 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 259:
+#line 1763 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true);
+ }
+#line 5806 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 260:
+#line 1768 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true);
+ }
+#line 5816 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 261:
+#line 1773 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true);
+ }
+#line 5826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 262:
+#line 1778 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true);
+ }
+#line 5836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 263:
+#line 1783 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true);
+ }
+#line 5846 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 264:
+#line 1788 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true);
+ }
+#line 5856 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 265:
+#line 1793 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setPureSampler(false);
+ }
+#line 5866 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 266:
+#line 1798 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setPureSampler(true);
+ }
+#line 5876 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 267:
+#line 1803 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D);
+ }
+#line 5886 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 268:
+#line 1808 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D);
+ }
+#line 5896 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 269:
+#line 1813 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D);
+ }
+#line 5906 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 270:
+#line 1818 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube);
+ }
+#line 5916 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 271:
+#line 1823 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true);
+ }
+#line 5926 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 272:
+#line 1828 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true);
+ }
+#line 5936 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 273:
+#line 1833 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true);
+ }
+#line 5946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 274:
+#line 1838 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D);
+ }
+#line 5956 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 275:
+#line 1843 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D);
+ }
+#line 5966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 276:
+#line 1848 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D);
+ }
+#line 5976 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 277:
+#line 1853 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube);
+ }
+#line 5986 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 278:
+#line 1858 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true);
+ }
+#line 5996 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 279:
+#line 1863 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true);
+ }
+#line 6006 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 280:
+#line 1868 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true);
+ }
+#line 6016 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 281:
+#line 1873 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D);
+ }
+#line 6026 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 282:
+#line 1878 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D);
+ }
+#line 6036 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 283:
+#line 1883 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D);
+ }
+#line 6046 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 284:
+#line 1888 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube);
+ }
+#line 6056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 285:
+#line 1893 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true);
+ }
+#line 6066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 286:
+#line 1898 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true);
+ }
+#line 6076 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 287:
+#line 1903 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true);
+ }
+#line 6086 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 288:
+#line 1908 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect);
+ }
+#line 6096 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 289:
+#line 1913 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect);
+ }
+#line 6106 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 290:
+#line 1918 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect);
+ }
+#line 6116 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 291:
+#line 1923 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer);
+ }
+#line 6126 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 292:
+#line 1928 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer);
+ }
+#line 6136 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 293:
+#line 1933 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer);
+ }
+#line 6146 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 294:
+#line 1938 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true);
+ }
+#line 6156 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 295:
+#line 1943 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true);
+ }
+#line 6166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 296:
+#line 1948 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true);
+ }
+#line 6176 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 297:
+#line 1953 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true);
+ }
+#line 6186 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 298:
+#line 1958 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true);
+ }
+#line 6196 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 299:
+#line 1963 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true);
+ }
+#line 6206 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 300:
+#line 1968 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D);
+ }
+#line 6216 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 301:
+#line 1973 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd1D);
+ }
+#line 6226 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 302:
+#line 1978 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd1D);
+ }
+#line 6236 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 303:
+#line 1983 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D);
+ }
+#line 6246 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 304:
+#line 1988 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D);
+ }
+#line 6256 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 305:
+#line 1993 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D);
+ }
+#line 6266 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 306:
+#line 1998 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D);
+ }
+#line 6276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 307:
+#line 2003 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd3D);
+ }
+#line 6286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 308:
+#line 2008 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd3D);
+ }
+#line 6296 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 309:
+#line 2013 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect);
+ }
+#line 6306 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 310:
+#line 2018 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdRect);
+ }
+#line 6316 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 311:
+#line 2023 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdRect);
+ }
+#line 6326 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 312:
+#line 2028 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube);
+ }
+#line 6336 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 313:
+#line 2033 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdCube);
+ }
+#line 6346 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 314:
+#line 2038 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdCube);
+ }
+#line 6356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 315:
+#line 2043 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer);
+ }
+#line 6366 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 316:
+#line 2048 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer);
+ }
+#line 6376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 317:
+#line 2053 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer);
+ }
+#line 6386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 318:
+#line 2058 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true);
+ }
+#line 6396 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 319:
+#line 2063 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true);
+ }
+#line 6406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 320:
+#line 2068 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true);
+ }
+#line 6416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 321:
+#line 2073 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true);
+ }
+#line 6426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 322:
+#line 2078 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true);
+ }
+#line 6436 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 323:
+#line 2083 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true);
+ }
+#line 6446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 324:
+#line 2088 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true);
+ }
+#line 6456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 325:
+#line 2093 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true);
+ }
+#line 6466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 326:
+#line 2098 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true);
+ }
+#line 6476 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 327:
+#line 2103 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true);
+ }
+#line 6486 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 328:
+#line 2108 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true);
+ }
+#line 6496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 329:
+#line 2113 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true);
+ }
+#line 6506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 330:
+#line 2118 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true);
+ }
+#line 6516 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 331:
+#line 2123 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true);
+ }
+#line 6526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 332:
+#line 2128 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true);
+ }
+#line 6536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 333:
+#line 2133 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { // GL_OES_EGL_image_external
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
+ (yyval.interm.type).sampler.external = true;
+ }
+#line 6547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 334:
+#line 2139 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtFloat);
+ }
+#line 6558 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 335:
+#line 2145 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtFloat, true);
+ }
+#line 6569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 336:
+#line 2151 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtInt);
+ }
+#line 6580 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 337:
+#line 2157 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtInt, true);
+ }
+#line 6591 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 338:
+#line 2163 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtUint);
+ }
+#line 6602 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 339:
+#line 2169 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtSampler;
+ (yyval.interm.type).sampler.setSubpass(EbtUint, true);
+ }
+#line 6613 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 340:
+#line 2175 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.type) = (yyvsp[0].interm.type);
+ (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type));
+ }
+#line 6623 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 341:
+#line 2180 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ if (const TVariable* variable = ((yyvsp[0].lex).symbol)->getAsVariable()) {
+ const TType& structure = variable->getType();
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ (yyval.interm.type).basicType = EbtStruct;
+ (yyval.interm.type).userDef = &structure;
+ } else
+ parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), "");
+ }
+#line 6641 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 342:
+#line 2196 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ if (parseContext.profile == EEsProfile)
+ (yyval.interm.type).qualifier.precision = EpqHigh;
+ }
+#line 6652 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 343:
+#line 2202 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ if (parseContext.profile == EEsProfile)
+ (yyval.interm.type).qualifier.precision = EpqMedium;
+ }
+#line 6663 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 344:
+#line 2208 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier");
+ (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+ if (parseContext.profile == EEsProfile)
+ (yyval.interm.type).qualifier.precision = EpqLow;
+ }
+#line 6674 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 345:
+#line 2217 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); }
+#line 6680 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 346:
+#line 2217 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string);
+ parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure);
+ TVariable* userTypeDef = new TVariable((yyvsp[-4].lex).string, *structure, true);
+ if (! parseContext.symbolTable.insert(*userTypeDef))
+ parseContext.error((yyvsp[-4].lex).loc, "redefinition", (yyvsp[-4].lex).string->c_str(), "struct");
+ (yyval.interm.type).init((yyvsp[-5].lex).loc);
+ (yyval.interm.type).basicType = EbtStruct;
+ (yyval.interm.type).userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+#line 6696 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 347:
+#line 2228 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); }
+#line 6702 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 348:
+#line 2228 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ TType* structure = new TType((yyvsp[-1].interm.typeList), TString(""));
+ (yyval.interm.type).init((yyvsp[-4].lex).loc);
+ (yyval.interm.type).basicType = EbtStruct;
+ (yyval.interm.type).userDef = structure;
+ --parseContext.structNestingLevel;
+ }
+#line 6714 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 349:
+#line 2238 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList) = (yyvsp[0].interm.typeList);
+ }
+#line 6722 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 350:
+#line 2241 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
+ for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) {
+ for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) {
+ if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[0].interm.typeList))[i].type->getFieldName())
+ parseContext.error((*(yyvsp[0].interm.typeList))[i].loc, "duplicate member name:", "", (*(yyvsp[0].interm.typeList))[i].type->getFieldName().c_str());
+ }
+ (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]);
+ }
+ }
+#line 6737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 351:
+#line 2254 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.profile == EEsProfile)
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+ }
+
+ (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
+
+ parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType);
+ parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier);
+
+ for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+ parseContext.arrayDimCheck((yyvsp[-2].interm.type).loc, (*(yyval.interm.typeList))[i].type, (yyvsp[-2].interm.type).arraySizes);
+ (*(yyval.interm.typeList))[i].type->mergeType((yyvsp[-2].interm.type));
+ }
+ }
+#line 6760 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 352:
+#line 2272 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.globalQualifierFixCheck((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier);
+ if ((yyvsp[-2].interm.type).arraySizes) {
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
+ parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type");
+ if (parseContext.profile == EEsProfile)
+ parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes);
+ }
+
+ (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
+
+ parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers);
+ parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType);
+ parseContext.mergeQualifiers((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, (yyvsp[-3].interm.type).qualifier, true);
+ parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier);
+
+ for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+ parseContext.arrayDimCheck((yyvsp[-3].interm.type).loc, (*(yyval.interm.typeList))[i].type, (yyvsp[-2].interm.type).arraySizes);
+ (*(yyval.interm.typeList))[i].type->mergeType((yyvsp[-2].interm.type));
+ }
+ }
+#line 6786 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 353:
+#line 2296 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList) = new TTypeList;
+ (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine));
+ }
+#line 6795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 354:
+#line 2300 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine));
+ }
+#line 6803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 355:
+#line 2306 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.typeLine).type = new TType(EbtVoid);
+ (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc;
+ (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string);
+ }
+#line 6813 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 356:
+#line 2311 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.arrayDimCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes, 0);
+
+ (yyval.interm.typeLine).type = new TType(EbtVoid);
+ (yyval.interm.typeLine).loc = (yyvsp[-1].lex).loc;
+ (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string);
+ (yyval.interm.typeLine).type->newArraySizes(*(yyvsp[0].interm).arraySizes);
+ }
+#line 6826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 357:
+#line 2322 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 6834 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 358:
+#line 2325 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
+ }
+#line 6845 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 359:
+#line 2331 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ const char* initFeature = "{ } style initializers";
+ parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature);
+ parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
+ (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
+ }
+#line 6856 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 360:
+#line 2340 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc());
+ }
+#line 6864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 361:
+#line 2343 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+ }
+#line 6872 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 362:
+#line 2349 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6878 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 363:
+#line 2353 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6884 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 364:
+#line 2354 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6890 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 365:
+#line 2360 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6896 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 366:
+#line 2361 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 367:
+#line 2362 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6908 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 368:
+#line 2363 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 369:
+#line 2364 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6920 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 370:
+#line 2365 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6926 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 371:
+#line 2366 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6932 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 372:
+#line 2370 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = 0; }
+#line 6938 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 373:
+#line 2371 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ }
+#line 6947 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 374:
+#line 2375 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ }
+#line 6956 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 375:
+#line 2379 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate())
+ (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
+ (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode);
+ }
+#line 6966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 376:
+#line 2387 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 377:
+#line 2388 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 6978 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 378:
+#line 2392 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 6986 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 379:
+#line 2395 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ --parseContext.controlFlowNestingLevel;
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 6995 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 380:
+#line 2399 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.push();
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 7005 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 381:
+#line 2404 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 7016 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 382:
+#line 2413 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ }
+#line 7024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 383:
+#line 2416 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate())
+ (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
+ (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode);
+ }
+#line 7034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 384:
+#line 2424 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode));
+ if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase ||
+ (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence(0, (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case
+ }
+ }
+#line 7047 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 385:
+#line 2432 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase ||
+ (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) {
+ parseContext.wrapupSwitchSubsequence((yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0, (yyvsp[0].interm.intermNode));
+ (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case
+ } else
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode));
+ }
+#line 7060 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 386:
+#line 2443 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = 0; }
+#line 7066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 387:
+#line 2444 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); }
+#line 7072 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 388:
+#line 2448 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode));
+ (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc);
+ }
+#line 7081 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 389:
+#line 2455 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode);
+ (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode);
+ }
+#line 7090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 390:
+#line 2459 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode);
+ (yyval.interm.nodePair).node2 = 0;
+ }
+#line 7099 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 391:
+#line 2467 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode));
+ }
+#line 7108 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 392:
+#line 2471 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type));
+
+ TType type((yyvsp[-3].interm.type));
+ TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode));
+ if (initNode)
+ (yyval.interm.intermTypedNode) = initNode->getAsTyped();
+ else
+ (yyval.interm.intermTypedNode) = 0;
+ }
+#line 7123 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 393:
+#line 2484 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // start new switch sequence on the switch stack
+ ++parseContext.controlFlowNestingLevel;
+ ++parseContext.statementNestingLevel;
+ parseContext.switchSequenceStack.push_back(new TIntermSequence);
+ parseContext.switchLevel.push_back(parseContext.statementNestingLevel);
+ parseContext.symbolTable.push();
+ }
+#line 7136 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 394:
+#line 2492 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0);
+ delete parseContext.switchSequenceStack.back();
+ parseContext.switchSequenceStack.pop_back();
+ parseContext.switchLevel.pop_back();
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 7150 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 395:
+#line 2504 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ }
+#line 7158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 396:
+#line 2507 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 7166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 397:
+#line 2513 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error((yyvsp[-2].lex).loc, "cannot appear outside switch statement", "case", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error((yyvsp[-2].lex).loc, "cannot be nested inside control flow", "case", "");
+ else {
+ parseContext.constantValueCheck((yyvsp[-1].interm.intermTypedNode), "case");
+ parseContext.integerCheck((yyvsp[-1].interm.intermTypedNode), "case");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc);
+ }
+ }
+#line 7183 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 398:
+#line 2525 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = 0;
+ if (parseContext.switchLevel.size() == 0)
+ parseContext.error((yyvsp[-1].lex).loc, "cannot appear outside switch statement", "default", "");
+ else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)
+ parseContext.error((yyvsp[-1].lex).loc, "cannot be nested inside control flow", "default", "");
+ else
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc);
+ }
+#line 7197 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 399:
+#line 2537 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", "");
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 7210 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 400:
+#line 2545 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 7222 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 401:
+#line 2552 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 7232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 402:
+#line 2557 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (! parseContext.limits.whileLoops)
+ parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", "");
+
+ parseContext.boolCheck((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode));
+
+ (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[-5].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, false, (yyvsp[-4].lex).loc);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 7248 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 403:
+#line 2568 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.push();
+ ++parseContext.loopNestingLevel;
+ ++parseContext.statementNestingLevel;
+ ++parseContext.controlFlowNestingLevel;
+ }
+#line 7259 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 404:
+#line 2574 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc);
+ TIntermLoop* forLoop = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[-2].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[-2].interm.nodePair).node2), true, (yyvsp[-6].lex).loc);
+ if (! parseContext.limits.nonInductiveForLoops)
+ parseContext.inductiveLoopCheck((yyvsp[-6].lex).loc, (yyvsp[-3].interm.intermNode), forLoop);
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyval.interm.intermNode), forLoop, (yyvsp[-6].lex).loc);
+ (yyval.interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
+ --parseContext.loopNestingLevel;
+ --parseContext.statementNestingLevel;
+ --parseContext.controlFlowNestingLevel;
+ }
+#line 7276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 405:
+#line 2589 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 7284 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 406:
+#line 2592 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 7292 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 407:
+#line 2598 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 7300 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 408:
+#line 2601 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermTypedNode) = 0;
+ }
+#line 7308 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 409:
+#line 2607 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode);
+ (yyval.interm.nodePair).node2 = 0;
+ }
+#line 7317 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 410:
+#line 2611 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode);
+ (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode);
+ }
+#line 7326 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 411:
+#line 2618 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (parseContext.loopNestingLevel <= 0)
+ parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc);
+ }
+#line 7336 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 412:
+#line 2623 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
+ parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc);
+ }
+#line 7346 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 413:
+#line 2628 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc);
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
+ parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", "");
+ if (parseContext.inMain)
+ parseContext.postMainReturn = true;
+ }
+#line 7358 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 414:
+#line 2635 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.functionReturnsValue = true;
+ if (parseContext.currentFunctionType->getBasicType() == EbtVoid) {
+ parseContext.error((yyvsp[-2].lex).loc, "void function cannot return a value", "return", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-2].lex).loc);
+ } else if (*(parseContext.currentFunctionType) != (yyvsp[-1].interm.intermTypedNode)->getType()) {
+ TIntermTyped* converted = parseContext.intermediate.addConversion(EOpReturn, *parseContext.currentFunctionType, (yyvsp[-1].interm.intermTypedNode));
+ if (converted) {
+ if (parseContext.version < 420)
+ parseContext.warn((yyvsp[-2].lex).loc, "type conversion on return values was not explicitly allowed until version 420", "return", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, converted, (yyvsp[-2].lex).loc);
+ } else {
+ parseContext.error((yyvsp[-2].lex).loc, "type does not match, or is not convertible to, the function's return type", "return", "");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc);
+ }
+ } else
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc);
+ }
+#line 7381 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 415:
+#line 2653 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard");
+ (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc);
+ }
+#line 7390 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 416:
+#line 2662 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ parseContext.intermediate.setTreeRoot((yyval.interm.intermNode));
+ }
+#line 7399 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 417:
+#line 2666 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode));
+ parseContext.intermediate.setTreeRoot((yyval.interm.intermNode));
+ }
+#line 7408 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 418:
+#line 2673 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 7416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 419:
+#line 2676 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+ }
+#line 7424 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 420:
+#line 2682 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */);
+ (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function);
+ }
+#line 7433 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+ case 421:
+#line 2686 "MachineIndependent/glslang.y" /* yacc.c:1646 */
+ {
+ // May be best done as post process phase on intermediate code
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
+ parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str());
+ parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
+ (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode));
+ parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc);
+ (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ (yyval.interm.intermNode)->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
+ (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+ (yyval.interm.intermNode)->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable);
+ }
+#line 7453 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ break;
+
+
+#line 7457 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (pParseContext, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (pParseContext, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, pParseContext);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, pParseContext);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (pParseContext, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, pParseContext);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, pParseContext);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ return yyresult;
+}
+#line 2703 "MachineIndependent/glslang.y" /* yacc.c:1906 */
+
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h
new file mode 100644
index 00000000000..e7d8fae862e
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h
@@ -0,0 +1,369 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ ATTRIBUTE = 258,
+ VARYING = 259,
+ CONST = 260,
+ BOOL = 261,
+ FLOAT = 262,
+ DOUBLE = 263,
+ INT = 264,
+ UINT = 265,
+ INT64_T = 266,
+ UINT64_T = 267,
+ BREAK = 268,
+ CONTINUE = 269,
+ DO = 270,
+ ELSE = 271,
+ FOR = 272,
+ IF = 273,
+ DISCARD = 274,
+ RETURN = 275,
+ SWITCH = 276,
+ CASE = 277,
+ DEFAULT = 278,
+ SUBROUTINE = 279,
+ BVEC2 = 280,
+ BVEC3 = 281,
+ BVEC4 = 282,
+ IVEC2 = 283,
+ IVEC3 = 284,
+ IVEC4 = 285,
+ I64VEC2 = 286,
+ I64VEC3 = 287,
+ I64VEC4 = 288,
+ UVEC2 = 289,
+ UVEC3 = 290,
+ UVEC4 = 291,
+ U64VEC2 = 292,
+ U64VEC3 = 293,
+ U64VEC4 = 294,
+ VEC2 = 295,
+ VEC3 = 296,
+ VEC4 = 297,
+ MAT2 = 298,
+ MAT3 = 299,
+ MAT4 = 300,
+ CENTROID = 301,
+ IN = 302,
+ OUT = 303,
+ INOUT = 304,
+ UNIFORM = 305,
+ PATCH = 306,
+ SAMPLE = 307,
+ BUFFER = 308,
+ SHARED = 309,
+ COHERENT = 310,
+ VOLATILE = 311,
+ RESTRICT = 312,
+ READONLY = 313,
+ WRITEONLY = 314,
+ DVEC2 = 315,
+ DVEC3 = 316,
+ DVEC4 = 317,
+ DMAT2 = 318,
+ DMAT3 = 319,
+ DMAT4 = 320,
+ NOPERSPECTIVE = 321,
+ FLAT = 322,
+ SMOOTH = 323,
+ LAYOUT = 324,
+ MAT2X2 = 325,
+ MAT2X3 = 326,
+ MAT2X4 = 327,
+ MAT3X2 = 328,
+ MAT3X3 = 329,
+ MAT3X4 = 330,
+ MAT4X2 = 331,
+ MAT4X3 = 332,
+ MAT4X4 = 333,
+ DMAT2X2 = 334,
+ DMAT2X3 = 335,
+ DMAT2X4 = 336,
+ DMAT3X2 = 337,
+ DMAT3X3 = 338,
+ DMAT3X4 = 339,
+ DMAT4X2 = 340,
+ DMAT4X3 = 341,
+ DMAT4X4 = 342,
+ ATOMIC_UINT = 343,
+ SAMPLER1D = 344,
+ SAMPLER2D = 345,
+ SAMPLER3D = 346,
+ SAMPLERCUBE = 347,
+ SAMPLER1DSHADOW = 348,
+ SAMPLER2DSHADOW = 349,
+ SAMPLERCUBESHADOW = 350,
+ SAMPLER1DARRAY = 351,
+ SAMPLER2DARRAY = 352,
+ SAMPLER1DARRAYSHADOW = 353,
+ SAMPLER2DARRAYSHADOW = 354,
+ ISAMPLER1D = 355,
+ ISAMPLER2D = 356,
+ ISAMPLER3D = 357,
+ ISAMPLERCUBE = 358,
+ ISAMPLER1DARRAY = 359,
+ ISAMPLER2DARRAY = 360,
+ USAMPLER1D = 361,
+ USAMPLER2D = 362,
+ USAMPLER3D = 363,
+ USAMPLERCUBE = 364,
+ USAMPLER1DARRAY = 365,
+ USAMPLER2DARRAY = 366,
+ SAMPLER2DRECT = 367,
+ SAMPLER2DRECTSHADOW = 368,
+ ISAMPLER2DRECT = 369,
+ USAMPLER2DRECT = 370,
+ SAMPLERBUFFER = 371,
+ ISAMPLERBUFFER = 372,
+ USAMPLERBUFFER = 373,
+ SAMPLERCUBEARRAY = 374,
+ SAMPLERCUBEARRAYSHADOW = 375,
+ ISAMPLERCUBEARRAY = 376,
+ USAMPLERCUBEARRAY = 377,
+ SAMPLER2DMS = 378,
+ ISAMPLER2DMS = 379,
+ USAMPLER2DMS = 380,
+ SAMPLER2DMSARRAY = 381,
+ ISAMPLER2DMSARRAY = 382,
+ USAMPLER2DMSARRAY = 383,
+ SAMPLEREXTERNALOES = 384,
+ SAMPLER = 385,
+ SAMPLERSHADOW = 386,
+ TEXTURE1D = 387,
+ TEXTURE2D = 388,
+ TEXTURE3D = 389,
+ TEXTURECUBE = 390,
+ TEXTURE1DARRAY = 391,
+ TEXTURE2DARRAY = 392,
+ ITEXTURE1D = 393,
+ ITEXTURE2D = 394,
+ ITEXTURE3D = 395,
+ ITEXTURECUBE = 396,
+ ITEXTURE1DARRAY = 397,
+ ITEXTURE2DARRAY = 398,
+ UTEXTURE1D = 399,
+ UTEXTURE2D = 400,
+ UTEXTURE3D = 401,
+ UTEXTURECUBE = 402,
+ UTEXTURE1DARRAY = 403,
+ UTEXTURE2DARRAY = 404,
+ TEXTURE2DRECT = 405,
+ ITEXTURE2DRECT = 406,
+ UTEXTURE2DRECT = 407,
+ TEXTUREBUFFER = 408,
+ ITEXTUREBUFFER = 409,
+ UTEXTUREBUFFER = 410,
+ TEXTURECUBEARRAY = 411,
+ ITEXTURECUBEARRAY = 412,
+ UTEXTURECUBEARRAY = 413,
+ TEXTURE2DMS = 414,
+ ITEXTURE2DMS = 415,
+ UTEXTURE2DMS = 416,
+ TEXTURE2DMSARRAY = 417,
+ ITEXTURE2DMSARRAY = 418,
+ UTEXTURE2DMSARRAY = 419,
+ SUBPASSINPUT = 420,
+ SUBPASSINPUTMS = 421,
+ ISUBPASSINPUT = 422,
+ ISUBPASSINPUTMS = 423,
+ USUBPASSINPUT = 424,
+ USUBPASSINPUTMS = 425,
+ IMAGE1D = 426,
+ IIMAGE1D = 427,
+ UIMAGE1D = 428,
+ IMAGE2D = 429,
+ IIMAGE2D = 430,
+ UIMAGE2D = 431,
+ IMAGE3D = 432,
+ IIMAGE3D = 433,
+ UIMAGE3D = 434,
+ IMAGE2DRECT = 435,
+ IIMAGE2DRECT = 436,
+ UIMAGE2DRECT = 437,
+ IMAGECUBE = 438,
+ IIMAGECUBE = 439,
+ UIMAGECUBE = 440,
+ IMAGEBUFFER = 441,
+ IIMAGEBUFFER = 442,
+ UIMAGEBUFFER = 443,
+ IMAGE1DARRAY = 444,
+ IIMAGE1DARRAY = 445,
+ UIMAGE1DARRAY = 446,
+ IMAGE2DARRAY = 447,
+ IIMAGE2DARRAY = 448,
+ UIMAGE2DARRAY = 449,
+ IMAGECUBEARRAY = 450,
+ IIMAGECUBEARRAY = 451,
+ UIMAGECUBEARRAY = 452,
+ IMAGE2DMS = 453,
+ IIMAGE2DMS = 454,
+ UIMAGE2DMS = 455,
+ IMAGE2DMSARRAY = 456,
+ IIMAGE2DMSARRAY = 457,
+ UIMAGE2DMSARRAY = 458,
+ STRUCT = 459,
+ VOID = 460,
+ WHILE = 461,
+ IDENTIFIER = 462,
+ TYPE_NAME = 463,
+ FLOATCONSTANT = 464,
+ DOUBLECONSTANT = 465,
+ INTCONSTANT = 466,
+ UINTCONSTANT = 467,
+ INT64CONSTANT = 468,
+ UINT64CONSTANT = 469,
+ BOOLCONSTANT = 470,
+ LEFT_OP = 471,
+ RIGHT_OP = 472,
+ INC_OP = 473,
+ DEC_OP = 474,
+ LE_OP = 475,
+ GE_OP = 476,
+ EQ_OP = 477,
+ NE_OP = 478,
+ AND_OP = 479,
+ OR_OP = 480,
+ XOR_OP = 481,
+ MUL_ASSIGN = 482,
+ DIV_ASSIGN = 483,
+ ADD_ASSIGN = 484,
+ MOD_ASSIGN = 485,
+ LEFT_ASSIGN = 486,
+ RIGHT_ASSIGN = 487,
+ AND_ASSIGN = 488,
+ XOR_ASSIGN = 489,
+ OR_ASSIGN = 490,
+ SUB_ASSIGN = 491,
+ LEFT_PAREN = 492,
+ RIGHT_PAREN = 493,
+ LEFT_BRACKET = 494,
+ RIGHT_BRACKET = 495,
+ LEFT_BRACE = 496,
+ RIGHT_BRACE = 497,
+ DOT = 498,
+ COMMA = 499,
+ COLON = 500,
+ EQUAL = 501,
+ SEMICOLON = 502,
+ BANG = 503,
+ DASH = 504,
+ TILDE = 505,
+ PLUS = 506,
+ STAR = 507,
+ SLASH = 508,
+ PERCENT = 509,
+ LEFT_ANGLE = 510,
+ RIGHT_ANGLE = 511,
+ VERTICAL_BAR = 512,
+ CARET = 513,
+ AMPERSAND = 514,
+ QUESTION = 515,
+ INVARIANT = 516,
+ PRECISE = 517,
+ HIGH_PRECISION = 518,
+ MEDIUM_PRECISION = 519,
+ LOW_PRECISION = 520,
+ PRECISION = 521,
+ PACKED = 522,
+ RESOURCE = 523,
+ SUPERP = 524
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 66 "MachineIndependent/glslang.y" /* yacc.c:1909 */
+
+ struct {
+ glslang::TSourceLoc loc;
+ union {
+ glslang::TString *string;
+ int i;
+ unsigned int u;
+ long long i64;
+ unsigned long long u64;
+ bool b;
+ double d;
+ };
+ glslang::TSymbol* symbol;
+ } lex;
+ struct {
+ glslang::TSourceLoc loc;
+ glslang::TOperator op;
+ union {
+ TIntermNode* intermNode;
+ glslang::TIntermNodePair nodePair;
+ glslang::TIntermTyped* intermTypedNode;
+ };
+ union {
+ glslang::TPublicType type;
+ glslang::TFunction* function;
+ glslang::TParameter param;
+ glslang::TTypeLoc typeLine;
+ glslang::TTypeList* typeList;
+ glslang::TArraySizes* arraySizes;
+ glslang::TIdentifierList* identifierList;
+ };
+ } interm;
+
+#line 358 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int yyparse (glslang::TParseContext* pParseContext);
+
+#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp
new file mode 100644
index 00000000000..a5a6f2ce0e0
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp
@@ -0,0 +1,864 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2012-2016 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "localintermediate.h"
+#include "../Include/InfoSink.h"
+
+#ifdef _MSC_VER
+#include <float.h>
+#elif defined __ANDROID__ || defined __linux__ || __MINGW32__ || __MINGW64__
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+namespace {
+
+bool is_positive_infinity(double x) {
+#ifdef _MSC_VER
+ return _fpclass(x) == _FPCLASS_PINF;
+#elif defined __ANDROID__ || defined __linux__ || __MINGW32__ || __MINGW64__
+ return std::isinf(x) && (x >= 0);
+#else
+ return isinf(x) && (x >= 0);
+#endif
+}
+
+}
+
+namespace glslang {
+
+//
+// Two purposes:
+// 1. Show an example of how to iterate tree. Functions can
+// also directly call Traverse() on children themselves to
+// have finer grained control over the process than shown here.
+// See the last function for how to get started.
+// 2. Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+ TOutputTraverser(TInfoSink& i) : infoSink(i) { }
+
+ virtual bool visitBinary(TVisit, TIntermBinary* node);
+ virtual bool visitUnary(TVisit, TIntermUnary* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+ virtual bool visitSelection(TVisit, TIntermSelection* node);
+ virtual void visitConstantUnion(TIntermConstantUnion* node);
+ virtual void visitSymbol(TIntermSymbol* node);
+ virtual bool visitLoop(TVisit, TIntermLoop* node);
+ virtual bool visitBranch(TVisit, TIntermBranch* node);
+ virtual bool visitSwitch(TVisit, TIntermSwitch* node);
+
+ TInfoSink& infoSink;
+protected:
+ TOutputTraverser(TOutputTraverser&);
+ TOutputTraverser& operator=(TOutputTraverser&);
+};
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+static void OutputTreeText(TInfoSink& infoSink, const TIntermNode* node, const int depth)
+{
+ int i;
+
+ infoSink.debug << node->getLoc().string << ":";
+ if (node->getLoc().line)
+ infoSink.debug << node->getLoc().line;
+ else
+ infoSink.debug << "? ";
+
+ for (i = 0; i < depth; ++i)
+ infoSink.debug << " ";
+}
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpAssign: out.debug << "move second child to first child"; break;
+ case EOpAddAssign: out.debug << "add second child into first child"; break;
+ case EOpSubAssign: out.debug << "subtract second child into first child"; break;
+ case EOpMulAssign: out.debug << "multiply second child into first child"; break;
+ case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break;
+ case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break;
+ case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpDivAssign: out.debug << "divide second child into first child"; break;
+ case EOpModAssign: out.debug << "mod second child into first child"; break;
+ case EOpAndAssign: out.debug << "and second child into first child"; break;
+ case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break;
+ case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break;
+ case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break;
+ case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break;
+
+ case EOpIndexDirect: out.debug << "direct index"; break;
+ case EOpIndexIndirect: out.debug << "indirect index"; break;
+ case EOpIndexDirectStruct:
+ out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName();
+ out.debug << ": direct index for structure"; break;
+ case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
+
+ case EOpAdd: out.debug << "add"; break;
+ case EOpSub: out.debug << "subtract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+ case EOpDiv: out.debug << "divide"; break;
+ case EOpMod: out.debug << "mod"; break;
+ case EOpRightShift: out.debug << "right-shift"; break;
+ case EOpLeftShift: out.debug << "left-shift"; break;
+ case EOpAnd: out.debug << "bitwise and"; break;
+ case EOpInclusiveOr: out.debug << "inclusive-or"; break;
+ case EOpExclusiveOr: out.debug << "exclusive-or"; break;
+ case EOpEqual: out.debug << "Compare Equal"; break;
+ case EOpNotEqual: out.debug << "Compare Not Equal"; break;
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+
+ case EOpVectorTimesScalar: out.debug << "vector-scale"; break;
+ case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break;
+ case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break;
+ case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break;
+ case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break;
+
+ case EOpLogicalOr: out.debug << "logical-or"; break;
+ case EOpLogicalXor: out.debug << "logical-xor"; break;
+ case EOpLogicalAnd: out.debug << "logical-and"; break;
+ default: out.debug << "<unknown op>";
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpNegative: out.debug << "Negate value"; break;
+ case EOpVectorLogicalNot:
+ case EOpLogicalNot: out.debug << "Negate conditional"; break;
+ case EOpBitwiseNot: out.debug << "Bitwise not"; break;
+
+ case EOpPostIncrement: out.debug << "Post-Increment"; break;
+ case EOpPostDecrement: out.debug << "Post-Decrement"; break;
+ case EOpPreIncrement: out.debug << "Pre-Increment"; break;
+ case EOpPreDecrement: out.debug << "Pre-Decrement"; break;
+
+ case EOpConvIntToBool: out.debug << "Convert int to bool"; break;
+ case EOpConvUintToBool: out.debug << "Convert uint to bool"; break;
+ case EOpConvFloatToBool: out.debug << "Convert float to bool"; break;
+ case EOpConvDoubleToBool: out.debug << "Convert double to bool"; break;
+ case EOpConvInt64ToBool: out.debug << "Convert int64 to bool"; break;
+ case EOpConvUint64ToBool: out.debug << "Convert uint64 to bool"; break;
+ case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
+ case EOpConvUintToFloat: out.debug << "Convert uint to float"; break;
+ case EOpConvDoubleToFloat: out.debug << "Convert double to float"; break;
+ case EOpConvInt64ToFloat: out.debug << "Convert int64 to float"; break;
+ case EOpConvUint64ToFloat: out.debug << "Convert uint64 to float"; break;
+ case EOpConvBoolToFloat: out.debug << "Convert bool to float"; break;
+ case EOpConvUintToInt: out.debug << "Convert uint to int"; break;
+ case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
+ case EOpConvDoubleToInt: out.debug << "Convert double to int"; break;
+ case EOpConvBoolToInt: out.debug << "Convert bool to int"; break;
+ case EOpConvInt64ToInt: out.debug << "Convert int64 to int"; break;
+ case EOpConvUint64ToInt: out.debug << "Convert uint64 to int"; break;
+ case EOpConvIntToUint: out.debug << "Convert int to uint"; break;
+ case EOpConvFloatToUint: out.debug << "Convert float to uint"; break;
+ case EOpConvDoubleToUint: out.debug << "Convert double to uint"; break;
+ case EOpConvBoolToUint: out.debug << "Convert bool to uint"; break;
+ case EOpConvInt64ToUint: out.debug << "Convert int64 to uint"; break;
+ case EOpConvUint64ToUint: out.debug << "Convert uint64 to uint"; break;
+ case EOpConvIntToDouble: out.debug << "Convert int to double"; break;
+ case EOpConvUintToDouble: out.debug << "Convert uint to double"; break;
+ case EOpConvFloatToDouble: out.debug << "Convert float to double"; break;
+ case EOpConvBoolToDouble: out.debug << "Convert bool to double"; break;
+ case EOpConvInt64ToDouble: out.debug << "Convert int64 to double"; break;
+ case EOpConvUint64ToDouble: out.debug << "Convert uint64 to double"; break;
+ case EOpConvBoolToInt64: out.debug << "Convert bool to int64"; break;
+ case EOpConvIntToInt64: out.debug << "Convert int to int64"; break;
+ case EOpConvUintToInt64: out.debug << "Convert uint to int64"; break;
+ case EOpConvFloatToInt64: out.debug << "Convert float to int64"; break;
+ case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break;
+ case EOpConvUint64ToInt64: out.debug << "Convert uint64 to int64"; break;
+ case EOpConvBoolToUint64: out.debug << "Convert bool to uint64"; break;
+ case EOpConvIntToUint64: out.debug << "Convert int to uint64"; break;
+ case EOpConvUintToUint64: out.debug << "Convert uint to uint64"; break;
+ case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break;
+ case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
+ case EOpConvInt64ToUint64: out.debug << "Convert uint64 to uint64"; break;
+
+ case EOpRadians: out.debug << "radians"; break;
+ case EOpDegrees: out.debug << "degrees"; break;
+ case EOpSin: out.debug << "sine"; break;
+ case EOpCos: out.debug << "cosine"; break;
+ case EOpTan: out.debug << "tangent"; break;
+ case EOpAsin: out.debug << "arc sine"; break;
+ case EOpAcos: out.debug << "arc cosine"; break;
+ case EOpAtan: out.debug << "arc tangent"; break;
+ case EOpSinh: out.debug << "hyp. sine"; break;
+ case EOpCosh: out.debug << "hyp. cosine"; break;
+ case EOpTanh: out.debug << "hyp. tangent"; break;
+ case EOpAsinh: out.debug << "arc hyp. sine"; break;
+ case EOpAcosh: out.debug << "arc hyp. cosine"; break;
+ case EOpAtanh: out.debug << "arc hyp. tangent"; break;
+
+ case EOpExp: out.debug << "exp"; break;
+ case EOpLog: out.debug << "log"; break;
+ case EOpExp2: out.debug << "exp2"; break;
+ case EOpLog2: out.debug << "log2"; break;
+ case EOpSqrt: out.debug << "sqrt"; break;
+ case EOpInverseSqrt: out.debug << "inverse sqrt"; break;
+
+ case EOpAbs: out.debug << "Absolute value"; break;
+ case EOpSign: out.debug << "Sign"; break;
+ case EOpFloor: out.debug << "Floor"; break;
+ case EOpTrunc: out.debug << "trunc"; break;
+ case EOpRound: out.debug << "round"; break;
+ case EOpRoundEven: out.debug << "roundEven"; break;
+ case EOpCeil: out.debug << "Ceiling"; break;
+ case EOpFract: out.debug << "Fraction"; break;
+
+ case EOpIsNan: out.debug << "isnan"; break;
+ case EOpIsInf: out.debug << "isinf"; break;
+
+ case EOpFloatBitsToInt: out.debug << "floatBitsToInt"; break;
+ case EOpFloatBitsToUint:out.debug << "floatBitsToUint"; break;
+ case EOpIntBitsToFloat: out.debug << "intBitsToFloat"; break;
+ case EOpUintBitsToFloat:out.debug << "uintBitsToFloat"; break;
+ case EOpDoubleBitsToInt64: out.debug << "doubleBitsToInt64"; break;
+ case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
+ case EOpInt64BitsToDouble: out.debug << "int64BitsToDouble"; break;
+ case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
+ case EOpPackSnorm2x16: out.debug << "packSnorm2x16"; break;
+ case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16"; break;
+ case EOpPackUnorm2x16: out.debug << "packUnorm2x16"; break;
+ case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16"; break;
+ case EOpPackHalf2x16: out.debug << "packHalf2x16"; break;
+ case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16"; break;
+
+ case EOpPackSnorm4x8: out.debug << "PackSnorm4x8"; break;
+ case EOpUnpackSnorm4x8: out.debug << "UnpackSnorm4x8"; break;
+ case EOpPackUnorm4x8: out.debug << "PackUnorm4x8"; break;
+ case EOpUnpackUnorm4x8: out.debug << "UnpackUnorm4x8"; break;
+ case EOpPackDouble2x32: out.debug << "PackDouble2x32"; break;
+ case EOpUnpackDouble2x32: out.debug << "UnpackDouble2x32"; break;
+
+ case EOpPackInt2x32: out.debug << "packInt2x32"; break;
+ case EOpUnpackInt2x32: out.debug << "unpackInt2x32"; break;
+ case EOpPackUint2x32: out.debug << "packUint2x32"; break;
+ case EOpUnpackUint2x32: out.debug << "unpackUint2x32"; break;
+
+ case EOpLength: out.debug << "length"; break;
+ case EOpNormalize: out.debug << "normalize"; break;
+ case EOpDPdx: out.debug << "dPdx"; break;
+ case EOpDPdy: out.debug << "dPdy"; break;
+ case EOpFwidth: out.debug << "fwidth"; break;
+ case EOpDPdxFine: out.debug << "dPdxFine"; break;
+ case EOpDPdyFine: out.debug << "dPdyFine"; break;
+ case EOpFwidthFine: out.debug << "fwidthFine"; break;
+ case EOpDPdxCoarse: out.debug << "dPdxCoarse"; break;
+ case EOpDPdyCoarse: out.debug << "dPdyCoarse"; break;
+ case EOpFwidthCoarse: out.debug << "fwidthCoarse"; break;
+
+ case EOpInterpolateAtCentroid: out.debug << "interpolateAtCentroid"; break;
+
+ case EOpDeterminant: out.debug << "determinant"; break;
+ case EOpMatrixInverse: out.debug << "inverse"; break;
+ case EOpTranspose: out.debug << "transpose"; break;
+
+ case EOpAny: out.debug << "any"; break;
+ case EOpAll: out.debug << "all"; break;
+
+ case EOpArrayLength: out.debug << "array length"; break;
+
+ case EOpEmitStreamVertex: out.debug << "EmitStreamVertex"; break;
+ case EOpEndStreamPrimitive: out.debug << "EndStreamPrimitive"; break;
+
+ case EOpAtomicCounterIncrement: out.debug << "AtomicCounterIncrement";break;
+ case EOpAtomicCounterDecrement: out.debug << "AtomicCounterDecrement";break;
+ case EOpAtomicCounter: out.debug << "AtomicCounter"; break;
+
+ case EOpTextureQuerySize: out.debug << "textureSize"; break;
+ case EOpTextureQueryLod: out.debug << "textureQueryLod"; break;
+ case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break;
+ case EOpTextureQuerySamples: out.debug << "textureSamples"; break;
+ case EOpImageQuerySize: out.debug << "imageQuerySize"; break;
+ case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break;
+ case EOpImageLoad: out.debug << "imageLoad"; break;
+
+ case EOpBitFieldReverse: out.debug << "bitFieldReverse"; break;
+ case EOpBitCount: out.debug << "bitCount"; break;
+ case EOpFindLSB: out.debug << "findLSB"; break;
+ case EOpFindMSB: out.debug << "findMSB"; break;
+
+ case EOpNoise: out.debug << "noise"; break;
+
+ case EOpBallot: out.debug << "ballot"; break;
+ case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break;
+ case EOpAnyInvocation: out.debug << "anyInvocation"; break;
+ case EOpAllInvocations: out.debug << "allInvocations"; break;
+ case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break;
+
+ case EOpClip: out.debug << "clip"; break;
+ case EOpIsFinite: out.debug << "isfinite"; break;
+ case EOpLog10: out.debug << "log10"; break;
+ case EOpRcp: out.debug << "rcp"; break;
+ case EOpSaturate: out.debug << "saturate"; break;
+
+ default: out.debug.message(EPrefixError, "Bad unary op");
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ TInfoSink& out = infoSink;
+
+ if (node->getOp() == EOpNull) {
+ out.debug.message(EPrefixError, "node is still EOpNull!");
+ return true;
+ }
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpSequence: out.debug << "Sequence\n"; return true;
+ case EOpLinkerObjects: out.debug << "Linker Objects\n"; return true;
+ case EOpComma: out.debug << "Comma"; break;
+ case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
+ case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
+ case EOpParameters: out.debug << "Function Parameters: "; break;
+
+ case EOpConstructFloat: out.debug << "Construct float"; break;
+ case EOpConstructDouble:out.debug << "Construct double"; break;
+ case EOpConstructVec2: out.debug << "Construct vec2"; break;
+ case EOpConstructVec3: out.debug << "Construct vec3"; break;
+ case EOpConstructVec4: out.debug << "Construct vec4"; break;
+ case EOpConstructBool: out.debug << "Construct bool"; break;
+ case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
+ case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
+ case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+ case EOpConstructInt: out.debug << "Construct int"; break;
+ case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
+ case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
+ case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+ case EOpConstructUint: out.debug << "Construct uint"; break;
+ case EOpConstructUVec2: out.debug << "Construct uvec2"; break;
+ case EOpConstructUVec3: out.debug << "Construct uvec3"; break;
+ case EOpConstructUVec4: out.debug << "Construct uvec4"; break;
+ case EOpConstructInt64: out.debug << "Construct int64_t"; break;
+ case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break;
+ case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break;
+ case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break;
+ case EOpConstructUint64: out.debug << "Construct uint64_t"; break;
+ case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
+ case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
+ case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
+ case EOpConstructMat2x2: out.debug << "Construct mat2"; break;
+ case EOpConstructMat2x3: out.debug << "Construct mat2x3"; break;
+ case EOpConstructMat2x4: out.debug << "Construct mat2x4"; break;
+ case EOpConstructMat3x2: out.debug << "Construct mat3x2"; break;
+ case EOpConstructMat3x3: out.debug << "Construct mat3"; break;
+ case EOpConstructMat3x4: out.debug << "Construct mat3x4"; break;
+ case EOpConstructMat4x2: out.debug << "Construct mat4x2"; break;
+ case EOpConstructMat4x3: out.debug << "Construct mat4x3"; break;
+ case EOpConstructMat4x4: out.debug << "Construct mat4"; break;
+ case EOpConstructDMat2x2: out.debug << "Construct dmat2"; break;
+ case EOpConstructDMat2x3: out.debug << "Construct dmat2x3"; break;
+ case EOpConstructDMat2x4: out.debug << "Construct dmat2x4"; break;
+ case EOpConstructDMat3x2: out.debug << "Construct dmat3x2"; break;
+ case EOpConstructDMat3x3: out.debug << "Construct dmat3"; break;
+ case EOpConstructDMat3x4: out.debug << "Construct dmat3x4"; break;
+ case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break;
+ case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break;
+ case EOpConstructDMat4x4: out.debug << "Construct dmat4"; break;
+ case EOpConstructStruct: out.debug << "Construct structure"; break;
+ case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
+
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+ case EOpVectorEqual: out.debug << "Equal"; break;
+ case EOpVectorNotEqual: out.debug << "NotEqual"; break;
+
+ case EOpMod: out.debug << "mod"; break;
+ case EOpModf: out.debug << "modf"; break;
+ case EOpPow: out.debug << "pow"; break;
+
+ case EOpAtan: out.debug << "arc tangent"; break;
+
+ case EOpMin: out.debug << "min"; break;
+ case EOpMax: out.debug << "max"; break;
+ case EOpClamp: out.debug << "clamp"; break;
+ case EOpMix: out.debug << "mix"; break;
+ case EOpStep: out.debug << "step"; break;
+ case EOpSmoothStep: out.debug << "smoothstep"; break;
+
+ case EOpDistance: out.debug << "distance"; break;
+ case EOpDot: out.debug << "dot-product"; break;
+ case EOpCross: out.debug << "cross-product"; break;
+ case EOpFaceForward: out.debug << "face-forward"; break;
+ case EOpReflect: out.debug << "reflect"; break;
+ case EOpRefract: out.debug << "refract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+ case EOpOuterProduct: out.debug << "outer product"; break;
+
+ case EOpEmitVertex: out.debug << "EmitVertex"; break;
+ case EOpEndPrimitive: out.debug << "EndPrimitive"; break;
+
+ case EOpBarrier: out.debug << "Barrier"; break;
+ case EOpMemoryBarrier: out.debug << "MemoryBarrier"; break;
+ case EOpMemoryBarrierAtomicCounter: out.debug << "MemoryBarrierAtomicCounter"; break;
+ case EOpMemoryBarrierBuffer: out.debug << "MemoryBarrierBuffer"; break;
+ case EOpMemoryBarrierImage: out.debug << "MemoryBarrierImage"; break;
+ case EOpMemoryBarrierShared: out.debug << "MemoryBarrierShared"; break;
+ case EOpGroupMemoryBarrier: out.debug << "GroupMemoryBarrier"; break;
+
+ case EOpReadInvocation: out.debug << "readInvocation"; break;
+
+ case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
+ case EOpAtomicMin: out.debug << "AtomicMin"; break;
+ case EOpAtomicMax: out.debug << "AtomicMax"; break;
+ case EOpAtomicAnd: out.debug << "AtomicAnd"; break;
+ case EOpAtomicOr: out.debug << "AtomicOr"; break;
+ case EOpAtomicXor: out.debug << "AtomicXor"; break;
+ case EOpAtomicExchange: out.debug << "AtomicExchange"; break;
+ case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break;
+
+ case EOpImageQuerySize: out.debug << "imageQuerySize"; break;
+ case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break;
+ case EOpImageLoad: out.debug << "imageLoad"; break;
+ case EOpImageStore: out.debug << "imageStore"; break;
+ case EOpImageAtomicAdd: out.debug << "imageAtomicAdd"; break;
+ case EOpImageAtomicMin: out.debug << "imageAtomicMin"; break;
+ case EOpImageAtomicMax: out.debug << "imageAtomicMax"; break;
+ case EOpImageAtomicAnd: out.debug << "imageAtomicAnd"; break;
+ case EOpImageAtomicOr: out.debug << "imageAtomicOr"; break;
+ case EOpImageAtomicXor: out.debug << "imageAtomicXor"; break;
+ case EOpImageAtomicExchange: out.debug << "imageAtomicExchange"; break;
+ case EOpImageAtomicCompSwap: out.debug << "imageAtomicCompSwap"; break;
+
+ case EOpTextureQuerySize: out.debug << "textureSize"; break;
+ case EOpTextureQueryLod: out.debug << "textureQueryLod"; break;
+ case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break;
+ case EOpTextureQuerySamples: out.debug << "textureSamples"; break;
+ case EOpTexture: out.debug << "texture"; break;
+ case EOpTextureProj: out.debug << "textureProj"; break;
+ case EOpTextureLod: out.debug << "textureLod"; break;
+ case EOpTextureOffset: out.debug << "textureOffset"; break;
+ case EOpTextureFetch: out.debug << "textureFetch"; break;
+ case EOpTextureFetchOffset: out.debug << "textureFetchOffset"; break;
+ case EOpTextureProjOffset: out.debug << "textureProjOffset"; break;
+ case EOpTextureLodOffset: out.debug << "textureLodOffset"; break;
+ case EOpTextureProjLod: out.debug << "textureProjLod"; break;
+ case EOpTextureProjLodOffset: out.debug << "textureProjLodOffset"; break;
+ case EOpTextureGrad: out.debug << "textureGrad"; break;
+ case EOpTextureGradOffset: out.debug << "textureGradOffset"; break;
+ case EOpTextureProjGrad: out.debug << "textureProjGrad"; break;
+ case EOpTextureProjGradOffset: out.debug << "textureProjGradOffset"; break;
+ case EOpTextureGather: out.debug << "textureGather"; break;
+ case EOpTextureGatherOffset: out.debug << "textureGatherOffset"; break;
+ case EOpTextureGatherOffsets: out.debug << "textureGatherOffsets"; break;
+
+ case EOpAddCarry: out.debug << "addCarry"; break;
+ case EOpSubBorrow: out.debug << "subBorrow"; break;
+ case EOpUMulExtended: out.debug << "uMulExtended"; break;
+ case EOpIMulExtended: out.debug << "iMulExtended"; break;
+ case EOpBitfieldExtract: out.debug << "bitfieldExtract"; break;
+ case EOpBitfieldInsert: out.debug << "bitfieldInsert"; break;
+
+ case EOpFma: out.debug << "fma"; break;
+ case EOpFrexp: out.debug << "frexp"; break;
+ case EOpLdexp: out.debug << "ldexp"; break;
+
+ case EOpInterpolateAtSample: out.debug << "interpolateAtSample"; break;
+ case EOpInterpolateAtOffset: out.debug << "interpolateAtOffset"; break;
+
+ case EOpSinCos: out.debug << "sincos"; break;
+ case EOpGenMul: out.debug << "mul"; break;
+
+ default: out.debug.message(EPrefixError, "Bad aggregation op");
+ }
+
+ if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ out.debug << "Test condition and select";
+ out.debug << " (" << node->getCompleteString() << ")\n";
+
+ ++depth;
+
+ OutputTreeText(out, node, depth);
+ out.debug << "Condition\n";
+ node->getCondition()->traverse(this);
+
+ OutputTreeText(out, node, depth);
+ if (node->getTrueBlock()) {
+ out.debug << "true case\n";
+ node->getTrueBlock()->traverse(this);
+ } else
+ out.debug << "true case is null\n";
+
+ if (node->getFalseBlock()) {
+ OutputTreeText(out, node, depth);
+ out.debug << "false case\n";
+ node->getFalseBlock()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion, int depth)
+{
+ int size = node->getType().computeNumComponents();
+
+ for (int i = 0; i < size; i++) {
+ OutputTreeText(out, node, depth);
+ switch (constUnion[i].getType()) {
+ case EbtBool:
+ if (constUnion[i].getBConst())
+ out.debug << "true";
+ else
+ out.debug << "false";
+
+ out.debug << " (" << "const bool" << ")";
+
+ out.debug << "\n";
+ break;
+ case EbtFloat:
+ case EbtDouble:
+ {
+ const double value = constUnion[i].getDConst();
+ // Print infinity in a portable way, for test stability.
+ // Other cases may be needed in the future: negative infinity,
+ // and NaNs.
+ if (is_positive_infinity(value))
+ out.debug << "inf\n";
+ else {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%f", value);
+
+ out.debug << buf << "\n";
+ }
+ }
+ break;
+ case EbtInt:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtUint:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtInt64:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtUint64:
+ {
+ const int maxSize = 300;
+ char buf[maxSize];
+ snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ default:
+ out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
+ break;
+ }
+ }
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ OutputTreeText(infoSink, node, depth);
+ infoSink.debug << "Constant:\n";
+
+ OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
+}
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+ OutputTreeText(infoSink, node, depth);
+
+ infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n";
+
+ if (! node->getConstArray().empty())
+ OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
+ else if (node->getConstSubtree()) {
+ incrementDepth(node);
+ node->getConstSubtree()->traverse(this);
+ decrementDepth();
+ }
+}
+
+bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ out.debug << "Loop with condition ";
+ if (! node->testFirst())
+ out.debug << "not ";
+ out.debug << "tested first\n";
+
+ ++depth;
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getTest()) {
+ out.debug << "Loop Condition\n";
+ node->getTest()->traverse(this);
+ } else
+ out.debug << "No loop condition\n";
+
+ OutputTreeText(infoSink, node, depth);
+ if (node->getBody()) {
+ out.debug << "Loop Body\n";
+ node->getBody()->traverse(this);
+ } else
+ out.debug << "No loop body\n";
+
+ if (node->getTerminal()) {
+ OutputTreeText(infoSink, node, depth);
+ out.debug << "Loop Terminal Expression\n";
+ node->getTerminal()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getFlowOp()) {
+ case EOpKill: out.debug << "Branch: Kill"; break;
+ case EOpBreak: out.debug << "Branch: Break"; break;
+ case EOpContinue: out.debug << "Branch: Continue"; break;
+ case EOpReturn: out.debug << "Branch: Return"; break;
+ case EOpCase: out.debug << "case: "; break;
+ case EOpDefault: out.debug << "default: "; break;
+ default: out.debug << "Branch: Unknown Branch"; break;
+ }
+
+ if (node->getExpression()) {
+ out.debug << " with expression\n";
+ ++depth;
+ node->getExpression()->traverse(this);
+ --depth;
+ } else
+ out.debug << "\n";
+
+ return false;
+}
+
+bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
+{
+ TInfoSink& out = infoSink;
+
+ OutputTreeText(out, node, depth);
+ out.debug << "switch\n";
+
+ OutputTreeText(out, node, depth);
+ out.debug << "condition\n";
+ ++depth;
+ node->getCondition()->traverse(this);
+
+ --depth;
+ OutputTreeText(out, node, depth);
+ out.debug << "body\n";
+ ++depth;
+ node->getBody()->traverse(this);
+
+ --depth;
+
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+void TIntermediate::output(TInfoSink& infoSink, bool tree)
+{
+ infoSink.debug << "Shader version: " << version << "\n";
+ if (requestedExtensions.size() > 0) {
+ for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt)
+ infoSink.debug << "Requested " << *extIt << "\n";
+ }
+
+ if (xfbMode)
+ infoSink.debug << "in xfb mode\n";
+
+ switch (language) {
+ case EShLangVertex:
+ break;
+
+ case EShLangTessControl:
+ infoSink.debug << "vertices = " << vertices << "\n";
+ break;
+
+ case EShLangTessEvaluation:
+ infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
+ infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
+ infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
+ if (pointMode)
+ infoSink.debug << "using point mode\n";
+ break;
+
+ case EShLangGeometry:
+ infoSink.debug << "invocations = " << invocations << "\n";
+ infoSink.debug << "max_vertices = " << vertices << "\n";
+ infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
+ infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n";
+ break;
+
+ case EShLangFragment:
+ if (pixelCenterInteger)
+ infoSink.debug << "gl_FragCoord pixel center is integer\n";
+ if (originUpperLeft)
+ infoSink.debug << "gl_FragCoord origin is upper left\n";
+ if (earlyFragmentTests)
+ infoSink.debug << "using early_fragment_tests\n";
+ if (depthLayout != EldNone)
+ infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
+ if (blendEquations != 0) {
+ infoSink.debug << "using";
+ // blendEquations is a mask, decode it
+ for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
+ if (blendEquations & (1 << be))
+ infoSink.debug << " " << TQualifier::getBlendEquationString(be);
+ }
+ infoSink.debug << "\n";
+ }
+ break;
+
+ case EShLangCompute:
+ infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n";
+ {
+ if (localSizeSpecId[0] != TQualifier::layoutNotSet ||
+ localSizeSpecId[1] != TQualifier::layoutNotSet ||
+ localSizeSpecId[2] != TQualifier::layoutNotSet) {
+ infoSink.debug << "local_size ids = (" <<
+ localSizeSpecId[0] << ", " <<
+ localSizeSpecId[1] << ", " <<
+ localSizeSpecId[2] << ")\n";
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (treeRoot == 0 || ! tree)
+ return;
+
+ TOutputTraverser it(infoSink);
+
+ treeRoot->traverse(&it);
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/limits.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/limits.cpp
new file mode 100644
index 00000000000..49da930110d
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/limits.cpp
@@ -0,0 +1,198 @@
+//
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Do sub tree walks for
+// 1) inductive loop bodies to see if the inductive variable is modified
+// 2) array-index expressions to see if they are "constant-index-expression"
+//
+// These are per Appendix A of ES 2.0:
+//
+// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the
+// argument to a function out or inout parameter."
+//
+// "The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above"
+//
+// N.B.: assuming the last rule excludes function calls
+//
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
+//
+// The inductive loop-body traverser.
+//
+// Just look at things that might modify the loop index.
+//
+
+class TInductiveTraverser : public TIntermTraverser {
+public:
+ TInductiveTraverser(int id, TSymbolTable& st)
+ : loopId(id), symbolTable(st), bad(false) { }
+
+ virtual bool visitBinary(TVisit, TIntermBinary* node);
+ virtual bool visitUnary(TVisit, TIntermUnary* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+
+ int loopId; // unique ID of the symbol that's the loop inductive variable
+ TSymbolTable& symbolTable;
+ bool bad;
+ TSourceLoc badLoc;
+
+protected:
+ TInductiveTraverser(TInductiveTraverser&);
+ TInductiveTraverser& operator=(TInductiveTraverser&);
+};
+
+// check binary operations for those modifying the loop index
+bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
+{
+ if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
+ node->getLeft()->getAsSymbolNode()->getId() == loopId) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+
+ return true;
+}
+
+// check unary operations for those modifying the loop index
+bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
+{
+ if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
+ node->getOperand()->getAsSymbolNode()->getId() == loopId) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+
+ return true;
+}
+
+// check function calls for arguments modifying the loop index
+bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (node->getOp() == EOpFunctionCall) {
+ // see if an out or inout argument is the loop index
+ const TIntermSequence& args = node->getSequence();
+ for (int i = 0; i < (int)args.size(); ++i) {
+ if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) {
+ TSymbol* function = symbolTable.find(node->getName());
+ const TType* type = (*function->getAsFunction())[i].type;
+ if (type->getQualifier().storage == EvqOut ||
+ type->getQualifier().storage == EvqInOut) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//
+// External function to call for loop check.
+//
+void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
+{
+ TInductiveTraverser it(loopId, symbolTable);
+
+ if (body == nullptr)
+ return;
+
+ body->traverse(&it);
+
+ if (it.bad)
+ error(it.badLoc, "inductive loop index modified", "limitations", "");
+}
+
+//
+// The "constant-index-expression" tranverser.
+//
+// Just look at things that can form an index.
+//
+
+class TIndexTraverser : public TIntermTraverser {
+public:
+ TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
+ virtual void visitSymbol(TIntermSymbol* symbol);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+ const TIdSetType& inductiveLoopIds;
+ bool bad;
+ TSourceLoc badLoc;
+
+protected:
+ TIndexTraverser(TIndexTraverser&);
+ TIndexTraverser& operator=(TIndexTraverser&);
+};
+
+// make sure symbols are inductive-loop indexes
+void TIndexTraverser::visitSymbol(TIntermSymbol* symbol)
+{
+ if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) {
+ bad = true;
+ badLoc = symbol->getLoc();
+ }
+}
+
+// check for function calls, assuming they are bad; spec. doesn't really say
+bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (node->getOp() == EOpFunctionCall) {
+ bad = true;
+ badLoc = node->getLoc();
+ }
+
+ return true;
+}
+
+//
+// External function to call for loop check.
+//
+void TParseContext::constantIndexExpressionCheck(TIntermNode* index)
+{
+ TIndexTraverser it(inductiveLoopIds);
+
+ index->traverse(&it);
+
+ if (it.bad)
+ error(it.badLoc, "Non-constant-index-expression", "limitations", "");
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp
new file mode 100644
index 00000000000..1cda57d36e9
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp
@@ -0,0 +1,1050 @@
+//
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Do link-time merging and validation of intermediate representations.
+//
+// Basic model is that during compilation, each compilation unit (shader) is
+// compiled into one TIntermediate instance. Then, at link time, multiple
+// units for the same stage can be merged together, which can generate errors.
+// Then, after all merging, a single instance of TIntermediate represents
+// the whole stage. A final error check can be done on the resulting stage,
+// even if no merging was done (i.e., the stage was only one compilation unit).
+//
+
+#include "localintermediate.h"
+#include "../Include/InfoSink.h"
+
+namespace glslang {
+
+//
+// Link-time error emitter.
+//
+void TIntermediate::error(TInfoSink& infoSink, const char* message)
+{
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n";
+
+ ++numErrors;
+}
+
+// TODO: 4.4 offset/align: "Two blocks linked together in the same program with the same block
+// name must have the exact same set of members qualified with offset and their integral-constant
+// expression values must be the same, or a link-time error results."
+
+//
+// Merge the information from 'unit' into 'this'
+//
+void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
+{
+ if (source == EShSourceNone)
+ source = unit.source;
+
+ if (source != unit.source)
+ error(infoSink, "can't link compilation units from different source languages");
+
+ if (source == EShSourceHlsl && unit.entryPoint.size() > 0) {
+ if (entryPoint.size() > 0)
+ error(infoSink, "can't handle multiple entry points per stage");
+ else
+ entryPoint = unit.entryPoint;
+ }
+ numMains += unit.numMains;
+ numErrors += unit.numErrors;
+ numPushConstants += unit.numPushConstants;
+ callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
+
+ if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
+ error(infoSink, "gl_FragCoord redeclarations must match across shaders\n");
+
+ if (! earlyFragmentTests)
+ earlyFragmentTests = unit.earlyFragmentTests;
+
+ if (depthLayout == EldNone)
+ depthLayout = unit.depthLayout;
+ else if (depthLayout != unit.depthLayout)
+ error(infoSink, "Contradictory depth layouts");
+
+ blendEquations |= unit.blendEquations;
+
+ if (inputPrimitive == ElgNone)
+ inputPrimitive = unit.inputPrimitive;
+ else if (inputPrimitive != unit.inputPrimitive)
+ error(infoSink, "Contradictory input layout primitives");
+
+ if (outputPrimitive == ElgNone)
+ outputPrimitive = unit.outputPrimitive;
+ else if (outputPrimitive != unit.outputPrimitive)
+ error(infoSink, "Contradictory output layout primitives");
+
+ if (vertices == TQualifier::layoutNotSet)
+ vertices = unit.vertices;
+ else if (vertices != unit.vertices) {
+ if (language == EShLangGeometry)
+ error(infoSink, "Contradictory layout max_vertices values");
+ else if (language == EShLangTessControl)
+ error(infoSink, "Contradictory layout vertices values");
+ else
+ assert(0);
+ }
+
+ if (vertexSpacing == EvsNone)
+ vertexSpacing = unit.vertexSpacing;
+ else if (vertexSpacing != unit.vertexSpacing)
+ error(infoSink, "Contradictory input vertex spacing");
+
+ if (vertexOrder == EvoNone)
+ vertexOrder = unit.vertexOrder;
+ else if (vertexOrder != unit.vertexOrder)
+ error(infoSink, "Contradictory triangle ordering");
+
+ if (unit.pointMode)
+ pointMode = true;
+
+ for (int i = 0; i < 3; ++i) {
+ if (localSize[i] > 1)
+ localSize[i] = unit.localSize[i];
+ else if (localSize[i] != unit.localSize[i])
+ error(infoSink, "Contradictory local size");
+
+ if (localSizeSpecId[i] != TQualifier::layoutNotSet)
+ localSizeSpecId[i] = unit.localSizeSpecId[i];
+ else if (localSizeSpecId[i] != unit.localSizeSpecId[i])
+ error(infoSink, "Contradictory local size specialization ids");
+ }
+
+ if (unit.xfbMode)
+ xfbMode = true;
+ for (size_t b = 0; b < xfbBuffers.size(); ++b) {
+ if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
+ xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
+ else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride)
+ error(infoSink, "Contradictory xfb_stride");
+ xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride);
+ if (unit.xfbBuffers[b].containsDouble)
+ xfbBuffers[b].containsDouble = true;
+ // TODO: 4.4 link: enhanced layouts: compare ranges
+ }
+
+ if (unit.treeRoot == 0)
+ return;
+
+ if (treeRoot == 0) {
+ treeRoot = unit.treeRoot;
+ version = unit.version;
+ requestedExtensions = unit.requestedExtensions;
+ return;
+ }
+
+ // Getting this far means we have two existing trees to merge...
+
+ version = std::max(version, unit.version);
+ requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
+
+ // Get the top-level globals of each unit
+ TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
+ TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
+
+ // Get the linker-object lists
+ TIntermSequence& linkerObjects = findLinkerObjects();
+ TIntermSequence& unitLinkerObjects = unit.findLinkerObjects();
+
+ mergeBodies(infoSink, globals, unitGlobals);
+ mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
+
+ ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
+}
+
+//
+// Merge the function bodies and global-level initializers from unitGlobals into globals.
+// Will error check duplication of function bodies for the same signature.
+//
+void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals)
+{
+ // TODO: link-time performance: Processing in alphabetical order will be faster
+
+ // Error check the global objects, not including the linker objects
+ for (unsigned int child = 0; child < globals.size() - 1; ++child) {
+ for (unsigned int unitChild = 0; unitChild < unitGlobals.size() - 1; ++unitChild) {
+ TIntermAggregate* body = globals[child]->getAsAggregate();
+ TIntermAggregate* unitBody = unitGlobals[unitChild]->getAsAggregate();
+ if (body && unitBody && body->getOp() == EOpFunction && unitBody->getOp() == EOpFunction && body->getName() == unitBody->getName()) {
+ error(infoSink, "Multiple function bodies in multiple compilation units for the same signature in the same stage:");
+ infoSink.info << " " << globals[child]->getAsAggregate()->getName() << "\n";
+ }
+ }
+ }
+
+ // Merge the global objects, just in front of the linker objects
+ globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
+}
+
+//
+// Merge the linker objects from unitLinkerObjects into linkerObjects.
+// Duplication is expected and filtered out, but contradictions are an error.
+//
+void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects)
+{
+ // Error check and merge the linker objects (duplicates should not be created)
+ std::size_t initialNumLinkerObjects = linkerObjects.size();
+ for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) {
+ bool merge = true;
+ for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
+ TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
+ TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
+ assert(symbol && unitSymbol);
+ if (symbol->getName() == unitSymbol->getName()) {
+ // filter out copy
+ merge = false;
+
+ // but if one has an initializer and the other does not, update
+ // the initializer
+ if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty())
+ symbol->setConstArray(unitSymbol->getConstArray());
+
+ // Similarly for binding
+ if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
+ symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
+
+ // Update implicit array sizes
+ mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
+
+ // Check for consistent types/qualification/initializers etc.
+ mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
+ }
+ }
+ if (merge)
+ linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
+ }
+}
+
+// TODO 4.5 link functionality: cull distance array size checking
+
+// Recursively merge the implicit array sizes through the objects' respective type trees.
+void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
+{
+ if (type.isImplicitlySizedArray() && unitType.isArray()) {
+ int newImplicitArraySize = unitType.isImplicitlySizedArray() ? unitType.getImplicitArraySize() : unitType.getOuterArraySize();
+ if (newImplicitArraySize > type.getImplicitArraySize ())
+ type.setImplicitArraySize(newImplicitArraySize);
+ }
+
+ // Type mismatches are caught and reported after this, just be careful for now.
+ if (! type.isStruct() || ! unitType.isStruct() || type.getStruct()->size() != unitType.getStruct()->size())
+ return;
+
+ for (int i = 0; i < (int)type.getStruct()->size(); ++i)
+ mergeImplicitArraySizes(*(*type.getStruct())[i].type, *(*unitType.getStruct())[i].type);
+}
+
+//
+// Compare two global objects from two compilation units and see if they match
+// well enough. Rules can be different for intra- vs. cross-stage matching.
+//
+// This function only does one of intra- or cross-stage matching per call.
+//
+void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
+{
+ bool writeTypeComparison = false;
+
+ // Types have to match
+ if (symbol.getType() != unitSymbol.getType()) {
+ error(infoSink, "Types must match:");
+ writeTypeComparison = true;
+ }
+
+ // Qualifiers have to (almost) match
+
+ // Storage...
+ if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
+ error(infoSink, "Storage qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Precision...
+ if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
+ error(infoSink, "Precision qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Invariance...
+ if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) {
+ error(infoSink, "Presence of invariant qualifier must match:");
+ writeTypeComparison = true;
+ }
+
+ // Precise...
+ if (! crossStage && symbol.getQualifier().noContraction != unitSymbol.getQualifier().noContraction) {
+ error(infoSink, "Presence of precise qualifier must match:");
+ writeTypeComparison = true;
+ }
+
+ // Auxiliary and interpolation...
+ if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid ||
+ symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth ||
+ symbol.getQualifier().flat != unitSymbol.getQualifier().flat ||
+ symbol.getQualifier().sample != unitSymbol.getQualifier().sample ||
+ symbol.getQualifier().patch != unitSymbol.getQualifier().patch ||
+ symbol.getQualifier().nopersp != unitSymbol.getQualifier().nopersp) {
+ error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Memory...
+ if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent ||
+ symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil ||
+ symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict ||
+ symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly ||
+ symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) {
+ error(infoSink, "Memory qualifiers must match:");
+ writeTypeComparison = true;
+ }
+
+ // Layouts...
+ // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec
+ // requires separate user-supplied offset from actual computed offset, but
+ // current implementation only has one offset.
+ if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix ||
+ symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking ||
+ symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation ||
+ symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent ||
+ symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex ||
+ symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding ||
+ (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) {
+ error(infoSink, "Layout qualification must match:");
+ writeTypeComparison = true;
+ }
+
+ // Initializers have to match, if both are present, and if we don't already know the types don't match
+ if (! writeTypeComparison) {
+ if (! symbol.getConstArray().empty() && ! unitSymbol.getConstArray().empty()) {
+ if (symbol.getConstArray() != unitSymbol.getConstArray()) {
+ error(infoSink, "Initializers must match:");
+ infoSink.info << " " << symbol.getName() << "\n";
+ }
+ }
+ }
+
+ if (writeTypeComparison)
+ infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" <<
+ unitSymbol.getType().getCompleteString() << "\"\n";
+}
+
+//
+// Do final link-time error checking of a complete (merged) intermediate representation.
+// (Much error checking was done during merging).
+//
+// Also, lock in defaults of things not set, including array sizes.
+//
+void TIntermediate::finalCheck(TInfoSink& infoSink)
+{
+ if (source == EShSourceGlsl && numMains < 1)
+ error(infoSink, "Missing entry point: Each stage requires one \"void main()\" entry point");
+
+ if (numPushConstants > 1)
+ error(infoSink, "Only one push_constant block is allowed per stage");
+
+ // recursion checking
+ checkCallGraphCycles(infoSink);
+
+ // overlap/alias/missing I/O, etc.
+ inOutLocationCheck(infoSink);
+
+ // invocations
+ if (invocations == TQualifier::layoutNotSet)
+ invocations = 1;
+
+ if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipVertex"))
+ error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipVertex (gl_ClipDistance is preferred)");
+ if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_ClipVertex"))
+ error(infoSink, "Can only use one of gl_CullDistance or gl_ClipVertex (gl_ClipDistance is preferred)");
+
+ if (userOutputUsed() && (inIoAccessed("gl_FragColor") || inIoAccessed("gl_FragData")))
+ error(infoSink, "Cannot use gl_FragColor or gl_FragData when using user-defined outputs");
+ if (inIoAccessed("gl_FragColor") && inIoAccessed("gl_FragData"))
+ error(infoSink, "Cannot use both gl_FragColor and gl_FragData");
+
+ for (size_t b = 0; b < xfbBuffers.size(); ++b) {
+ if (xfbBuffers[b].containsDouble)
+ RoundToPow2(xfbBuffers[b].implicitStride, 8);
+
+ // "It is a compile-time or link-time error to have
+ // any xfb_offset that overflows xfb_stride, whether stated on declarations before or after the xfb_stride, or
+ // in different compilation units. While xfb_stride can be declared multiple times for the same buffer, it is a
+ // compile-time or link-time error to have different values specified for the stride for the same buffer."
+ if (xfbBuffers[b].stride != TQualifier::layoutXfbStrideEnd && xfbBuffers[b].implicitStride > xfbBuffers[b].stride) {
+ error(infoSink, "xfb_stride is too small to hold all buffer entries:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << ", minimum stride needed: " << xfbBuffers[b].implicitStride << "\n";
+ }
+ if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
+ xfbBuffers[b].stride = xfbBuffers[b].implicitStride;
+
+ // "If the buffer is capturing any
+ // outputs with double-precision components, the stride must be a multiple of 8, otherwise it must be a
+ // multiple of 4, or a compile-time or link-time error results."
+ if (xfbBuffers[b].containsDouble && ! IsMultipleOfPow2(xfbBuffers[b].stride, 8)) {
+ error(infoSink, "xfb_stride must be multiple of 8 for buffer holding a double:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
+ } else if (! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) {
+ error(infoSink, "xfb_stride must be multiple of 4:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
+ }
+
+ // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
+ // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
+ if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) {
+ error(infoSink, "xfb_stride is too large:");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources.maxTransformFeedbackInterleavedComponents << "\n";
+ }
+ }
+
+ switch (language) {
+ case EShLangVertex:
+ break;
+ case EShLangTessControl:
+ if (vertices == TQualifier::layoutNotSet)
+ error(infoSink, "At least one shader must specify an output layout(vertices=...)");
+ break;
+ case EShLangTessEvaluation:
+ if (inputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an input layout primitive");
+ if (vertexSpacing == EvsNone)
+ vertexSpacing = EvsEqual;
+ if (vertexOrder == EvoNone)
+ vertexOrder = EvoCcw;
+ break;
+ case EShLangGeometry:
+ if (inputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an input layout primitive");
+ if (outputPrimitive == ElgNone)
+ error(infoSink, "At least one shader must specify an output layout primitive");
+ if (vertices == TQualifier::layoutNotSet)
+ error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
+ break;
+ case EShLangFragment:
+ break;
+ case EShLangCompute:
+ break;
+ default:
+ error(infoSink, "Unknown Stage.");
+ break;
+ }
+
+ // Process the tree for any node-specific work.
+ class TFinalLinkTraverser : public TIntermTraverser {
+ public:
+ TFinalLinkTraverser() { }
+ virtual ~TFinalLinkTraverser() { }
+
+ virtual void visitSymbol(TIntermSymbol* symbol)
+ {
+ // Implicitly size arrays.
+ symbol->getWritableType().adoptImplicitArraySizes();
+ }
+ } finalLinkTraverser;
+
+ treeRoot->traverse(&finalLinkTraverser);
+}
+
+//
+// See if the call graph contains any static recursion, which is disallowed
+// by the specification.
+//
+void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink)
+{
+ // Reset everything, once.
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ call->visited = false;
+ call->currentPath = false;
+ call->errorGiven = false;
+ }
+
+ //
+ // Loop, looking for a new connected subgraph. One subgraph is handled per loop iteration.
+ //
+
+ TCall* newRoot;
+ do {
+ // See if we have unvisited parts of the graph.
+ newRoot = 0;
+ for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
+ if (! call->visited) {
+ newRoot = &(*call);
+ break;
+ }
+ }
+
+ // If not, we are done.
+ if (! newRoot)
+ break;
+
+ // Otherwise, we found a new subgraph, process it:
+ // See what all can be reached by this new root, and if any of
+ // that is recursive. This is done by depth-first traversals, seeing
+ // if a new call is found that was already in the currentPath (a back edge),
+ // thereby detecting recursion.
+ std::list<TCall*> stack;
+ newRoot->currentPath = true; // currentPath will be true iff it is on the stack
+ stack.push_back(newRoot);
+ while (! stack.empty()) {
+ // get a caller
+ TCall* call = stack.back();
+
+ // Add to the stack just one callee.
+ // This algorithm always terminates, because only !visited and !currentPath causes a push
+ // and all pushes change currentPath to true, and all pops change visited to true.
+ TGraph::iterator child = callGraph.begin();
+ for (; child != callGraph.end(); ++child) {
+
+ // If we already visited this node, its whole subgraph has already been processed, so skip it.
+ if (child->visited)
+ continue;
+
+ if (call->callee == child->caller) {
+ if (child->currentPath) {
+ // Then, we found a back edge
+ if (! child->errorGiven) {
+ error(infoSink, "Recursion detected:");
+ infoSink.info << " " << call->callee << " calling " << child->callee << "\n";
+ child->errorGiven = true;
+ recursive = true;
+ }
+ } else {
+ child->currentPath = true;
+ stack.push_back(&(*child));
+ break;
+ }
+ }
+ }
+ if (child == callGraph.end()) {
+ // no more callees, we bottomed out, never look at this node again
+ stack.back()->currentPath = false;
+ stack.back()->visited = true;
+ stack.pop_back();
+ }
+ } // end while, meaning nothing left to process in this subtree
+
+ } while (newRoot); // redundant loop check; should always exit via the 'break' above
+}
+
+//
+// Satisfy rules for location qualifiers on inputs and outputs
+//
+void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
+{
+ // ES 3.0 requires all outputs to have location qualifiers if there is more than one output
+ bool fragOutWithNoLocation = false;
+ int numFragOut = 0;
+
+ // TODO: linker functionality: location collision checking
+
+ TIntermSequence& linkObjects = findLinkerObjects();
+ for (size_t i = 0; i < linkObjects.size(); ++i) {
+ const TType& type = linkObjects[i]->getAsTyped()->getType();
+ const TQualifier& qualifier = type.getQualifier();
+ if (language == EShLangFragment) {
+ if (qualifier.storage == EvqVaryingOut && qualifier.builtIn == EbvNone) {
+ ++numFragOut;
+ if (!qualifier.hasAnyLocation())
+ fragOutWithNoLocation = true;
+ }
+ }
+ }
+
+ if (profile == EEsProfile) {
+ if (numFragOut > 1 && fragOutWithNoLocation)
+ error(infoSink, "when more than one fragment shader output, all must have location qualifiers");
+ }
+}
+
+TIntermSequence& TIntermediate::findLinkerObjects() const
+{
+ // Get the top-level globals
+ TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
+
+ // Get the last member of the sequences, expected to be the linker-object lists
+ assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
+
+ return globals.back()->getAsAggregate()->getSequence();
+}
+
+// See if a variable was both a user-declared output and used.
+// Note: the spec discusses writing to one, but this looks at read or write, which
+// is more useful, and perhaps the spec should be changed to reflect that.
+bool TIntermediate::userOutputUsed() const
+{
+ const TIntermSequence& linkerObjects = findLinkerObjects();
+
+ bool found = false;
+ for (size_t i = 0; i < linkerObjects.size(); ++i) {
+ const TIntermSymbol& symbolNode = *linkerObjects[i]->getAsSymbolNode();
+ if (symbolNode.getQualifier().storage == EvqVaryingOut &&
+ symbolNode.getName().compare(0, 3, "gl_") != 0 &&
+ inIoAccessed(symbolNode.getName())) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
+
+// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
+// as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+// typeCollision is set to true if there is no direct collision, but the types in the same location
+// are different.
+//
+int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type, bool& typeCollision)
+{
+ typeCollision = false;
+
+ int set;
+ if (qualifier.isPipeInput())
+ set = 0;
+ else if (qualifier.isPipeOutput())
+ set = 1;
+ else if (qualifier.storage == EvqUniform)
+ set = 2;
+ else if (qualifier.storage == EvqBuffer)
+ set = 3;
+ else
+ return -1;
+
+ int size;
+ if (qualifier.isUniformOrBuffer()) {
+ if (type.isArray())
+ size = type.getCumulativeArraySize();
+ else
+ size = 1;
+ } else {
+ // Strip off the outer array dimension for those having an extra one.
+ if (type.isArray() && qualifier.isArrayedIo(language)) {
+ TType elementType(type, 0);
+ size = computeTypeLocationSize(elementType);
+ } else
+ size = computeTypeLocationSize(type);
+ }
+
+ TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1);
+ TRange componentRange(0, 3);
+ if (qualifier.hasComponent()) {
+ componentRange.start = qualifier.layoutComponent;
+ componentRange.last = componentRange.start + type.getVectorSize() - 1;
+ }
+ TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0);
+
+ // check for collisions, except for vertex inputs on desktop
+ if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput())) {
+ for (size_t r = 0; r < usedIo[set].size(); ++r) {
+ if (range.overlap(usedIo[set][r])) {
+ // there is a collision; pick one
+ return std::max(locationRange.start, usedIo[set][r].location.start);
+ } else if (locationRange.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) {
+ // aliased-type mismatch
+ typeCollision = true;
+ return std::max(locationRange.start, usedIo[set][r].location.start);
+ }
+ }
+ }
+
+ usedIo[set].push_back(range);
+
+ return -1; // no collision
+}
+
+// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
+// as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+int TIntermediate::addUsedOffsets(int binding, int offset, int numOffsets)
+{
+ TRange bindingRange(binding, binding);
+ TRange offsetRange(offset, offset + numOffsets - 1);
+ TOffsetRange range(bindingRange, offsetRange);
+
+ // check for collisions, except for vertex inputs on desktop
+ for (size_t r = 0; r < usedAtomics.size(); ++r) {
+ if (range.overlap(usedAtomics[r])) {
+ // there is a collision; pick one
+ return std::max(offset, usedAtomics[r].offset.start);
+ }
+ }
+
+ usedAtomics.push_back(range);
+
+ return -1; // no collision
+}
+
+// Accumulate used constant_id values.
+//
+// Return false is one was already used.
+bool TIntermediate::addUsedConstantId(int id)
+{
+ if (usedConstantId.find(id) != usedConstantId.end())
+ return false;
+
+ usedConstantId.insert(id);
+
+ return true;
+}
+
+// Recursively figure out how many locations are used up by an input or output type.
+// Return the size of type, as measured by "locations".
+int TIntermediate::computeTypeLocationSize(const TType& type) const
+{
+ // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n
+ // consecutive locations..."
+ if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ TType elementType(type, 0);
+ if (type.isImplicitlySizedArray()) {
+ // TODO: are there valid cases of having an implicitly-sized array with a location? If so, running this code too early.
+ return computeTypeLocationSize(elementType);
+ } else
+ return type.getOuterArraySize() * computeTypeLocationSize(elementType);
+ }
+
+ // "The locations consumed by block and structure members are determined by applying the rules above
+ // recursively..."
+ if (type.isStruct()) {
+ int size = 0;
+ for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
+ TType memberType(type, member);
+ size += computeTypeLocationSize(memberType);
+ }
+ return size;
+ }
+
+ // ES: "If a shader input is any scalar or vector type, it will consume a single location."
+
+ // Desktop: "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex
+ // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while
+ // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will
+ // consume only a single location, in all stages."
+ if (type.isScalar())
+ return 1;
+ if (type.isVector()) {
+ if (language == EShLangVertex && type.getQualifier().isPipeInput())
+ return 1;
+ if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2)
+ return 2;
+ else
+ return 1;
+ }
+
+ // "If the declared input is an n x m single- or double-precision matrix, ...
+ // The number of locations assigned for each matrix will be the same as
+ // for an n-element array of m-component vectors..."
+ if (type.isMatrix()) {
+ TType columnType(type, 0);
+ return type.getMatrixCols() * computeTypeLocationSize(columnType);
+ }
+
+ assert(0);
+ return 1;
+}
+
+// Accumulate xfb buffer ranges and check for collisions as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+//
+int TIntermediate::addXfbBufferOffset(const TType& type)
+{
+ const TQualifier& qualifier = type.getQualifier();
+
+ assert(qualifier.hasXfbOffset() && qualifier.hasXfbBuffer());
+ TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer];
+
+ // compute the range
+ unsigned int size = computeTypeXfbSize(type, buffer.containsDouble);
+ buffer.implicitStride = std::max(buffer.implicitStride, qualifier.layoutXfbOffset + size);
+ TRange range(qualifier.layoutXfbOffset, qualifier.layoutXfbOffset + size - 1);
+
+ // check for collisions
+ for (size_t r = 0; r < buffer.ranges.size(); ++r) {
+ if (range.overlap(buffer.ranges[r])) {
+ // there is a collision; pick an example to return
+ return std::max(range.start, buffer.ranges[r].start);
+ }
+ }
+
+ buffer.ranges.push_back(range);
+
+ return -1; // no collision
+}
+
+// Recursively figure out how many bytes of xfb buffer are used by the given type.
+// Return the size of type, in bytes.
+// Sets containsDouble to true if the type contains a double.
+// N.B. Caller must set containsDouble to false before calling.
+unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& containsDouble) const
+{
+ // "...if applied to an aggregate containing a double, the offset must also be a multiple of 8,
+ // and the space taken in the buffer will be a multiple of 8.
+ // ...within the qualified entity, subsequent components are each
+ // assigned, in order, to the next available offset aligned to a multiple of
+ // that component's size. Aggregate types are flattened down to the component
+ // level to get this sequence of components."
+
+ if (type.isArray()) {
+ // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ assert(type.isExplicitlySizedArray());
+ TType elementType(type, 0);
+ return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble);
+ }
+
+ if (type.isStruct()) {
+ unsigned int size = 0;
+ bool structContainsDouble = false;
+ for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
+ TType memberType(type, member);
+ // "... if applied to
+ // an aggregate containing a double, the offset must also be a multiple of 8,
+ // and the space taken in the buffer will be a multiple of 8."
+ bool memberContainsDouble = false;
+ int memberSize = computeTypeXfbSize(memberType, memberContainsDouble);
+ if (memberContainsDouble) {
+ structContainsDouble = true;
+ RoundToPow2(size, 8);
+ }
+ size += memberSize;
+ }
+
+ if (structContainsDouble) {
+ containsDouble = true;
+ RoundToPow2(size, 8);
+ }
+ return size;
+ }
+
+ int numComponents;
+ if (type.isScalar())
+ numComponents = 1;
+ else if (type.isVector())
+ numComponents = type.getVectorSize();
+ else if (type.isMatrix())
+ numComponents = type.getMatrixCols() * type.getMatrixRows();
+ else {
+ assert(0);
+ numComponents = 1;
+ }
+
+ if (type.getBasicType() == EbtDouble) {
+ containsDouble = true;
+ return 8 * numComponents;
+ } else
+ return 4 * numComponents;
+}
+
+const int baseAlignmentVec4Std140 = 16;
+
+// Return the size and alignment of a scalar.
+// The size is returned in the 'size' parameter
+// Return value is the alignment of the type.
+int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
+{
+ switch (type.getBasicType()) {
+ case EbtInt64:
+ case EbtUint64:
+ case EbtDouble: size = 8; return 8;
+ default: size = 4; return 4;
+ }
+}
+
+// Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout
+// Operates recursively.
+//
+// If std140 is true, it does the rounding up to vec4 size required by std140,
+// otherwise it does not, yielding std430 rules.
+//
+// The size is returned in the 'size' parameter
+//
+// The stride is only non-0 for arrays or matrices, and is the stride of the
+// top-level object nested within the type. E.g., for an array of matrices,
+// it is the distances needed between matrices, despite the rules saying the
+// stride comes from the flattening down to vectors.
+//
+// Return value is the alignment of the type.
+int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor)
+{
+ int alignment;
+
+ // When using the std140 storage layout, structures will be laid out in buffer
+ // storage with its members stored in monotonically increasing order based on their
+ // location in the declaration. A structure and each structure member have a base
+ // offset and a base alignment, from which an aligned offset is computed by rounding
+ // the base offset up to a multiple of the base alignment. The base offset of the first
+ // member of a structure is taken from the aligned offset of the structure itself. The
+ // base offset of all other structure members is derived by taking the offset of the
+ // last basic machine unit consumed by the previous member and adding one. Each
+ // structure member is stored in memory at its aligned offset. The members of a top-
+ // level uniform block are laid out in buffer storage by treating the uniform block as
+ // a structure with a base offset of zero.
+ //
+ // 1. If the member is a scalar consuming N basic machine units, the base alignment is N.
+ //
+ // 2. If the member is a two- or four-component vector with components consuming N basic
+ // machine units, the base alignment is 2N or 4N, respectively.
+ //
+ // 3. If the member is a three-component vector with components consuming N
+ // basic machine units, the base alignment is 4N.
+ //
+ // 4. If the member is an array of scalars or vectors, the base alignment and array
+ // stride are set to match the base alignment of a single array element, according
+ // to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The
+ // array may have padding at the end; the base offset of the member following
+ // the array is rounded up to the next multiple of the base alignment.
+ //
+ // 5. If the member is a column-major matrix with C columns and R rows, the
+ // matrix is stored identically to an array of C column vectors with R
+ // components each, according to rule (4).
+ //
+ // 6. If the member is an array of S column-major matrices with C columns and
+ // R rows, the matrix is stored identically to a row of S  C column vectors
+ // with R components each, according to rule (4).
+ //
+ // 7. If the member is a row-major matrix with C columns and R rows, the matrix
+ // is stored identically to an array of R row vectors with C components each,
+ // according to rule (4).
+ //
+ // 8. If the member is an array of S row-major matrices with C columns and R
+ // rows, the matrix is stored identically to a row of S  R row vectors with C
+ // components each, according to rule (4).
+ //
+ // 9. If the member is a structure, the base alignment of the structure is N , where
+ // N is the largest base alignment value of any of its members, and rounded
+ // up to the base alignment of a vec4. The individual members of this substructure
+ // are then assigned offsets by applying this set of rules recursively,
+ // where the base offset of the first member of the sub-structure is equal to the
+ // aligned offset of the structure. The structure may have padding at the end;
+ // the base offset of the member following the sub-structure is rounded up to
+ // the next multiple of the base alignment of the structure.
+ //
+ // 10. If the member is an array of S structures, the S elements of the array are laid
+ // out in order, according to rule (9).
+ //
+ // Assuming, for rule 10: The stride is the same as the size of an element.
+
+ stride = 0;
+ int dummyStride;
+
+ // rules 4, 6, 8, and 10
+ if (type.isArray()) {
+ // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
+ TType derefType(type, 0);
+ alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
+ if (std140)
+ alignment = std::max(baseAlignmentVec4Std140, alignment);
+ RoundToPow2(size, alignment);
+ stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
+ // uses the assumption for rule 10 in the comment above
+ size = stride * type.getOuterArraySize();
+ return alignment;
+ }
+
+ // rule 9
+ if (type.getBasicType() == EbtStruct) {
+ const TTypeList& memberList = *type.getStruct();
+
+ size = 0;
+ int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0;
+ for (size_t m = 0; m < memberList.size(); ++m) {
+ int memberSize;
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+ int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140,
+ (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
+ maxAlignment = std::max(maxAlignment, memberAlignment);
+ RoundToPow2(size, memberAlignment);
+ size += memberSize;
+ }
+
+ // The structure may have padding at the end; the base offset of
+ // the member following the sub-structure is rounded up to the next
+ // multiple of the base alignment of the structure.
+ RoundToPow2(size, maxAlignment);
+
+ return maxAlignment;
+ }
+
+ // rule 1
+ if (type.isScalar())
+ return getBaseAlignmentScalar(type, size);
+
+ // rules 2 and 3
+ if (type.isVector()) {
+ int scalarAlign = getBaseAlignmentScalar(type, size);
+ switch (type.getVectorSize()) {
+ case 2:
+ size *= 2;
+ return 2 * scalarAlign;
+ default:
+ size *= type.getVectorSize();
+ return 4 * scalarAlign;
+ }
+ }
+
+ // rules 5 and 7
+ if (type.isMatrix()) {
+ // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
+ TType derefType(type, 0, rowMajor);
+
+ alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
+ if (std140)
+ alignment = std::max(baseAlignmentVec4Std140, alignment);
+ RoundToPow2(size, alignment);
+ stride = size; // use intra-matrix stride for stride of a just a matrix
+ if (rowMajor)
+ size = stride * type.getMatrixRows();
+ else
+ size = stride * type.getMatrixCols();
+
+ return alignment;
+ }
+
+ assert(0); // all cases should be covered above
+ size = baseAlignmentVec4Std140;
+ return baseAlignmentVec4Std140;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h
new file mode 100644
index 00000000000..7445dee04e0
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h
@@ -0,0 +1,396 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "../Include/intermediate.h"
+#include "../Public/ShaderLang.h"
+#include "Versions.h"
+
+#include <algorithm>
+#include <set>
+
+class TInfoSink;
+
+namespace glslang {
+
+struct TVectorFields {
+ int offsets[4];
+ int num;
+};
+
+//
+// Some helper structures for TIntermediate. Their contents are encapsulated
+// by TIntermediate.
+//
+
+// Used for detecting recursion: A "call" is a pair: <caller, callee>.
+struct TCall {
+ TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
+ TString caller;
+ TString callee;
+ bool visited;
+ bool currentPath;
+ bool errorGiven;
+};
+
+// A generic 1-D range.
+struct TRange {
+ TRange(int start, int last) : start(start), last(last) { }
+ bool overlap(const TRange& rhs) const
+ {
+ return last >= rhs.start && start <= rhs.last;
+ }
+ int start;
+ int last;
+};
+
+// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
+// within the same location range, component range, and index value. Locations don't alias unless
+// all other dimensions of their range overlap.
+struct TIoRange {
+ TIoRange(TRange location, TRange component, TBasicType basicType, int index)
+ : location(location), component(component), basicType(basicType), index(index) { }
+ bool overlap(const TIoRange& rhs) const
+ {
+ return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
+ }
+ TRange location;
+ TRange component;
+ TBasicType basicType;
+ int index;
+};
+
+// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
+// within the same binding and offset range.
+struct TOffsetRange {
+ TOffsetRange(TRange binding, TRange offset)
+ : binding(binding), offset(offset) { }
+ bool overlap(const TOffsetRange& rhs) const
+ {
+ return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
+ }
+ TRange binding;
+ TRange offset;
+};
+
+// Things that need to be tracked per xfb buffer.
+struct TXfbBuffer {
+ TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { }
+ std::vector<TRange> ranges; // byte offsets that have already been assigned
+ unsigned int stride;
+ unsigned int implicitStride;
+ bool containsDouble;
+};
+
+class TSymbolTable;
+class TSymbol;
+class TVariable;
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TIntermediate {
+public:
+ explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
+ source(EShSourceNone), language(l), profile(p), version(v), spv(0), treeRoot(0),
+ numMains(0), numErrors(0), numPushConstants(0), recursive(false),
+ invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), inputPrimitive(ElgNone), outputPrimitive(ElgNone),
+ pixelCenterInteger(false), originUpperLeft(false),
+ vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), depthReplacing(false), blendEquations(0),
+ multiStream(false), xfbMode(false)
+ {
+ localSize[0] = 1;
+ localSize[1] = 1;
+ localSize[2] = 1;
+ localSizeSpecId[0] = TQualifier::layoutNotSet;
+ localSizeSpecId[1] = TQualifier::layoutNotSet;
+ localSizeSpecId[2] = TQualifier::layoutNotSet;
+ xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
+ }
+ void setLimits(const TBuiltInResource& r) { resources = r; }
+
+ bool postProcess(TIntermNode*, EShLanguage);
+ void output(TInfoSink&, bool tree);
+ void removeTree();
+
+ void setSource(EShSource s) { source = s; }
+ EShSource getSource() const { return source; }
+ void setEntryPoint(const char* ep) { entryPoint = ep; }
+ const std::string& getEntryPoint() const { return entryPoint; }
+ void setVersion(int v) { version = v; }
+ int getVersion() const { return version; }
+ void setProfile(EProfile p) { profile = p; }
+ EProfile getProfile() const { return profile; }
+ void setSpv(int s) { spv = s; }
+ int getSpv() const { return spv; }
+ EShLanguage getStage() const { return language; }
+ void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
+ const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
+
+ void setTreeRoot(TIntermNode* r) { treeRoot = r; }
+ TIntermNode* getTreeRoot() const { return treeRoot; }
+ void addMainCount() { ++numMains; }
+ int getNumMains() const { return numMains; }
+ int getNumErrors() const { return numErrors; }
+ void addPushConstantCount() { ++numPushConstants; }
+ bool isRecursive() const { return recursive; }
+
+ TIntermSymbol* addSymbol(const TVariable&);
+ TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
+ TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
+ TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
+ TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+ TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
+ TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
+ bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
+ TIntermAggregate* makeAggregate(TIntermNode* node);
+ TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
+ TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
+ bool areAllChildConst(TIntermAggregate* aggrNode);
+ TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
+ TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
+ TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+ TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
+ TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
+ TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
+ TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
+ bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
+ TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
+ TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
+
+ // Constant folding (in Constant.cpp)
+ TIntermTyped* fold(TIntermAggregate* aggrNode);
+ TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
+ TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
+ TIntermTyped* foldSwizzle(TIntermTyped* node, TVectorFields& fields, const TSourceLoc&);
+
+ // Tree ops
+ static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay);
+
+ // Linkage related
+ void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
+ void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
+ void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
+
+ bool setInvocations(int i)
+ {
+ if (invocations != TQualifier::layoutNotSet)
+ return invocations == i;
+ invocations = i;
+ return true;
+ }
+ int getInvocations() const { return invocations; }
+ bool setVertices(int m)
+ {
+ if (vertices != TQualifier::layoutNotSet)
+ return vertices == m;
+ vertices = m;
+ return true;
+ }
+ int getVertices() const { return vertices; }
+ bool setInputPrimitive(TLayoutGeometry p)
+ {
+ if (inputPrimitive != ElgNone)
+ return inputPrimitive == p;
+ inputPrimitive = p;
+ return true;
+ }
+ TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
+ bool setVertexSpacing(TVertexSpacing s)
+ {
+ if (vertexSpacing != EvsNone)
+ return vertexSpacing == s;
+ vertexSpacing = s;
+ return true;
+ }
+ TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
+ bool setVertexOrder(TVertexOrder o)
+ {
+ if (vertexOrder != EvoNone)
+ return vertexOrder == o;
+ vertexOrder = o;
+ return true;
+ }
+ TVertexOrder getVertexOrder() const { return vertexOrder; }
+ void setPointMode() { pointMode = true; }
+ bool getPointMode() const { return pointMode; }
+
+ bool setLocalSize(int dim, int size)
+ {
+ if (localSize[dim] > 1)
+ return size == localSize[dim];
+ localSize[dim] = size;
+ return true;
+ }
+ unsigned int getLocalSize(int dim) const { return localSize[dim]; }
+
+ bool setLocalSizeSpecId(int dim, int id)
+ {
+ if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
+ return id == localSizeSpecId[dim];
+ localSizeSpecId[dim] = id;
+ return true;
+ }
+ int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
+
+ void setXfbMode() { xfbMode = true; }
+ bool getXfbMode() const { return xfbMode; }
+ void setMultiStream() { multiStream = true; }
+ bool isMultiStream() const { return multiStream; }
+ bool setOutputPrimitive(TLayoutGeometry p)
+ {
+ if (outputPrimitive != ElgNone)
+ return outputPrimitive == p;
+ outputPrimitive = p;
+ return true;
+ }
+ TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
+ void setOriginUpperLeft() { originUpperLeft = true; }
+ bool getOriginUpperLeft() const { return originUpperLeft; }
+ void setPixelCenterInteger() { pixelCenterInteger = true; }
+ bool getPixelCenterInteger() const { return pixelCenterInteger; }
+ void setEarlyFragmentTests() { earlyFragmentTests = true; }
+ bool getEarlyFragmentTests() const { return earlyFragmentTests; }
+ bool setDepth(TLayoutDepth d)
+ {
+ if (depthLayout != EldNone)
+ return depthLayout == d;
+ depthLayout = d;
+ return true;
+ }
+ TLayoutDepth getDepth() const { return depthLayout; }
+ void setDepthReplacing() { depthReplacing = true; }
+ bool isDepthReplacing() const { return depthReplacing; }
+
+ void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
+ unsigned int getBlendEquations() const { return blendEquations; }
+
+ void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
+ void merge(TInfoSink&, TIntermediate&);
+ void finalCheck(TInfoSink&);
+
+ void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
+ bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
+
+ int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
+ int addUsedOffsets(int binding, int offset, int numOffsets);
+ bool addUsedConstantId(int id);
+ int computeTypeLocationSize(const TType&) const;
+
+ bool setXfbBufferStride(int buffer, unsigned stride)
+ {
+ if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
+ return xfbBuffers[buffer].stride == stride;
+ xfbBuffers[buffer].stride = stride;
+ return true;
+ }
+ int addXfbBufferOffset(const TType&);
+ unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
+ static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
+
+protected:
+ TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
+ void error(TInfoSink& infoSink, const char*);
+ void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
+ void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
+ void mergeImplicitArraySizes(TType&, const TType&);
+ void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
+ void checkCallGraphCycles(TInfoSink&);
+ void inOutLocationCheck(TInfoSink&);
+ TIntermSequence& findLinkerObjects() const;
+ bool userOutputUsed() const;
+ static int getBaseAlignmentScalar(const TType&, int& size);
+ bool isSpecializationOperation(const TIntermOperator&) const;
+
+ const EShLanguage language; // stage, known at construction time
+ EShSource source; // source language, known a bit later
+ std::string entryPoint;
+ EProfile profile;
+ int version;
+ int spv;
+ TIntermNode* treeRoot;
+ std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
+ TBuiltInResource resources;
+ int numMains;
+ int numErrors;
+ int numPushConstants;
+ bool recursive;
+ int invocations;
+ int vertices;
+ TLayoutGeometry inputPrimitive;
+ TLayoutGeometry outputPrimitive;
+ bool pixelCenterInteger;
+ bool originUpperLeft;
+ TVertexSpacing vertexSpacing;
+ TVertexOrder vertexOrder;
+ bool pointMode;
+ int localSize[3];
+ int localSizeSpecId[3];
+ bool earlyFragmentTests;
+ TLayoutDepth depthLayout;
+ bool depthReplacing;
+ int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift
+ bool xfbMode;
+ bool multiStream;
+
+ typedef std::list<TCall> TGraph;
+ TGraph callGraph;
+
+ std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
+ std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
+ std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
+ std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
+ std::unordered_set<int> usedConstantId; // specialization constant ids used
+
+private:
+ void operator=(TIntermediate&); // prevent assignments
+};
+
+} // end namespace glslang
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp
new file mode 100644
index 00000000000..90621d39f47
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp
@@ -0,0 +1,210 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Travarse a tree of constants to create a single folded constant.
+// It should only be used when the whole tree is known to be constant.
+//
+
+#include "ParseHelper.h"
+
+namespace glslang {
+
+class TConstTraverser : public TIntermTraverser {
+public:
+ TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
+ : unionArray(cUnion), type(t),
+ constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
+ matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
+
+ virtual void visitConstantUnion(TIntermConstantUnion* node);
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+
+ int index;
+ TConstUnionArray unionArray;
+ TOperator tOp;
+ const TType& type;
+ TOperator constructorType;
+ bool singleConstantParam;
+ bool error;
+ int size; // size of the constructor ( 4 for vec4)
+ bool isMatrix;
+ int matrixCols;
+ int matrixRows;
+
+protected:
+ TConstTraverser(TConstTraverser&);
+ TConstTraverser& operator=(TConstTraverser&);
+};
+
+bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (! node->isConstructor() && node->getOp() != EOpComma) {
+ error = true;
+
+ return false;
+ }
+
+ if (node->getSequence().size() == 0) {
+ error = true;
+
+ return false;
+ }
+
+ bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+ if (flag) {
+ singleConstantParam = true;
+ constructorType = node->getOp();
+ size = node->getType().computeNumComponents();
+
+ if (node->getType().isMatrix()) {
+ isMatrix = true;
+ matrixCols = node->getType().getMatrixCols();
+ matrixRows = node->getType().getMatrixRows();
+ }
+ }
+
+ for (TIntermSequence::iterator p = node->getSequence().begin();
+ p != node->getSequence().end(); p++) {
+
+ if (node->getOp() == EOpComma)
+ index = 0;
+
+ (*p)->traverse(this);
+ }
+ if (flag)
+ {
+ singleConstantParam = false;
+ constructorType = EOpNull;
+ size = 0;
+ isMatrix = false;
+ matrixCols = 0;
+ matrixRows = 0;
+ }
+
+ return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ TConstUnionArray leftUnionArray(unionArray);
+ int instanceSize = type.computeNumComponents();
+
+ if (index >= instanceSize)
+ return;
+
+ if (! singleConstantParam) {
+ int rightUnionSize = node->getType().computeNumComponents();
+
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ for (int i = 0; i < rightUnionSize; i++) {
+ if (index >= instanceSize)
+ return;
+ leftUnionArray[index] = rightUnionArray[i];
+
+ index++;
+ }
+ } else {
+ int endIndex = index + size;
+ const TConstUnionArray& rightUnionArray = node->getConstArray();
+ if (! isMatrix) {
+ int count = 0;
+ int nodeComps = node->getType().computeNumComponents();
+ for (int i = index; i < endIndex; i++) {
+ if (i >= instanceSize)
+ return;
+
+ leftUnionArray[i] = rightUnionArray[count];
+
+ (index)++;
+
+ if (nodeComps > 1)
+ count++;
+ }
+ } else {
+ // constructing a matrix, but from what?
+ if (node->isMatrix()) {
+ // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
+ // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
+ // identity matrix.
+ for (int c = 0; c < matrixCols; ++c) {
+ for (int r = 0; r < matrixRows; ++r) {
+ int targetOffset = index + c * matrixRows + r;
+ if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
+ int srcOffset = c * node->getType().getMatrixRows() + r;
+ leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
+ } else if (r == c)
+ leftUnionArray[targetOffset].setDConst(1.0);
+ else
+ leftUnionArray[targetOffset].setDConst(0.0);
+ }
+ }
+ } else {
+ // matrix from vector
+ int count = 0;
+ const int startIndex = index;
+ int nodeComps = node->getType().computeNumComponents();
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i >= instanceSize)
+ return;
+ if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+ leftUnionArray[i] = rightUnionArray[count];
+ else
+ leftUnionArray[i].setDConst(0.0);
+
+ index++;
+
+ if (nodeComps > 1)
+ count++;
+ }
+ }
+ }
+ }
+}
+
+bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
+{
+ if (root == 0)
+ return false;
+
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
+
+ root->traverse(&it);
+ if (it.error)
+ return true;
+ else
+ return false;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/parseVersions.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/parseVersions.h
new file mode 100755
index 00000000000..0eebb10aec2
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/parseVersions.h
@@ -0,0 +1,135 @@
+//
+//Copyright (C) 2016 Google, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+// This is implemented in Versions.cpp
+
+#ifndef _PARSE_VERSIONS_INCLUDED_
+#define _PARSE_VERSIONS_INCLUDED_
+
+#include "../Public/ShaderLang.h"
+#include "../Include/InfoSink.h"
+#include "Scan.h"
+
+#include <map>
+
+namespace glslang {
+
+//
+// Base class for parse helpers.
+// This just has version-related information and checking.
+// This class should be sufficient for preprocessing.
+//
+class TParseVersions {
+public:
+ TParseVersions(TIntermediate& interm, int version, EProfile profile,
+ int spv, int vulkan, EShLanguage language, TInfoSink& infoSink,
+ bool forwardCompatible, EShMessages messages)
+ : infoSink(infoSink), version(version), profile(profile), language(language),
+ spv(spv), vulkan(vulkan), forwardCompatible(forwardCompatible),
+ intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { }
+ virtual ~TParseVersions() { }
+ virtual void initializeExtensionBehavior();
+ virtual void requireProfile(const TSourceLoc&, int queryProfiles, const char* featureDesc);
+ virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc);
+ virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, const char* const extension, const char* featureDesc);
+ virtual void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc);
+ virtual void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
+ virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
+ virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
+ virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
+ virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
+ virtual TExtensionBehavior getExtensionBehavior(const char*);
+ virtual bool extensionTurnedOn(const char* const extension);
+ virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
+ virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
+ virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
+ virtual void doubleCheck(const TSourceLoc&, const char* op);
+ virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
+ virtual void spvRemoved(const TSourceLoc&, const char* op);
+ virtual void vulkanRemoved(const TSourceLoc&, const char* op);
+ virtual void requireVulkan(const TSourceLoc&, const char* op);
+ virtual void requireSpv(const TSourceLoc&, const char* op);
+ virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
+ virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
+
+ virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+ virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+ virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+ virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
+ const char* szExtraInfoFormat, ...) = 0;
+
+ void addError() { ++numErrors; }
+ int getNumErrors() const { return numErrors; }
+
+ void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
+ TInputScanner* getScanner() const { return currentScanner; }
+ const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
+ void setCurrentLine(int line) { currentScanner->setLine(line); }
+ void setCurrentColumn(int col) { currentScanner->setColumn(col); }
+ void setCurrentSourceName(const char* name) { currentScanner->setFile(name); }
+ void setCurrentString(int string) { currentScanner->setString(string); }
+
+ void getPreamble(std::string&);
+ bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }
+ bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
+
+ TInfoSink& infoSink;
+
+ // compilation mode
+ int version; // version, updated by #version in the shader
+ EProfile profile; // the declared profile in the shader (core by default)
+ EShLanguage language; // really the stage
+ int spv; // SPIR-V version; 0 means not SPIR-V
+ int vulkan; // Vulkan version; 0 means not vulkan
+ bool forwardCompatible; // true if errors are to be given for use of deprecated features
+ TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
+
+protected:
+ EShMessages messages; // errors/warnings/rule-sets
+ int numErrors; // number of compile-time errors encountered
+ TInputScanner* currentScanner;
+
+private:
+ TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
+ explicit TParseVersions(const TParseVersions&);
+ TParseVersions& operator=(const TParseVersions&);
+};
+
+} // end namespace glslang
+
+#endif // _PARSE_VERSIONS_INCLUDED_
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp
new file mode 100644
index 00000000000..35097588c43
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp
@@ -0,0 +1,1151 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.c
+//
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <sstream>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+
+namespace glslang {
+
+int TPpContext::InitCPP()
+{
+ pool = mem_CreatePool(0, 0);
+
+ return 1;
+}
+
+// Handle #define
+int TPpContext::CPPdefine(TPpToken* ppToken)
+{
+ MacroSymbol mac;
+ Symbol *symb;
+
+ // get macro name
+ int token = scanToken(ppToken);
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", "");
+ return token;
+ }
+ if (ppToken->loc.string >= 0) {
+ // We are in user code; check for reserved name use:
+ parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define");
+ }
+
+ // save the original atom
+ const int defAtom = ppToken->atom;
+
+ // gather parameters to the macro, between (...)
+ token = scanToken(ppToken);
+ if (token == '(' && ! ppToken->space) {
+ int argc = 0;
+ int args[maxMacroArgs];
+ do {
+ token = scanToken(ppToken);
+ if (argc == 0 && token == ')')
+ break;
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "bad argument", "#define", "");
+
+ return token;
+ }
+ // check for duplication of parameter name
+ bool duplicate = false;
+ for (int a = 0; a < argc; ++a) {
+ if (args[a] == ppToken->atom) {
+ parseContext.ppError(ppToken->loc, "duplicate macro parameter", "#define", "");
+ duplicate = true;
+ break;
+ }
+ }
+ if (! duplicate) {
+ if (argc < maxMacroArgs)
+ args[argc++] = ppToken->atom;
+ else
+ parseContext.ppError(ppToken->loc, "too many macro parameters", "#define", "");
+ }
+ token = scanToken(ppToken);
+ } while (token == ',');
+ if (token != ')') {
+ parseContext.ppError(ppToken->loc, "missing parenthesis", "#define", "");
+
+ return token;
+ }
+ mac.argc = argc;
+ mac.args = (int*)mem_Alloc(pool, argc * sizeof(int));
+ memcpy(mac.args, args, argc * sizeof(int));
+ token = scanToken(ppToken);
+ }
+
+ // record the definition of the macro
+ TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
+ mac.body = new TokenStream;
+ while (token != '\n' && token != EndOfInput) {
+ RecordToken(mac.body, token, ppToken);
+ token = scanToken(ppToken);
+ if (token != '\n' && ppToken->space)
+ RecordToken(mac.body, ' ', ppToken);
+ }
+
+ // check for duplicate definition
+ symb = LookUpSymbol(defAtom);
+ if (symb) {
+ if (! symb->mac.undef) {
+ // Already defined -- need to make sure they are identical:
+ // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
+ // ordering, spelling, and white-space separation, where all white-space separations are considered identical."
+ if (symb->mac.argc != mac.argc)
+ parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", GetAtomString(defAtom));
+ else {
+ for (int argc = 0; argc < mac.argc; argc++) {
+ if (symb->mac.args[argc] != mac.args[argc])
+ parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", GetAtomString(defAtom));
+ }
+ RewindTokenStream(symb->mac.body);
+ RewindTokenStream(mac.body);
+ int newToken;
+ do {
+ int oldToken;
+ TPpToken oldPpToken;
+ TPpToken newPpToken;
+ oldToken = ReadToken(symb->mac.body, &oldPpToken);
+ newToken = ReadToken(mac.body, &newPpToken);
+ if (oldToken != newToken || oldPpToken != newPpToken) {
+ parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", GetAtomString(defAtom));
+ break;
+ }
+ } while (newToken > 0);
+ }
+ }
+ } else
+ symb = AddSymbol(defAtom);
+
+ delete symb->mac.body;
+ symb->mac = mac;
+
+ return '\n';
+}
+
+// Handle #undef
+int TPpContext::CPPundef(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ Symbol *symb;
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#undef", "");
+
+ return token;
+ }
+
+ parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#undef");
+
+ symb = LookUpSymbol(ppToken->atom);
+ if (symb) {
+ symb->mac.undef = 1;
+ }
+ token = scanToken(ppToken);
+ if (token != '\n')
+ parseContext.ppError(ppToken->loc, "can only be followed by a single macro name", "#undef", "");
+
+ return token;
+}
+
+// Handle #else
+/* Skip forward to appropriate spot. This is used both
+** to skip to a #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false.
+*/
+int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
+{
+ int atom;
+ int depth = 0;
+ int token = scanToken(ppToken);
+
+ while (token != EndOfInput) {
+ if (token != '#') {
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+
+ if (token == EndOfInput)
+ return token;
+
+ token = scanToken(ppToken);
+ continue;
+ }
+
+ if ((token = scanToken(ppToken)) != PpAtomIdentifier)
+ continue;
+
+ atom = ppToken->atom;
+ if (atom == PpAtomIf || atom == PpAtomIfdef || atom == PpAtomIfndef) {
+ depth++;
+ ifdepth++;
+ elsetracker++;
+ } else if (atom == PpAtomEndif) {
+ token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
+ elseSeen[elsetracker] = false;
+ --elsetracker;
+ if (depth == 0) {
+ // found the #endif we are looking for
+ if (ifdepth)
+ --ifdepth;
+ break;
+ }
+ --depth;
+ --ifdepth;
+ } else if (matchelse && depth == 0) {
+ if (atom == PpAtomElse) {
+ elseSeen[elsetracker] = true;
+ token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
+ // found the #else we are looking for
+ break;
+ } else if (atom == PpAtomElif) {
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
+ /* we decrement ifdepth here, because CPPif will increment
+ * it and we really want to leave it alone */
+ if (ifdepth) {
+ --ifdepth;
+ elseSeen[elsetracker] = false;
+ --elsetracker;
+ }
+
+ return CPPif(ppToken);
+ }
+ } else if (atom == PpAtomElse) {
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
+ else
+ elseSeen[elsetracker] = true;
+ token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
+ } else if (atom == PpAtomElif) {
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
+ }
+ }
+
+ return token;
+}
+
+// Call when there should be no more tokens left on a line.
+int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token)
+{
+ if (token != '\n' && token != EndOfInput) {
+ static const char* message = "unexpected tokens following directive";
+
+ const char* label;
+ if (atom == PpAtomElse)
+ label = "#else";
+ else if (atom == PpAtomElif)
+ label = "#elif";
+ else if (atom == PpAtomEndif)
+ label = "#endif";
+ else if (atom == PpAtomIf)
+ label = "#if";
+ else if (atom == PpAtomLine)
+ label = "#line";
+ else
+ label = "";
+
+ if (parseContext.relaxedErrors())
+ parseContext.ppWarn(ppToken->loc, message, label, "");
+ else
+ parseContext.ppError(ppToken->loc, message, label, "");
+
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+ }
+
+ return token;
+}
+
+enum eval_prec {
+ MIN_PRECEDENCE,
+ COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+ MAX_PRECEDENCE
+};
+
+namespace {
+
+ int op_logor(int a, int b) { return a || b; }
+ int op_logand(int a, int b) { return a && b; }
+ int op_or(int a, int b) { return a | b; }
+ int op_xor(int a, int b) { return a ^ b; }
+ int op_and(int a, int b) { return a & b; }
+ int op_eq(int a, int b) { return a == b; }
+ int op_ne(int a, int b) { return a != b; }
+ int op_ge(int a, int b) { return a >= b; }
+ int op_le(int a, int b) { return a <= b; }
+ int op_gt(int a, int b) { return a > b; }
+ int op_lt(int a, int b) { return a < b; }
+ int op_shl(int a, int b) { return a << b; }
+ int op_shr(int a, int b) { return a >> b; }
+ int op_add(int a, int b) { return a + b; }
+ int op_sub(int a, int b) { return a - b; }
+ int op_mul(int a, int b) { return a * b; }
+ int op_div(int a, int b) { return a / b; }
+ int op_mod(int a, int b) { return a % b; }
+ int op_pos(int a) { return a; }
+ int op_neg(int a) { return -a; }
+ int op_cmpl(int a) { return ~a; }
+ int op_not(int a) { return !a; }
+
+};
+
+struct TBinop {
+ int token, precedence, (*op)(int, int);
+} binop[] = {
+ { PpAtomOr, LOGOR, op_logor },
+ { PpAtomAnd, LOGAND, op_logand },
+ { '|', OR, op_or },
+ { '^', XOR, op_xor },
+ { '&', AND, op_and },
+ { PpAtomEQ, EQUAL, op_eq },
+ { PpAtomNE, EQUAL, op_ne },
+ { '>', RELATION, op_gt },
+ { PpAtomGE, RELATION, op_ge },
+ { '<', RELATION, op_lt },
+ { PpAtomLE, RELATION, op_le },
+ { PpAtomLeft, SHIFT, op_shl },
+ { PpAtomRight, SHIFT, op_shr },
+ { '+', ADD, op_add },
+ { '-', ADD, op_sub },
+ { '*', MUL, op_mul },
+ { '/', MUL, op_div },
+ { '%', MUL, op_mod },
+};
+
+struct TUnop {
+ int token, (*op)(int);
+} unop[] = {
+ { '+', op_pos },
+ { '-', op_neg },
+ { '~', op_cmpl },
+ { '!', op_not },
+};
+
+#define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0]))
+
+int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
+{
+ TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error
+ if (token == PpAtomIdentifier) {
+ if (ppToken->atom == PpAtomDefined) {
+ bool needclose = 0;
+ token = scanToken(ppToken);
+ if (token == '(') {
+ needclose = true;
+ token = scanToken(ppToken);
+ }
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ Symbol* s = LookUpSymbol(ppToken->atom);
+ res = s ? ! s->mac.undef : 0;
+ token = scanToken(ppToken);
+ if (needclose) {
+ if (token != ')') {
+ parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ token = scanToken(ppToken);
+ }
+ } else {
+ token = evalToToken(token, shortCircuit, res, err, ppToken);
+ return eval(token, precedence, shortCircuit, res, err, ppToken);
+ }
+ } else if (token == PpAtomConstInt) {
+ res = ppToken->ival;
+ token = scanToken(ppToken);
+ } else if (token == '(') {
+ token = scanToken(ppToken);
+ token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken);
+ if (! err) {
+ if (token != ')') {
+ parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ token = scanToken(ppToken);
+ }
+ } else {
+ int op = NUM_ELEMENTS(unop) - 1;
+ for (; op >= 0; op--) {
+ if (unop[op].token == token)
+ break;
+ }
+ if (op >= 0) {
+ token = scanToken(ppToken);
+ token = eval(token, UNARY, shortCircuit, res, err, ppToken);
+ res = unop[op].op(res);
+ } else {
+ parseContext.ppError(loc, "bad expression", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+
+ return token;
+ }
+ }
+
+ token = evalToToken(token, shortCircuit, res, err, ppToken);
+
+ // Perform evaluation of binary operation, if there is one, otherwise we are done.
+ while (! err) {
+ if (token == ')' || token == '\n')
+ break;
+ int op;
+ for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) {
+ if (binop[op].token == token)
+ break;
+ }
+ if (op < 0 || binop[op].precedence <= precedence)
+ break;
+ int leftSide = res;
+
+ // Setup short-circuiting, needed for ES, unless already in a short circuit.
+ // (Once in a short-circuit, can't turn off again, until that whole subexpression is done.
+ if (! shortCircuit) {
+ if ((token == PpAtomOr && leftSide == 1) ||
+ (token == PpAtomAnd && leftSide == 0))
+ shortCircuit = true;
+ }
+
+ token = scanToken(ppToken);
+ token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken);
+
+ if (binop[op].op == op_div || binop[op].op == op_mod) {
+ if (res == 0) {
+ parseContext.ppError(loc, "division by 0", "preprocessor evaluation", "");
+ res = 1;
+ }
+ }
+ res = binop[op].op(leftSide, res);
+ }
+
+ return token;
+}
+
+// Expand macros, skipping empty expansions, to get to the first real token in those expansions.
+int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
+{
+ while (token == PpAtomIdentifier && ppToken->atom != PpAtomDefined) {
+ int macroReturn = MacroExpand(ppToken->atom, ppToken, true, false);
+ if (macroReturn == 0) {
+ parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
+ err = true;
+ res = 0;
+ token = scanToken(ppToken);
+ break;
+ }
+ if (macroReturn == -1) {
+ if (! shortCircuit && parseContext.profile == EEsProfile) {
+ const char* message = "undefined macro in expression not allowed in es profile";
+ if (parseContext.relaxedErrors())
+ parseContext.ppWarn(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
+ else
+ parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
+ }
+ }
+ token = scanToken(ppToken);
+ }
+
+ return token;
+}
+
+// Handle #if
+int TPpContext::CPPif(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ elsetracker++;
+ ifdepth++;
+ if (ifdepth > maxIfNesting) {
+ parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", "");
+ return 0;
+ }
+ int res = 0;
+ bool err = false;
+ token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken);
+ token = extraTokenCheck(PpAtomIf, ppToken, token);
+ if (!res && !err)
+ token = CPPelse(1, ppToken);
+
+ return token;
+}
+
+// Handle #ifdef
+int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ int name = ppToken->atom;
+ if (++ifdepth > maxIfNesting) {
+ parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", "");
+ return 0;
+ }
+ elsetracker++;
+ if (token != PpAtomIdentifier) {
+ if (defined)
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", "");
+ else
+ parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifndef", "");
+ } else {
+ Symbol *s = LookUpSymbol(name);
+ token = scanToken(ppToken);
+ if (token != '\n') {
+ parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", "");
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+ }
+ if (((s && !s->mac.undef) ? 1 : 0) != defined)
+ token = CPPelse(1, ppToken);
+ }
+
+ return token;
+}
+
+// Handle #include
+int TPpContext::CPPinclude(TPpToken* ppToken)
+{
+ const TSourceLoc directiveLoc = ppToken->loc;
+ int token = scanToken(ppToken);
+ if (token != PpAtomConstString) {
+ // TODO: handle angle brackets.
+ parseContext.ppError(directiveLoc, "must be followed by a file designation", "#include", "");
+ } else {
+ // Make a copy of the name because it will be overwritten by the next token scan.
+ const std::string filename = ppToken->name;
+ token = scanToken(ppToken);
+ if (token != '\n' && token != EndOfInput) {
+ parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", "");
+ } else {
+ TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), TShader::Includer::EIncludeRelative, currentSourceFile.c_str(), includeStack.size() + 1);
+ if (res && !res->file_name.empty()) {
+ if (res->file_data && res->file_length) {
+ const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
+ std::ostringstream prologue;
+ std::ostringstream epilogue;
+ prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n";
+ epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n";
+ pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this));
+ }
+ // At EOF, there's no "current" location anymore.
+ if (token != EndOfInput) parseContext.setCurrentColumn(0);
+ // Don't accidentally return EndOfInput, which will end all preprocessing.
+ return '\n';
+ } else {
+ std::string message =
+ res ? std::string(res->file_data, res->file_length)
+ : std::string("Could not process include directive");
+ parseContext.ppError(directiveLoc, message.c_str(), "#include", "");
+ if (res) {
+ includer.releaseInclude(res);
+ }
+ }
+ }
+ }
+ return token;
+}
+
+// Handle #line
+int TPpContext::CPPline(TPpToken* ppToken)
+{
+ // "#line must have, after macro substitution, one of the following forms:
+ // "#line line
+ // "#line line source-string-number"
+
+ int token = scanToken(ppToken);
+ const TSourceLoc directiveLoc = ppToken->loc;
+ if (token == '\n') {
+ parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", "");
+ return token;
+ }
+
+ int lineRes = 0; // Line number after macro expansion.
+ int lineToken = 0;
+ bool hasFile = false;
+ int fileRes = 0; // Source file number after macro expansion.
+ const char* sourceName = nullptr; // Optional source file name.
+ bool lineErr = false;
+ bool fileErr = false;
+ token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
+ if (! lineErr) {
+ lineToken = lineRes;
+ if (token == '\n')
+ ++lineRes;
+
+ if (parseContext.lineDirectiveShouldSetNextLine())
+ --lineRes;
+ parseContext.setCurrentLine(lineRes);
+
+ if (token != '\n') {
+ if (token == PpAtomConstString) {
+ parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line");
+ // We need to save a copy of the string instead of pointing
+ // to the name field of the token since the name field
+ // will likely be overwritten by the next token scan.
+ sourceName = GetAtomString(LookUpAddString(ppToken->name));
+ parseContext.setCurrentSourceName(sourceName);
+ hasFile = true;
+ token = scanToken(ppToken);
+ } else {
+ token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken);
+ if (! fileErr) {
+ parseContext.setCurrentString(fileRes);
+ hasFile = true;
+ }
+ }
+ }
+ }
+ if (!fileErr && !lineErr) {
+ parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName);
+ }
+ token = extraTokenCheck(PpAtomLine, ppToken, token);
+
+ return token;
+}
+
+// Handle #error
+int TPpContext::CPPerror(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+ std::string message;
+ TSourceLoc loc = ppToken->loc;
+
+ while (token != '\n' && token != EndOfInput) {
+ if (token == PpAtomConstInt || token == PpAtomConstUint ||
+ token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
+ token == PpAtomConstFloat || token == PpAtomConstDouble) {
+ message.append(ppToken->name);
+ } else if (token == PpAtomIdentifier || token == PpAtomConstString) {
+ message.append(ppToken->name);
+ } else {
+ message.append(GetAtomString(token));
+ }
+ message.append(" ");
+ token = scanToken(ppToken);
+ }
+ parseContext.notifyErrorDirective(loc.line, message.c_str());
+ //store this msg into the shader's information log..set the Compile Error flag!!!!
+ parseContext.ppError(loc, message.c_str(), "#error", "");
+
+ return '\n';
+}
+
+// Handle #pragma
+int TPpContext::CPPpragma(TPpToken* ppToken)
+{
+ char SrcStrName[2];
+ TVector<TString> tokens;
+
+ TSourceLoc loc = ppToken->loc; // because we go to the next line before processing
+ int token = scanToken(ppToken);
+ while (token != '\n' && token != EndOfInput) {
+ switch (token) {
+ case PpAtomIdentifier:
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ case PpAtomConstFloat:
+ case PpAtomConstDouble:
+ tokens.push_back(ppToken->name);
+ break;
+ default:
+ SrcStrName[0] = (char)token;
+ SrcStrName[1] = '\0';
+ tokens.push_back(SrcStrName);
+ }
+ token = scanToken(ppToken);
+ }
+
+ if (token == EndOfInput)
+ parseContext.ppError(loc, "directive must end with a newline", "#pragma", "");
+ else
+ parseContext.handlePragma(loc, tokens);
+
+ return token;
+}
+
+// #version: This is just for error checking: the version and profile are decided before preprocessing starts
+int TPpContext::CPPversion(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+
+ if (errorOnVersion || versionSeen)
+ parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", "");
+ versionSeen = true;
+
+ if (token == '\n') {
+ parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", "");
+
+ return token;
+ }
+
+ if (token != PpAtomConstInt)
+ parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", "");
+
+ ppToken->ival = atoi(ppToken->name);
+ int versionNumber = ppToken->ival;
+ int line = ppToken->loc.line;
+ token = scanToken(ppToken);
+
+ if (token == '\n') {
+ parseContext.notifyVersion(line, versionNumber, nullptr);
+ return token;
+ } else {
+ if (ppToken->atom != PpAtomCore &&
+ ppToken->atom != PpAtomCompatibility &&
+ ppToken->atom != PpAtomEs)
+ parseContext.ppError(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", "");
+ parseContext.notifyVersion(line, versionNumber, ppToken->name);
+ token = scanToken(ppToken);
+
+ if (token == '\n')
+ return token;
+ else
+ parseContext.ppError(ppToken->loc, "bad tokens following profile -- expected newline", "#version", "");
+ }
+
+ return token;
+}
+
+// Handle #extension
+int TPpContext::CPPextension(TPpToken* ppToken)
+{
+ int line = ppToken->loc.line;
+ int token = scanToken(ppToken);
+ char extensionName[MaxTokenLength + 1];
+
+ if (token=='\n') {
+ parseContext.ppError(ppToken->loc, "extension name not specified", "#extension", "");
+ return token;
+ }
+
+ if (token != PpAtomIdentifier)
+ parseContext.ppError(ppToken->loc, "extension name expected", "#extension", "");
+
+ assert(strlen(ppToken->name) <= MaxTokenLength);
+ strcpy(extensionName, ppToken->name);
+
+ token = scanToken(ppToken);
+ if (token != ':') {
+ parseContext.ppError(ppToken->loc, "':' missing after extension name", "#extension", "");
+ return token;
+ }
+
+ token = scanToken(ppToken);
+ if (token != PpAtomIdentifier) {
+ parseContext.ppError(ppToken->loc, "behavior for extension not specified", "#extension", "");
+ return token;
+ }
+
+ parseContext.updateExtensionBehavior(line, extensionName, ppToken->name);
+ parseContext.notifyExtensionDirective(line, extensionName, ppToken->name);
+
+ token = scanToken(ppToken);
+ if (token == '\n')
+ return token;
+ else
+ parseContext.ppError(ppToken->loc, "extra tokens -- expected newline", "#extension","");
+
+ return token;
+}
+
+int TPpContext::readCPPline(TPpToken* ppToken)
+{
+ int token = scanToken(ppToken);
+
+ if (token == PpAtomIdentifier) {
+ switch (ppToken->atom) {
+ case PpAtomDefine:
+ token = CPPdefine(ppToken);
+ break;
+ case PpAtomElse:
+ if (elsetracker[elseSeen])
+ parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
+ elsetracker[elseSeen] = true;
+ if (! ifdepth)
+ parseContext.ppError(ppToken->loc, "mismatched statements", "#else", "");
+ token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken));
+ token = CPPelse(0, ppToken);
+ break;
+ case PpAtomElif:
+ if (! ifdepth)
+ parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", "");
+ if (elseSeen[elsetracker])
+ parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
+ // this token is really a dont care, but we still need to eat the tokens
+ token = scanToken(ppToken);
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+ token = CPPelse(0, ppToken);
+ break;
+ case PpAtomEndif:
+ if (! ifdepth)
+ parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", "");
+ else {
+ elseSeen[elsetracker] = false;
+ --elsetracker;
+ --ifdepth;
+ }
+ token = extraTokenCheck(PpAtomEndif, ppToken, scanToken(ppToken));
+ break;
+ case PpAtomIf:
+ token = CPPif(ppToken);
+ break;
+ case PpAtomIfdef:
+ token = CPPifdef(1, ppToken);
+ break;
+ case PpAtomIfndef:
+ token = CPPifdef(0, ppToken);
+ break;
+ case PpAtomInclude:
+ parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include");
+ token = CPPinclude(ppToken);
+ break;
+ case PpAtomLine:
+ token = CPPline(ppToken);
+ break;
+ case PpAtomPragma:
+ token = CPPpragma(ppToken);
+ break;
+ case PpAtomUndef:
+ token = CPPundef(ppToken);
+ break;
+ case PpAtomError:
+ token = CPPerror(ppToken);
+ break;
+ case PpAtomVersion:
+ token = CPPversion(ppToken);
+ break;
+ case PpAtomExtension:
+ token = CPPextension(ppToken);
+ break;
+ default:
+ parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name);
+ break;
+ }
+ } else if (token != '\n' && token != EndOfInput)
+ parseContext.ppError(ppToken->loc, "invalid directive", "#", "");
+
+ while (token != '\n' && token != EndOfInput)
+ token = scanToken(ppToken);
+
+ return token;
+}
+
+TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream* a, TPpToken* ppToken, bool newLineOkay)
+{
+ int token;
+ TokenStream *n;
+ RewindTokenStream(a);
+ do {
+ token = ReadToken(a, ppToken);
+ if (token == PpAtomIdentifier && LookUpSymbol(ppToken->atom))
+ break;
+ } while (token != EndOfInput);
+
+ if (token == EndOfInput)
+ return a;
+
+ n = new TokenStream;
+ pushInput(new tMarkerInput(this));
+ pushTokenStreamInput(a);
+ while ((token = scanToken(ppToken)) != tMarkerInput::marker) {
+ if (token == PpAtomIdentifier && MacroExpand(ppToken->atom, ppToken, false, newLineOkay) != 0)
+ continue;
+ RecordToken(n, token, ppToken);
+ }
+ popInput();
+ delete a;
+
+ return n;
+}
+
+//
+// Return the next token for a macro expansion, handling macro args.
+//
+int TPpContext::tMacroInput::scan(TPpToken* ppToken)
+{
+ int token;
+ do {
+ token = pp->ReadToken(mac->body, ppToken);
+ } while (token == ' '); // handle white space in macro
+
+ // TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding
+ if (token == PpAtomIdentifier) {
+ int i;
+ for (i = mac->argc - 1; i >= 0; i--)
+ if (mac->args[i] == ppToken->atom)
+ break;
+ if (i >= 0) {
+ pp->pushTokenStreamInput(args[i]);
+
+ return pp->scanToken(ppToken);
+ }
+ }
+
+ if (token == EndOfInput)
+ mac->busy = 0;
+
+ return token;
+}
+
+// return a textual zero, for scanning a macro that was never defined
+int TPpContext::tZeroInput::scan(TPpToken* ppToken)
+{
+ if (done)
+ return EndOfInput;
+
+ strcpy(ppToken->name, "0");
+ ppToken->ival = 0;
+ ppToken->space = false;
+ done = true;
+
+ return PpAtomConstInt;
+}
+
+//
+// Check an identifier (atom) to see if it is a macro that should be expanded.
+// If it is, and defined, push a tInput that will produce the appropriate expansion
+// and return 1.
+// If it is, but undefined, and expandUndef is requested, push a tInput that will
+// expand to 0 and return -1.
+// Otherwise, return 0 to indicate no expansion, which is not necessarily an error.
+//
+int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay)
+{
+ ppToken->space = false;
+ switch (atom) {
+ case PpAtomLineMacro:
+ ppToken->ival = parseContext.getCurrentLoc().line;
+ snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
+ UngetToken(PpAtomConstInt, ppToken);
+ return 1;
+
+ case PpAtomFileMacro: {
+ if (parseContext.getCurrentLoc().name)
+ parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__");
+ ppToken->ival = parseContext.getCurrentLoc().string;
+ snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str());
+ UngetToken(PpAtomConstInt, ppToken);
+ return 1;
+ }
+
+ case PpAtomVersionMacro:
+ ppToken->ival = parseContext.version;
+ snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
+ UngetToken(PpAtomConstInt, ppToken);
+ return 1;
+
+ default:
+ break;
+ }
+
+ Symbol *sym = LookUpSymbol(atom);
+ int token;
+ int depth = 0;
+
+ // no recursive expansions
+ if (sym && sym->mac.busy)
+ return 0;
+
+ // not expanding undefined macros
+ if ((! sym || sym->mac.undef) && ! expandUndef)
+ return 0;
+
+ // 0 is the value of an undefined macro
+ if ((! sym || sym->mac.undef) && expandUndef) {
+ pushInput(new tZeroInput(this));
+ return -1;
+ }
+
+ tMacroInput *in = new tMacroInput(this);
+
+ TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
+ in->mac = &sym->mac;
+ if (sym->mac.args) {
+ token = scanToken(ppToken);
+ if (newLineOkay) {
+ while (token == '\n')
+ token = scanToken(ppToken);
+ }
+ if (token != '(') {
+ parseContext.ppError(loc, "expected '(' following", "macro expansion", GetAtomString(atom));
+ UngetToken(token, ppToken);
+ ppToken->atom = atom;
+
+ delete in;
+ return 0;
+ }
+ in->args.resize(in->mac->argc);
+ for (int i = 0; i < in->mac->argc; i++)
+ in->args[i] = new TokenStream;
+ int arg = 0;
+ bool tokenRecorded = false;
+ do {
+ depth = 0;
+ while (1) {
+ token = scanToken(ppToken);
+ if (token == EndOfInput) {
+ parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom));
+ delete in;
+ return 0;
+ }
+ if (token == '\n') {
+ if (! newLineOkay) {
+ parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", GetAtomString(atom));
+ delete in;
+ return 0;
+ }
+ continue;
+ }
+ if (token == '#') {
+ parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom));
+ delete in;
+ return 0;
+ }
+ if (in->mac->argc == 0 && token != ')')
+ break;
+ if (depth == 0 && (token == ',' || token == ')'))
+ break;
+ if (token == '(')
+ depth++;
+ if (token == ')')
+ depth--;
+ RecordToken(in->args[arg], token, ppToken);
+ tokenRecorded = true;
+ }
+ if (token == ')') {
+ if (in->mac->argc == 1 && tokenRecorded == 0)
+ break;
+ arg++;
+ break;
+ }
+ arg++;
+ } while (arg < in->mac->argc);
+
+ if (arg < in->mac->argc)
+ parseContext.ppError(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom));
+ else if (token != ')') {
+ depth=0;
+ while (token != EndOfInput && (depth > 0 || token != ')')) {
+ if (token == ')')
+ depth--;
+ token = scanToken(ppToken);
+ if (token == '(')
+ depth++;
+ }
+
+ if (token == EndOfInput) {
+ parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom));
+ delete in;
+ return 0;
+ }
+ parseContext.ppError(loc, "Too many args in macro", "macro expansion", GetAtomString(atom));
+ }
+ for (int i = 0; i < in->mac->argc; i++)
+ in->args[i] = PrescanMacroArg(in->args[i], ppToken, newLineOkay);
+ }
+
+ pushInput(in);
+ sym->mac.busy = 1;
+ RewindTokenStream(sym->mac.body);
+
+ return 1;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp
new file mode 100644
index 00000000000..763b6b4e67b
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp
@@ -0,0 +1,192 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+//
+// atom.c
+//
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+
+namespace {
+
+using namespace glslang;
+
+const struct {
+ int val;
+ const char* str;
+} tokens[] = {
+ { PpAtomDefine, "define" },
+ { PpAtomDefined, "defined" },
+ { PpAtomUndef, "undef" },
+ { PpAtomIf, "if" },
+ { PpAtomElif, "elif" },
+ { PpAtomElse, "else" },
+ { PpAtomEndif, "endif" },
+ { PpAtomIfdef, "ifdef" },
+ { PpAtomIfndef, "ifndef" },
+ { PpAtomLine, "line" },
+ { PpAtomPragma, "pragma" },
+ { PpAtomError, "error" },
+
+ { PpAtomVersion, "version" },
+ { PpAtomCore, "core" },
+ { PpAtomCompatibility, "compatibility" },
+ { PpAtomEs, "es" },
+ { PpAtomExtension, "extension" },
+
+ { PpAtomLineMacro, "__LINE__" },
+ { PpAtomFileMacro, "__FILE__" },
+ { PpAtomVersionMacro, "__VERSION__" },
+
+ { PpAtomInclude, "include" },
+
+};
+
+} // end anonymous namespace
+
+namespace glslang {
+
+//
+// Map a new or existing string to an atom, inventing a new atom if necessary.
+//
+int TPpContext::LookUpAddString(const char* s)
+{
+ auto it = atomMap.find(s);
+ if (it == atomMap.end()) {
+ AddAtomFixed(s, nextAtom);
+ return nextAtom++;
+ } else
+ return it->second;
+}
+
+//
+// Map an already created atom to its string.
+//
+const char* TPpContext::GetAtomString(int atom)
+{
+ if ((size_t)atom >= stringMap.size())
+ return "<bad token>";
+
+ const TString* atomString = stringMap[atom];
+
+ return atomString ? atomString->c_str() : "<bad token>";
+}
+
+//
+// Add forced mapping of string to atom.
+//
+void TPpContext::AddAtomFixed(const char* s, int atom)
+{
+ auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
+ if (stringMap.size() < (size_t)atom + 1)
+ stringMap.resize(atom + 100, 0);
+ stringMap[atom] = &it->first;
+}
+
+//
+// Initialize the atom table.
+//
+void TPpContext::InitAtomTable()
+{
+ // Add single character tokens to the atom table:
+ const char* s = "~!%^&*()-+=|,.<>/?;:[]{}#\\";
+ char t[2];
+
+ t[1] = '\0';
+ while (*s) {
+ t[0] = *s;
+ AddAtomFixed(t, s[0]);
+ s++;
+ }
+
+ // Add multiple character scanner tokens :
+ for (size_t ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
+ AddAtomFixed(tokens[ii].str, tokens[ii].val);
+
+ nextAtom = PpAtomLast;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp
new file mode 100644
index 00000000000..6f0b8a9a11a
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp
@@ -0,0 +1,122 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "PpContext.h"
+
+namespace glslang {
+
+TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
+ preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false),
+ rootFileName(rootFileName),
+ currentSourceFile(rootFileName)
+{
+ InitAtomTable();
+ InitScanner();
+
+ ifdepth = 0;
+ for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)
+ elseSeen[elsetracker] = false;
+ elsetracker = 0;
+}
+
+TPpContext::~TPpContext()
+{
+ for (TSymbolMap::iterator it = symbols.begin(); it != symbols.end(); ++it)
+ delete it->second->mac.body;
+ mem_FreePool(pool);
+ delete [] preamble;
+
+ // free up the inputStack
+ while (! inputStack.empty())
+ popInput();
+}
+
+void TPpContext::setInput(TInputScanner& input, bool versionWillBeError)
+{
+ assert(inputStack.size() == 0);
+
+ pushInput(new tStringInput(this, input));
+
+ errorOnVersion = versionWillBeError;
+ versionSeen = false;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h
new file mode 100644
index 00000000000..4e47fa055ec
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h
@@ -0,0 +1,570 @@
+//
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef PPCONTEXT_H
+#define PPCONTEXT_H
+
+#include <stack>
+#include <unordered_map>
+
+#include "../ParseHelper.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4127)
+#endif
+
+namespace glslang {
+
+class TPpToken {
+public:
+ TPpToken() : token(0), space(false), ival(0), dval(0.0), atom(0)
+ {
+ loc.init();
+ name[0] = 0;
+ }
+
+ bool operator==(const TPpToken& right)
+ {
+ return token == right.token && atom == right.atom &&
+ ival == right.ival && dval == right.dval &&
+ strcmp(name, right.name) == 0;
+ }
+ bool operator!=(const TPpToken& right) { return ! operator==(right); }
+
+ TSourceLoc loc;
+ int token;
+ bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
+ int ival;
+ double dval;
+ long long i64val;
+ int atom;
+ char name[MaxTokenLength + 1];
+};
+
+class TInputScanner;
+
+// This class is the result of turning a huge pile of C code communicating through globals
+// into a class. This was done to allowing instancing to attain thread safety.
+// Don't expect too much in terms of OO design.
+class TPpContext {
+public:
+ TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&);
+ virtual ~TPpContext();
+
+ void setPreamble(const char* preamble, size_t length);
+
+ const char* tokenize(TPpToken* ppToken);
+
+ class tInput {
+ public:
+ tInput(TPpContext* p) : done(false), pp(p) { }
+ virtual ~tInput() { }
+
+ virtual int scan(TPpToken*) = 0;
+ virtual int getch() = 0;
+ virtual void ungetch() = 0;
+
+ // Will be called when we start reading tokens from this instance
+ virtual void notifyActivated() {}
+ // Will be called when we do not read tokens from this instance anymore
+ virtual void notifyDeleted() {}
+ protected:
+ bool done;
+ TPpContext* pp;
+ };
+
+ void setInput(TInputScanner& input, bool versionWillBeError);
+
+ void pushInput(tInput* in)
+ {
+ inputStack.push_back(in);
+ in->notifyActivated();
+ }
+ void popInput()
+ {
+ inputStack.back()->notifyDeleted();
+ delete inputStack.back();
+ inputStack.pop_back();
+ }
+
+ struct TokenStream {
+ TokenStream() : current(0) { }
+ TVector<unsigned char> data;
+ size_t current;
+ };
+
+ struct MemoryPool {
+ struct chunk *next;
+ uintptr_t free, end;
+ size_t chunksize;
+ uintptr_t alignmask;
+ };
+
+ //
+ // From Pp.cpp
+ //
+
+ struct MacroSymbol {
+ MacroSymbol() : argc(0), args(0), body(0), busy(0), undef(0) { }
+ int argc;
+ int *args;
+ TokenStream *body;
+ unsigned busy:1;
+ unsigned undef:1;
+ };
+
+ struct Symbol {
+ int atom;
+ MacroSymbol mac;
+ };
+
+ struct SymbolList {
+ struct SymbolList_Rec *next;
+ Symbol *symb;
+ };
+
+ MemoryPool *pool;
+ typedef TMap<int, Symbol*> TSymbolMap;
+ TSymbolMap symbols; // this has light use... just defined macros
+
+protected:
+ TPpContext(TPpContext&);
+ TPpContext& operator=(TPpContext&);
+
+ char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble
+ int preambleLength;
+ char** strings; // official strings of shader, starting a string 0 line 1
+ size_t* lengths;
+ int numStrings; // how many official strings there are
+ int currentString; // which string we're currently parsing (-1 for preamble)
+
+ // Scanner data:
+ int previous_token;
+ TParseContextBase& parseContext;
+
+ // Get the next token from *stack* of input sources, popping input sources
+ // that are out of tokens, down until an input sources is found that has a token.
+ // Return EndOfInput when there are no more tokens to be found by doing this.
+ int scanToken(TPpToken* ppToken)
+ {
+ int token = EndOfInput;
+
+ while (! inputStack.empty()) {
+ token = inputStack.back()->scan(ppToken);
+ if (token != EndOfInput)
+ break;
+ popInput();
+ }
+
+ return token;
+ }
+ int getChar() { return inputStack.back()->getch(); }
+ void ungetChar() { inputStack.back()->ungetch(); }
+
+ static const int maxMacroArgs = 64;
+ static const int maxIfNesting = 64;
+
+ int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
+ bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth
+ int elsetracker; // #if-#else and #endif constructs...Counter.
+
+ class tMacroInput : public tInput {
+ public:
+ tMacroInput(TPpContext* pp) : tInput(pp) { }
+ virtual ~tMacroInput()
+ {
+ for (size_t i = 0; i < args.size(); ++i)
+ delete args[i];
+ }
+
+ virtual int scan(TPpToken*);
+ virtual int getch() { assert(0); return EndOfInput; }
+ virtual void ungetch() { assert(0); }
+ MacroSymbol *mac;
+ TVector<TokenStream*> args;
+ };
+
+ class tMarkerInput : public tInput {
+ public:
+ tMarkerInput(TPpContext* pp) : tInput(pp) { }
+ virtual int scan(TPpToken*)
+ {
+ if (done)
+ return EndOfInput;
+ done = true;
+
+ return marker;
+ }
+ virtual int getch() { assert(0); return EndOfInput; }
+ virtual void ungetch() { assert(0); }
+ static const int marker = -3;
+ };
+
+ class tZeroInput : public tInput {
+ public:
+ tZeroInput(TPpContext* pp) : tInput(pp) { }
+ virtual int scan(TPpToken*);
+ virtual int getch() { assert(0); return EndOfInput; }
+ virtual void ungetch() { assert(0); }
+ };
+
+ std::vector<tInput*> inputStack;
+ bool errorOnVersion;
+ bool versionSeen;
+
+ //
+ // from Pp.cpp
+ //
+
+ // Used to obtain #include content.
+ TShader::Includer& includer;
+
+ int InitCPP();
+ int CPPdefine(TPpToken * ppToken);
+ int CPPundef(TPpToken * ppToken);
+ int CPPelse(int matchelse, TPpToken * ppToken);
+ int extraTokenCheck(int atom, TPpToken* ppToken, int token);
+ int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
+ int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
+ int CPPif (TPpToken * ppToken);
+ int CPPifdef(int defined, TPpToken * ppToken);
+ int CPPinclude(TPpToken * ppToken);
+ int CPPline(TPpToken * ppToken);
+ int CPPerror(TPpToken * ppToken);
+ int CPPpragma(TPpToken * ppToken);
+ int CPPversion(TPpToken * ppToken);
+ int CPPextension(TPpToken * ppToken);
+ int readCPPline(TPpToken * ppToken);
+ TokenStream* PrescanMacroArg(TokenStream *a, TPpToken * ppToken, bool newLineOkay);
+ int MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay);
+
+ //
+ // from PpSymbols.cpp
+ //
+ Symbol *NewSymbol(int name);
+ Symbol *AddSymbol(int atom);
+ Symbol *LookUpSymbol(int atom);
+
+ //
+ // From PpTokens.cpp
+ //
+ void lAddByte(TokenStream *fTok, unsigned char fVal);
+ int lReadByte(TokenStream *pTok);
+ void lUnreadByte(TokenStream *pTok);
+ void RecordToken(TokenStream* pTok, int token, TPpToken* ppToken);
+ void RewindTokenStream(TokenStream *pTok);
+ int ReadToken(TokenStream* pTok, TPpToken* ppToken);
+ void pushTokenStreamInput(TokenStream *ts);
+ void UngetToken(int token, TPpToken* ppToken);
+
+ class tTokenInput : public tInput {
+ public:
+ tTokenInput(TPpContext* pp, TokenStream* t) : tInput(pp), tokens(t) { }
+ virtual int scan(TPpToken *);
+ virtual int getch() { assert(0); return EndOfInput; }
+ virtual void ungetch() { assert(0); }
+ protected:
+ TokenStream *tokens;
+ };
+
+ class tUngotTokenInput : public tInput {
+ public:
+ tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
+ virtual int scan(TPpToken *);
+ virtual int getch() { assert(0); return EndOfInput; }
+ virtual void ungetch() { assert(0); }
+ protected:
+ int token;
+ TPpToken lval;
+ };
+
+ //
+ // From PpScanner.cpp
+ //
+ class tStringInput : public tInput {
+ public:
+ tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
+ virtual int scan(TPpToken*);
+
+ // Scanner used to get source stream characters.
+ // - Escaped newlines are handled here, invisibly to the caller.
+ // - All forms of newline are handled, and turned into just a '\n'.
+ int getch()
+ {
+ int ch = input->get();
+
+ if (ch == '\\') {
+ // Move past escaped newlines, as many as sequentially exist
+ do {
+ if (input->peek() == '\r' || input->peek() == '\n') {
+ bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
+ if (! allowed && pp->inComment)
+ return '\\';
+
+ // escape one newline now
+ ch = input->get();
+ int nextch = input->get();
+ if (ch == '\r' && nextch == '\n')
+ ch = input->get();
+ else
+ ch = nextch;
+ } else
+ return '\\';
+ } while (ch == '\\');
+ }
+
+ // handle any non-escaped newline
+ if (ch == '\r' || ch == '\n') {
+ if (ch == '\r' && input->peek() == '\n')
+ input->get();
+ return '\n';
+ }
+
+ return ch;
+ }
+
+ // Scanner used to backup the source stream characters. Newlines are
+ // handled here, invisibly to the caller, meaning have to undo exactly
+ // what getch() above does (e.g., don't leave things in the middle of a
+ // sequence of escaped newlines).
+ void ungetch()
+ {
+ input->unget();
+
+ do {
+ int ch = input->peek();
+ if (ch == '\r' || ch == '\n') {
+ if (ch == '\n') {
+ // correct for two-character newline
+ input->unget();
+ if (input->peek() != '\r')
+ input->get();
+ }
+ // now in front of a complete newline, move past an escape character
+ input->unget();
+ if (input->peek() == '\\')
+ input->unget();
+ else {
+ input->get();
+ break;
+ }
+ } else
+ break;
+ } while (true);
+ }
+
+ protected:
+ TInputScanner* input;
+ };
+
+ // Holds a reference to included file data, as well as a
+ // prologue and an epilogue string. This can be scanned using the tInput
+ // interface and acts as a single source string.
+ class TokenizableIncludeFile : public tInput {
+ public:
+ // Copies prologue and epilogue. The includedFile must remain valid
+ // until this TokenizableIncludeFile is no longer used.
+ TokenizableIncludeFile(const TSourceLoc& startLoc,
+ const std::string& prologue,
+ TShader::Includer::IncludeResult* includedFile,
+ const std::string& epilogue,
+ TPpContext* pp)
+ : tInput(pp),
+ prologue_(prologue),
+ includedFile_(includedFile),
+ epilogue_(epilogue),
+ scanner(3, strings, lengths, names, 0, 0, true),
+ prevScanner(nullptr),
+ stringInput(pp, scanner)
+ {
+ strings[0] = prologue_.data();
+ strings[1] = includedFile_->file_data;
+ strings[2] = epilogue_.data();
+
+ lengths[0] = prologue_.size();
+ lengths[1] = includedFile_->file_length;
+ lengths[2] = epilogue_.size();
+
+ scanner.setLine(startLoc.line);
+ scanner.setString(startLoc.string);
+
+ scanner.setFile(startLoc.name, 0);
+ scanner.setFile(startLoc.name, 1);
+ scanner.setFile(startLoc.name, 2);
+ }
+
+ // tInput methods:
+ int scan(TPpToken* t) override { return stringInput.scan(t); }
+ int getch() override { return stringInput.getch(); }
+ void ungetch() override { stringInput.ungetch(); }
+
+ void notifyActivated() override
+ {
+ prevScanner = pp->parseContext.getScanner();
+ pp->parseContext.setScanner(&scanner);
+ pp->push_include(includedFile_);
+ }
+
+ void notifyDeleted() override
+ {
+ pp->parseContext.setScanner(prevScanner);
+ pp->pop_include();
+ }
+
+ private:
+ // Stores the prologue for this string.
+ const std::string prologue_;
+
+ // Stores the epilogue for this string.
+ const std::string epilogue_;
+
+ // Points to the IncludeResult that this TokenizableIncludeFile represents.
+ TShader::Includer::IncludeResult* includedFile_;
+
+ // Will point to prologue_, includedFile_->file_data and epilogue_
+ // This is passed to scanner constructor.
+ // These do not own the storage and it must remain valid until this
+ // object has been destroyed.
+ const char* strings[3];
+ // Length of str_, passed to scanner constructor.
+ size_t lengths[3];
+ // String names
+ const char* names[3];
+ // Scans over str_.
+ TInputScanner scanner;
+ // The previous effective scanner before the scanner in this instance
+ // has been activated.
+ TInputScanner* prevScanner;
+ // Delegate object implementing the tInput interface.
+ tStringInput stringInput;
+ };
+
+ int InitScanner();
+ int ScanFromString(char* s);
+ void missingEndifCheck();
+ int lFloatConst(int len, int ch, TPpToken* ppToken);
+
+ void push_include(TShader::Includer::IncludeResult* result)
+ {
+ currentSourceFile = result->file_name;
+ includeStack.push(result);
+ }
+
+ void pop_include()
+ {
+ TShader::Includer::IncludeResult* include = includeStack.top();
+ includeStack.pop();
+ includer.releaseInclude(include);
+ if (includeStack.empty()) {
+ currentSourceFile = rootFileName;
+ } else {
+ currentSourceFile = includeStack.top()->file_name;
+ }
+ }
+
+ bool inComment;
+
+ //
+ // From PpAtom.cpp
+ //
+ typedef TUnorderedMap<TString, int> TAtomMap;
+ typedef TVector<const TString*> TStringMap;
+
+ TAtomMap atomMap;
+ TStringMap stringMap;
+ std::stack<TShader::Includer::IncludeResult*> includeStack;
+ std::string currentSourceFile;
+ std::string rootFileName;
+ int nextAtom;
+ void InitAtomTable();
+ void AddAtomFixed(const char* s, int atom);
+ int LookUpAddString(const char* s);
+ const char* GetAtomString(int atom);
+
+ //
+ // From PpMemory.cpp
+ //
+ MemoryPool *mem_CreatePool(size_t chunksize, unsigned align);
+ void mem_FreePool(MemoryPool*);
+ void *mem_Alloc(MemoryPool* p, size_t size);
+ int mem_AddCleanup(MemoryPool* p, void (*fn)(void *, void*), void* arg1, void* arg2);
+};
+
+} // end namespace glslang
+
+#endif // PPCONTEXT_H
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp
new file mode 100644
index 00000000000..57a49fb893a
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp
@@ -0,0 +1,162 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "PpContext.h"
+
+// default alignment and chunksize, if called with 0 arguments
+#define CHUNKSIZE (64*1024)
+#define ALIGN 8
+
+namespace glslang {
+
+struct chunk {
+ struct chunk *next;
+};
+
+TPpContext::MemoryPool* TPpContext::mem_CreatePool(size_t chunksize, unsigned int align)
+{
+ if (align == 0)
+ align = ALIGN;
+ if (chunksize == 0)
+ chunksize = CHUNKSIZE;
+ if (align & (align - 1))
+ return nullptr;
+ if (chunksize < sizeof(MemoryPool))
+ return nullptr;
+ if (chunksize & (align - 1))
+ return nullptr;
+
+ MemoryPool *pool = (MemoryPool*)malloc(chunksize);
+ if (! pool)
+ return nullptr;
+
+ pool->next = 0;
+ pool->chunksize = chunksize;
+ pool->alignmask = (uintptr_t)(align) - 1;
+ pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
+ pool->end = (uintptr_t)pool + chunksize;
+
+ return pool;
+}
+
+void TPpContext::mem_FreePool(MemoryPool *pool)
+{
+ struct chunk *p, *next;
+
+ for (p = (struct chunk *)pool; p; p = next) {
+ next = p->next;
+ free(p);
+ }
+}
+
+void* TPpContext::mem_Alloc(MemoryPool *pool, size_t size)
+{
+ struct chunk *ch;
+ void *rv = (void *)pool->free;
+ size = (size + pool->alignmask) & ~pool->alignmask;
+ if (size <= 0) size = pool->alignmask;
+ pool->free += size;
+ if (pool->free > pool->end || pool->free < (uintptr_t)rv) {
+ size_t minreq = (size + sizeof(struct chunk) + pool->alignmask) & ~pool->alignmask;
+ pool->free = (uintptr_t)rv;
+ if (minreq >= pool->chunksize) {
+ // request size is too big for the chunksize, so allocate it as
+ // a single chunk of the right size
+ ch = (struct chunk*)malloc(minreq);
+ if (! ch)
+ return nullptr;
+ } else {
+ ch = (struct chunk*)malloc(pool->chunksize);
+ if (! ch)
+ return nullptr;
+ pool->free = (uintptr_t)ch + minreq;
+ pool->end = (uintptr_t)ch + pool->chunksize;
+ }
+ ch->next = pool->next;
+ pool->next = ch;
+ rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask);
+ }
+ return rv;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp
new file mode 100644
index 00000000000..b3d1af6dad2
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp
@@ -0,0 +1,778 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.c
+//
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+#include "../Scan.h"
+
+namespace glslang {
+
+int TPpContext::InitScanner()
+{
+ // Add various atoms needed by the CPP line scanner:
+ if (!InitCPP())
+ return 0;
+
+ previous_token = '\n';
+
+ return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Floating point constants: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+* lFloatConst() - Scan a single- or double-precision floating point constant. Assumes that the scanner
+* has seen at least one digit, followed by either a decimal '.' or the
+* letter 'e', or a precision ending (e.g., F or LF).
+*/
+
+int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
+{
+ bool HasDecimalOrExponent = false;
+ int declen;
+ int str_len;
+ int isDouble = 0;
+
+ declen = 0;
+
+ str_len=len;
+ char* str = ppToken->name;
+ if (ch == '.') {
+ HasDecimalOrExponent = true;
+ str[len++] = (char)ch;
+ ch = getChar();
+ while (ch >= '0' && ch <= '9') {
+ if (len < MaxTokenLength) {
+ declen++;
+ if (len > 0 || ch != '0') {
+ str[len] = (char)ch;
+ len++;
+ str_len++;
+ }
+ ch = getChar();
+ } else {
+ parseContext.ppError(ppToken->loc, "float literal too long", "", "");
+ len = 1;
+ str_len = 1;
+ }
+ }
+ }
+
+ // Exponent:
+
+ if (ch == 'e' || ch == 'E') {
+ HasDecimalOrExponent = true;
+ if (len >= MaxTokenLength) {
+ parseContext.ppError(ppToken->loc, "float literal too long", "", "");
+ len = 1;
+ str_len = 1;
+ } else {
+ str[len++] = (char)ch;
+ ch = getChar();
+ if (ch == '+') {
+ str[len++] = (char)ch;
+ ch = getChar();
+ } else if (ch == '-') {
+ str[len++] = (char)ch;
+ ch = getChar();
+ }
+ if (ch >= '0' && ch <= '9') {
+ while (ch >= '0' && ch <= '9') {
+ if (len < MaxTokenLength) {
+ str[len++] = (char)ch;
+ ch = getChar();
+ } else {
+ parseContext.ppError(ppToken->loc, "float literal too long", "", "");
+ len = 1;
+ str_len = 1;
+ }
+ }
+ } else {
+ parseContext.ppError(ppToken->loc, "bad character in float exponent", "", "");
+ }
+ }
+ }
+
+ if (len == 0) {
+ ppToken->dval = 0.0;
+ strcpy(str, "0.0");
+ } else {
+ if (ch == 'l' || ch == 'L') {
+ parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
+ if (! HasDecimalOrExponent)
+ parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
+ int ch2 = getChar();
+ if (ch2 != 'f' && ch2 != 'F') {
+ ungetChar();
+ ungetChar();
+ } else {
+ if (len < MaxTokenLength) {
+ str[len++] = (char)ch;
+ str[len++] = (char)ch2;
+ isDouble = 1;
+ } else {
+ parseContext.ppError(ppToken->loc, "float literal too long", "", "");
+ len = 1,str_len=1;
+ }
+ }
+ } else if (ch == 'f' || ch == 'F') {
+ parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix");
+ if (! parseContext.relaxedErrors())
+ parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix");
+ if (! HasDecimalOrExponent)
+ parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
+ if (len < MaxTokenLength)
+ str[len++] = (char)ch;
+ else {
+ parseContext.ppError(ppToken->loc, "float literal too long", "", "");
+ len = 1,str_len=1;
+ }
+ } else
+ ungetChar();
+
+ str[len]='\0';
+
+ ppToken->dval = strtod(str, nullptr);
+ }
+
+ if (isDouble)
+ return PpAtomConstDouble;
+ else
+ return PpAtomConstFloat;
+}
+
+//
+// Scanner used to tokenize source stream.
+//
+int TPpContext::tStringInput::scan(TPpToken* ppToken)
+{
+ char* tokenText = ppToken->name;
+ int AlreadyComplained = 0;
+ int len = 0;
+ int ch = 0;
+ int ii = 0;
+ unsigned long long ival = 0;
+ bool enableInt64 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64);
+
+ ppToken->ival = 0;
+ ppToken->i64val = 0;
+ ppToken->space = false;
+ ch = getch();
+ for (;;) {
+ while (ch == ' ' || ch == '\t') {
+ ppToken->space = true;
+ ch = getch();
+ }
+
+ ppToken->loc = pp->parseContext.getCurrentLoc();
+ len = 0;
+ switch (ch) {
+ default:
+ // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token)
+ return ch;
+
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z': case '_':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ do {
+ if (len < MaxTokenLength) {
+ tokenText[len++] = (char)ch;
+ ch = getch();
+ } else {
+ if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "name too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ch = getch();
+ }
+ } while ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '_');
+
+ // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc.
+ if (len == 0)
+ continue;
+
+ tokenText[len] = '\0';
+ ungetch();
+ ppToken->atom = pp->LookUpAddString(tokenText);
+ return PpAtomIdentifier;
+ case '0':
+ ppToken->name[len++] = (char)ch;
+ ch = getch();
+ if (ch == 'x' || ch == 'X') {
+ // must be hexidecimal
+
+ bool isUnsigned = false;
+ bool isInt64 = false;
+ ppToken->name[len++] = (char)ch;
+ ch = getch();
+ if ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f')) {
+
+ ival = 0;
+ do {
+ if (ival <= 0x0fffffff || (enableInt64 && ival <= 0x0fffffffffffffffull)) {
+ ppToken->name[len++] = (char)ch;
+ if (ch >= '0' && ch <= '9') {
+ ii = ch - '0';
+ } else if (ch >= 'A' && ch <= 'F') {
+ ii = ch - 'A' + 10;
+ } else if (ch >= 'a' && ch <= 'f') {
+ ii = ch - 'a' + 10;
+ } else
+ pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", "");
+ ival = (ival << 4) | ii;
+ } else {
+ if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "hexidecimal literal too big", "", "");
+ AlreadyComplained = 1;
+ }
+ ival = 0xffffffffffffffffull;
+ }
+ ch = getch();
+ } while ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f'));
+ } else {
+ pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", "");
+ }
+ if (ch == 'u' || ch == 'U') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isUnsigned = true;
+
+ if (enableInt64) {
+ int nextCh = getch();
+ if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt64 = true;
+ } else
+ ungetch();
+ }
+ }
+ else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt64 = true;
+ } else
+ ungetch();
+ ppToken->name[len] = '\0';
+
+ if (isInt64) {
+ ppToken->i64val = ival;
+ return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+ } else {
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
+ }
+ } else {
+ // could be octal integer or floating point, speculative pursue octal until it must be floating point
+
+ bool isUnsigned = false;
+ bool isInt64 = false;
+ bool octalOverflow = false;
+ bool nonOctal = false;
+ ival = 0;
+
+ // see how much octal-like stuff we can read
+ while (ch >= '0' && ch <= '7') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ if (ival <= 0x1fffffff || (enableInt64 && ival <= 0x1fffffffffffffffull)) {
+ ii = ch - '0';
+ ival = (ival << 3) | ii;
+ } else
+ octalOverflow = true;
+ ch = getch();
+ }
+
+ // could be part of a float...
+ if (ch == '8' || ch == '9') {
+ nonOctal = true;
+ do {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ch = getch();
+ } while (ch >= '0' && ch <= '9');
+ }
+ if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F')
+ return pp->lFloatConst(len, ch, ppToken);
+
+ // wasn't a float, so must be octal...
+ if (nonOctal)
+ pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", "");
+
+ if (ch == 'u' || ch == 'U') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isUnsigned = true;
+
+ if (enableInt64) {
+ int nextCh = getch();
+ if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt64 = true;
+ } else
+ ungetch();
+ }
+ }
+ else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt64 = true;
+ } else
+ ungetch();
+ ppToken->name[len] = '\0';
+
+ if (octalOverflow)
+ pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", "");
+
+ if (isInt64) {
+ ppToken->i64val = ival;
+ return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+ } else {
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
+ }
+ }
+ break;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ // can't be hexidecimal or octal, is either decimal or floating point
+
+ do {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ else if (! AlreadyComplained) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
+ AlreadyComplained = 1;
+ }
+ ch = getch();
+ } while (ch >= '0' && ch <= '9');
+ if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') {
+ return pp->lFloatConst(len, ch, ppToken);
+ } else {
+ // Finish handling signed and unsigned integers
+ int numericLen = len;
+ bool isUnsigned = false;
+ bool isInt64 = false;
+ if (ch == 'u' || ch == 'U') {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isUnsigned = true;
+
+ if (enableInt64) {
+ int nextCh = getch();
+ if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)nextCh;
+ isInt64 = true;
+ } else
+ ungetch();
+ }
+ } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+ if (len < MaxTokenLength)
+ ppToken->name[len++] = (char)ch;
+ isInt64 = true;
+ } else
+ ungetch();
+
+ ppToken->name[len] = '\0';
+ ival = 0;
+ const unsigned oneTenthMaxInt = 0xFFFFFFFFu / 10;
+ const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt;
+ const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10;
+ const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64;
+ for (int i = 0; i < numericLen; i++) {
+ ch = ppToken->name[i] - '0';
+ if ((enableInt64 == false && ((ival > oneTenthMaxInt) || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt))) ||
+ (enableInt64 && ((ival > oneTenthMaxInt64) || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)))) {
+ pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", "");
+ ival = 0xFFFFFFFFFFFFFFFFull;
+ break;
+ } else
+ ival = ival * 10 + ch;
+ }
+
+ if (isInt64) {
+ ppToken->i64val = ival;
+ return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+ } else {
+ ppToken->ival = (int)ival;
+ return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
+ }
+ }
+ break;
+ case '-':
+ ch = getch();
+ if (ch == '-') {
+ return PpAtomDecrement;
+ } else if (ch == '=') {
+ return PpAtomSub;
+ } else {
+ ungetch();
+ return '-';
+ }
+ case '+':
+ ch = getch();
+ if (ch == '+') {
+ return PpAtomIncrement;
+ } else if (ch == '=') {
+ return PpAtomAdd;
+ } else {
+ ungetch();
+ return '+';
+ }
+ case '*':
+ ch = getch();
+ if (ch == '=') {
+ return PpAtomMul;
+ } else {
+ ungetch();
+ return '*';
+ }
+ case '%':
+ ch = getch();
+ if (ch == '=') {
+ return PpAtomMod;
+ } else {
+ ungetch();
+ return '%';
+ }
+ case '^':
+ ch = getch();
+ if (ch == '^') {
+ return PpAtomXor;
+ } else {
+ if (ch == '=')
+ return PpAtomXorAssign;
+ else{
+ ungetch();
+ return '^';
+ }
+ }
+
+ case '=':
+ ch = getch();
+ if (ch == '=') {
+ return PpAtomEQ;
+ } else {
+ ungetch();
+ return '=';
+ }
+ case '!':
+ ch = getch();
+ if (ch == '=') {
+ return PpAtomNE;
+ } else {
+ ungetch();
+ return '!';
+ }
+ case '|':
+ ch = getch();
+ if (ch == '|') {
+ return PpAtomOr;
+ } else if (ch == '=') {
+ return PpAtomOrAssign;
+ } else {
+ ungetch();
+ return '|';
+ }
+ case '&':
+ ch = getch();
+ if (ch == '&') {
+ return PpAtomAnd;
+ } else if (ch == '=') {
+ return PpAtomAndAssign;
+ } else {
+ ungetch();
+ return '&';
+ }
+ case '<':
+ ch = getch();
+ if (ch == '<') {
+ ch = getch();
+ if (ch == '=')
+ return PpAtomLeftAssign;
+ else {
+ ungetch();
+ return PpAtomLeft;
+ }
+ } else if (ch == '=') {
+ return PpAtomLE;
+ } else {
+ ungetch();
+ return '<';
+ }
+ case '>':
+ ch = getch();
+ if (ch == '>') {
+ ch = getch();
+ if (ch == '=')
+ return PpAtomRightAssign;
+ else {
+ ungetch();
+ return PpAtomRight;
+ }
+ } else if (ch == '=') {
+ return PpAtomGE;
+ } else {
+ ungetch();
+ return '>';
+ }
+ case '.':
+ ch = getch();
+ if (ch >= '0' && ch <= '9') {
+ ungetch();
+ return pp->lFloatConst(0, '.', ppToken);
+ } else {
+ ungetch();
+ return '.';
+ }
+ case '/':
+ ch = getch();
+ if (ch == '/') {
+ pp->inComment = true;
+ do {
+ ch = getch();
+ } while (ch != '\n' && ch != EndOfInput);
+ ppToken->space = true;
+ pp->inComment = false;
+
+ return ch;
+ } else if (ch == '*') {
+ ch = getch();
+ do {
+ while (ch != '*') {
+ if (ch == EndOfInput) {
+ pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", "");
+ return ch;
+ }
+ ch = getch();
+ }
+ ch = getch();
+ if (ch == EndOfInput) {
+ pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", "");
+ return ch;
+ }
+ } while (ch != '/');
+ ppToken->space = true;
+ // loop again to get the next token...
+ break;
+ } else if (ch == '=') {
+ return PpAtomDiv;
+ } else {
+ ungetch();
+ return '/';
+ }
+ break;
+ case '"':
+ ch = getch();
+ while (ch != '"' && ch != '\n' && ch != EndOfInput) {
+ if (len < MaxTokenLength) {
+ tokenText[len] = (char)ch;
+ len++;
+ ch = getch();
+ } else
+ break;
+ };
+ tokenText[len] = '\0';
+ if (ch != '"') {
+ ungetch();
+ pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", "");
+ }
+ return PpAtomConstString;
+ }
+
+ ch = getch();
+ }
+}
+
+//
+// The main functional entry-point into the preprocessor, which will
+// scan the source strings to figure out and return the next processing token.
+//
+// Return string pointer to next token.
+// Return 0 when no more tokens.
+//
+const char* TPpContext::tokenize(TPpToken* ppToken)
+{
+ int token = '\n';
+
+ for(;;) {
+ token = scanToken(ppToken);
+ ppToken->token = token;
+ if (token == EndOfInput) {
+ missingEndifCheck();
+ return nullptr;
+ }
+ if (token == '#') {
+ if (previous_token == '\n') {
+ token = readCPPline(ppToken);
+ if (token == EndOfInput) {
+ missingEndifCheck();
+ return nullptr;
+ }
+ continue;
+ } else {
+ parseContext.ppError(ppToken->loc, "preprocessor directive cannot be preceded by another token", "#", "");
+ return nullptr;
+ }
+ }
+ previous_token = token;
+
+ if (token == '\n')
+ continue;
+
+ // expand macros
+ if (token == PpAtomIdentifier && MacroExpand(ppToken->atom, ppToken, false, true) != 0)
+ continue;
+
+ const char* tokenString = nullptr;
+ switch (token) {
+ case PpAtomIdentifier:
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstFloat:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ case PpAtomConstDouble:
+ tokenString = ppToken->name;
+ break;
+ case PpAtomConstString:
+ parseContext.ppError(ppToken->loc, "string literals not supported", "\"\"", "");
+ break;
+ case '\'':
+ parseContext.ppError(ppToken->loc, "character literals not supported", "\'", "");
+ break;
+ default:
+ tokenString = GetAtomString(token);
+ break;
+ }
+
+ if (tokenString) {
+ if (tokenString[0] != 0)
+ parseContext.tokensBeforeEOF = 1;
+
+ return tokenString;
+ }
+ }
+}
+
+// Checks if we've seen balanced #if...#endif
+void TPpContext::missingEndifCheck()
+{
+ if (ifdepth > 0)
+ parseContext.ppError(parseContext.getCurrentLoc(), "missing #endif", "", "");
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp
new file mode 100644
index 00000000000..c2ab7c0a11e
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp
@@ -0,0 +1,135 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "PpContext.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Symbol Table Variables: ///////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+namespace glslang {
+
+/*
+* Allocate a new symbol node;
+*
+*/
+TPpContext::Symbol* TPpContext::NewSymbol(int atom)
+{
+ Symbol* lSymb;
+ char* pch;
+ size_t ii;
+
+ lSymb = (Symbol *) mem_Alloc(pool, sizeof(Symbol));
+ lSymb->atom = atom;
+
+ // Clear macro
+ pch = (char*) &lSymb->mac;
+ for (ii = 0; ii < sizeof(lSymb->mac); ii++)
+ *pch++ = 0;
+
+ return lSymb;
+}
+
+TPpContext::Symbol* TPpContext::AddSymbol(int atom)
+{
+ Symbol *lSymb;
+
+ lSymb = NewSymbol(atom);
+ symbols[lSymb->atom] = lSymb;
+
+ return lSymb;
+}
+
+TPpContext::Symbol* TPpContext::LookUpSymbol(int atom)
+{
+ TSymbolMap::iterator it = symbols.find(atom);
+ if (it == symbols.end())
+ return nullptr;
+ else
+ return it->second;
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp
new file mode 100644
index 00000000000..54d495e11f2
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp
@@ -0,0 +1,278 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//Copyright (C) 2013 LunarG, Inc.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+//
+// For recording and playing back the stream of tokens in a macro definition.
+//
+
+#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
+#define _CRT_SECURE_NO_WARNINGS
+#define snprintf sprintf_s
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "PpContext.h"
+#include "PpTokens.h"
+
+namespace glslang {
+
+void TPpContext::lAddByte(TokenStream *fTok, unsigned char fVal)
+{
+ fTok->data.push_back(fVal);
+}
+
+/*
+* Get the next byte from a stream.
+*/
+int TPpContext::lReadByte(TokenStream *pTok)
+{
+ if (pTok->current < pTok->data.size())
+ return pTok->data[pTok->current++];
+ else
+ return EndOfInput;
+}
+
+void TPpContext::lUnreadByte(TokenStream *pTok)
+{
+ if (pTok->current > 0)
+ --pTok->current;
+}
+
+/*
+* Add a token to the end of a list for later playback.
+*/
+void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken)
+{
+ const char* s;
+ char* str = NULL;
+
+ if (token > PpAtomMaxSingle)
+ lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
+ else
+ lAddByte(pTok, (unsigned char)(token & 0x7f));
+
+ switch (token) {
+ case PpAtomIdentifier:
+ case PpAtomConstString:
+ s = ppToken->name;
+ while (*s)
+ lAddByte(pTok, (unsigned char) *s++);
+ lAddByte(pTok, 0);
+ break;
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ case PpAtomConstFloat:
+ case PpAtomConstDouble:
+ str = ppToken->name;
+ while (*str) {
+ lAddByte(pTok, (unsigned char) *str);
+ str++;
+ }
+ lAddByte(pTok, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+* Reset a token stream in preperation for reading.
+*/
+void TPpContext::RewindTokenStream(TokenStream *pTok)
+{
+ pTok->current = 0;
+}
+
+/*
+* Read the next token from a token stream (not the source stream, but stream used to hold a tokenized macro).
+*/
+int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
+{
+ char* tokenText = ppToken->name;
+ int ltoken, len;
+ int ch;
+
+ ltoken = lReadByte(pTok);
+ ppToken->loc = parseContext.getCurrentLoc();
+ if (ltoken > 127)
+ ltoken += 128;
+ switch (ltoken) {
+ case '#':
+ if (lReadByte(pTok) == '#') {
+ parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
+ parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
+ parseContext.error(ppToken->loc, "token pasting not implemented (internal error)", "##", "");
+ //return PpAtomPaste;
+ return ReadToken(pTok, ppToken);
+ } else
+ lUnreadByte(pTok);
+ break;
+ case PpAtomConstString:
+ case PpAtomIdentifier:
+ case PpAtomConstFloat:
+ case PpAtomConstDouble:
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ len = 0;
+ ch = lReadByte(pTok);
+ while (ch != 0 && ch != EndOfInput) {
+ if (len < MaxTokenLength) {
+ tokenText[len] = (char)ch;
+ len++;
+ ch = lReadByte(pTok);
+ } else {
+ parseContext.error(ppToken->loc, "token too long", "", "");
+ break;
+ }
+ }
+ tokenText[len] = 0;
+
+ switch (ltoken) {
+ case PpAtomIdentifier:
+ ppToken->atom = LookUpAddString(tokenText);
+ break;
+ case PpAtomConstString:
+ break;
+ case PpAtomConstFloat:
+ case PpAtomConstDouble:
+ ppToken->dval = atof(ppToken->name);
+ break;
+ case PpAtomConstInt:
+ case PpAtomConstUint:
+ if (len > 0 && tokenText[0] == '0') {
+ if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X'))
+ ppToken->ival = strtol(ppToken->name, 0, 16);
+ else
+ ppToken->ival = strtol(ppToken->name, 0, 8);
+ } else
+ ppToken->ival = atoi(ppToken->name);
+ break;
+ case PpAtomConstInt64:
+ case PpAtomConstUint64:
+ if (len > 0 && tokenText[0] == '0') {
+ if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X'))
+ ppToken->i64val = strtoll(ppToken->name, nullptr, 16);
+ else
+ ppToken->i64val = strtoll(ppToken->name, nullptr, 8);
+ } else
+ ppToken->i64val = atoll(ppToken->name);
+ break;
+ }
+ }
+
+ return ltoken;
+}
+
+int TPpContext::tTokenInput::scan(TPpToken* ppToken)
+{
+ return pp->ReadToken(tokens, ppToken);
+}
+
+void TPpContext::pushTokenStreamInput(TokenStream* ts)
+{
+ pushInput(new tTokenInput(this, ts));
+ RewindTokenStream(ts);
+}
+
+int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)
+{
+ if (done)
+ return EndOfInput;
+
+ int ret = token;
+ *ppToken = lval;
+ done = true;
+
+ return ret;
+}
+
+void TPpContext::UngetToken(int token, TPpToken* ppToken)
+{
+ pushInput(new tUngotTokenInput(this, token, ppToken));
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h
new file mode 100644
index 00000000000..87f0eb1a60a
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h
@@ -0,0 +1,171 @@
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+namespace glslang {
+
+// Multi-character tokens
+enum EFixedAtoms {
+ PpAtomMaxSingle = 256, // single character tokens get their own char value as their token, skip them
+
+ // Operators
+
+ PpAtomAdd,
+ PpAtomSub,
+ PpAtomMul,
+ PpAtomDiv,
+ PpAtomMod,
+
+ PpAtomRight,
+ PpAtomLeft,
+
+ PpAtomRightAssign,
+ PpAtomLeftAssign,
+ PpAtomAndAssign,
+ PpAtomOrAssign,
+ PpAtomXorAssign,
+
+ PpAtomAnd,
+ PpAtomOr,
+ PpAtomXor,
+
+ PpAtomEQ,
+ PpAtomNE,
+ PpAtomGE,
+ PpAtomLE,
+
+ PpAtomDecrement,
+ PpAtomIncrement,
+
+ PpAtomPaste,
+
+ // Constants
+
+ PpAtomConstInt,
+ PpAtomConstUint,
+ PpAtomConstInt64,
+ PpAtomConstUint64,
+ PpAtomConstFloat,
+ PpAtomConstDouble,
+ PpAtomConstString,
+
+ // Indentifiers
+ PpAtomIdentifier,
+
+ // preprocessor "keywords"
+
+ PpAtomDefine,
+ PpAtomDefined,
+ PpAtomUndef,
+
+ PpAtomIf,
+ PpAtomIfdef,
+ PpAtomIfndef,
+ PpAtomElse,
+ PpAtomElif,
+ PpAtomEndif,
+
+ PpAtomLine,
+ PpAtomPragma,
+ PpAtomError,
+
+ // #version ...
+ PpAtomVersion,
+ PpAtomCore,
+ PpAtomCompatibility,
+ PpAtomEs,
+
+ // #extension
+ PpAtomExtension,
+
+ // __LINE__, __FILE__, __VERSION__
+
+ PpAtomLineMacro,
+ PpAtomFileMacro,
+ PpAtomVersionMacro,
+
+ // #include
+ PpAtomInclude,
+
+ PpAtomLast,
+};
+
+} // end namespace glslang
+
+#endif /* not PARSER_H */
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp
new file mode 100644
index 00000000000..835f57f69d6
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp
@@ -0,0 +1,859 @@
+//
+// Copyright (C) 2015-2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Visit the nodes in the glslang intermediate tree representation to
+// propagate the 'noContraction' qualifier.
+//
+
+#include "propagateNoContraction.h"
+
+#include <cstdlib>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "localintermediate.h"
+namespace {
+
+// Use a string to hold the access chain information, as in most cases the
+// access chain is short and may contain only one element, which is the symbol
+// ID.
+// Example: struct {float a; float b;} s;
+// Object s.a will be represented with: <symbol ID of s>/0
+// Object s.b will be represented with: <symbol ID of s>/1
+// Object s will be represented with: <symbol ID of s>
+// For members of vector, matrix and arrays, they will be represented with the
+// same symbol ID of their container symbol objects. This is because their
+// preciseness is always the same as their container symbol objects.
+typedef std::string ObjectAccessChain;
+
+// The delimiter used in the ObjectAccessChain string to separate symbol ID and
+// different level of struct indices.
+const char ObjectAccesschainDelimiter = '/';
+
+// Mapping from Symbol IDs of symbol nodes, to their defining operation
+// nodes.
+typedef std::unordered_multimap<ObjectAccessChain, glslang::TIntermOperator*> NodeMapping;
+// Mapping from object nodes to their access chain info string.
+typedef std::unordered_map<glslang::TIntermTyped*, ObjectAccessChain> AccessChainMapping;
+
+// Set of object IDs.
+typedef std::unordered_set<ObjectAccessChain> ObjectAccesschainSet;
+// Set of return branch nodes.
+typedef std::unordered_set<glslang::TIntermBranch*> ReturnBranchNodeSet;
+
+// A helper function to tell whether a node is 'noContraction'. Returns true if
+// the node has 'noContraction' qualifier, otherwise false.
+bool isPreciseObjectNode(glslang::TIntermTyped* node)
+{
+ return node->getType().getQualifier().noContraction;
+}
+
+// Returns true if the opcode is a dereferencing one.
+bool isDereferenceOperation(glslang::TOperator op)
+{
+ switch (op) {
+ case glslang::EOpIndexDirect:
+ case glslang::EOpIndexDirectStruct:
+ case glslang::EOpIndexIndirect:
+ case glslang::EOpVectorSwizzle:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Returns true if the opcode leads to an assignment operation.
+bool isAssignOperation(glslang::TOperator op)
+{
+ switch (op) {
+ case glslang::EOpAssign:
+ case glslang::EOpAddAssign:
+ case glslang::EOpSubAssign:
+ case glslang::EOpMulAssign:
+ case glslang::EOpVectorTimesMatrixAssign:
+ case glslang::EOpVectorTimesScalarAssign:
+ case glslang::EOpMatrixTimesScalarAssign:
+ case glslang::EOpMatrixTimesMatrixAssign:
+ case glslang::EOpDivAssign:
+ case glslang::EOpModAssign:
+ case glslang::EOpAndAssign:
+ case glslang::EOpLeftShiftAssign:
+ case glslang::EOpRightShiftAssign:
+ case glslang::EOpInclusiveOrAssign:
+ case glslang::EOpExclusiveOrAssign:
+
+ case glslang::EOpPostIncrement:
+ case glslang::EOpPostDecrement:
+ case glslang::EOpPreIncrement:
+ case glslang::EOpPreDecrement:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// A helper function to get the unsigned int from a given constant union node.
+// Note the node should only hold a uint scalar.
+unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node)
+{
+ assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar());
+ unsigned struct_dereference_index = node->getAsConstantUnion()->getConstArray()[0].getUConst();
+ return struct_dereference_index;
+}
+
+// A helper function to generate symbol_label.
+ObjectAccessChain generateSymbolLabel(glslang::TIntermSymbol* node)
+{
+ ObjectAccessChain symbol_id =
+ std::to_string(node->getId()) + "(" + node->getName().c_str() + ")";
+ return symbol_id;
+}
+
+// Returns true if the operation is an arithmetic operation and valid for
+// the 'NoContraction' decoration.
+bool isArithmeticOperation(glslang::TOperator op)
+{
+ switch (op) {
+ case glslang::EOpAddAssign:
+ case glslang::EOpSubAssign:
+ case glslang::EOpMulAssign:
+ case glslang::EOpVectorTimesMatrixAssign:
+ case glslang::EOpVectorTimesScalarAssign:
+ case glslang::EOpMatrixTimesScalarAssign:
+ case glslang::EOpMatrixTimesMatrixAssign:
+ case glslang::EOpDivAssign:
+ case glslang::EOpModAssign:
+
+ case glslang::EOpNegative:
+
+ case glslang::EOpAdd:
+ case glslang::EOpSub:
+ case glslang::EOpMul:
+ case glslang::EOpDiv:
+ case glslang::EOpMod:
+
+ case glslang::EOpVectorTimesScalar:
+ case glslang::EOpVectorTimesMatrix:
+ case glslang::EOpMatrixTimesVector:
+ case glslang::EOpMatrixTimesScalar:
+ case glslang::EOpMatrixTimesMatrix:
+
+ case glslang::EOpDot:
+
+ case glslang::EOpPostIncrement:
+ case glslang::EOpPostDecrement:
+ case glslang::EOpPreIncrement:
+ case glslang::EOpPreDecrement:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// A helper class to help manage the populating_initial_no_contraction_ flag.
+template <typename T> class StateSettingGuard {
+public:
+ StateSettingGuard(T* state_ptr, T new_state_value)
+ : state_ptr_(state_ptr), previous_state_(*state_ptr)
+ {
+ *state_ptr = new_state_value;
+ }
+ StateSettingGuard(T* state_ptr) : state_ptr_(state_ptr), previous_state_(*state_ptr) {}
+ void setState(T new_state_value) { *state_ptr_ = new_state_value; }
+ ~StateSettingGuard() { *state_ptr_ = previous_state_; }
+
+private:
+ T* state_ptr_;
+ T previous_state_;
+};
+
+// A helper function to get the front element from a given ObjectAccessChain
+ObjectAccessChain getFrontElement(const ObjectAccessChain& chain)
+{
+ size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
+ return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter);
+}
+
+// A helper function to get the access chain starting from the second element.
+ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain)
+{
+ size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
+ return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1);
+}
+
+// A helper function to get the access chain after removing a given prefix.
+ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain,
+ const ObjectAccessChain& prefix)
+{
+ size_t pos = chain.find(prefix);
+ if (pos != 0)
+ return chain;
+ return chain.substr(prefix.length() + sizeof(ObjectAccesschainDelimiter));
+}
+
+//
+// A traverser which traverses the whole AST and populates:
+// 1) A mapping from symbol nodes' IDs to their defining operation nodes.
+// 2) A set of access chains of the initial precise object nodes.
+//
+class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser {
+public:
+ TSymbolDefinitionCollectingTraverser(NodeMapping* symbol_definition_mapping,
+ AccessChainMapping* accesschain_mapping,
+ ObjectAccesschainSet* precise_objects,
+ ReturnBranchNodeSet* precise_return_nodes);
+
+ bool visitUnary(glslang::TVisit, glslang::TIntermUnary*) override;
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary*) override;
+ void visitSymbol(glslang::TIntermSymbol*) override;
+ bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*) override;
+ bool visitBranch(glslang::TVisit, glslang::TIntermBranch*) override;
+
+protected:
+ // The mapping from symbol node IDs to their defining nodes. This should be
+ // populated along traversing the AST.
+ NodeMapping& symbol_definition_mapping_;
+ // The set of symbol node IDs for precise symbol nodes, the ones marked as
+ // 'noContraction'.
+ ObjectAccesschainSet& precise_objects_;
+ // The set of precise return nodes.
+ ReturnBranchNodeSet& precise_return_nodes_;
+ // A temporary cache of the symbol node whose defining node is to be found
+ // currently along traversing the AST.
+ ObjectAccessChain current_object_;
+ // A map from object node to its access chain. This traverser stores
+ // the built access chains into this map for each object node it has
+ // visited.
+ AccessChainMapping& accesschain_mapping_;
+ // The pointer to the Function Definition node, so we can get the
+ // preciseness of the return expression from it when we traverse the
+ // return branch node.
+ glslang::TIntermAggregate* current_function_definition_node_;
+};
+
+TSymbolDefinitionCollectingTraverser::TSymbolDefinitionCollectingTraverser(
+ NodeMapping* symbol_definition_mapping, AccessChainMapping* accesschain_mapping,
+ ObjectAccesschainSet* precise_objects,
+ std::unordered_set<glslang::TIntermBranch*>* precise_return_nodes)
+ : TIntermTraverser(true, false, false), symbol_definition_mapping_(*symbol_definition_mapping),
+ precise_objects_(*precise_objects), current_object_(),
+ accesschain_mapping_(*accesschain_mapping), current_function_definition_node_(nullptr),
+ precise_return_nodes_(*precise_return_nodes) {}
+
+// Visits a symbol node, set the current_object_ to the
+// current node symbol ID, and record a mapping from this node to the current
+// current_object_, which is the just obtained symbol
+// ID.
+void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol* node)
+{
+ current_object_ = generateSymbolLabel(node);
+ accesschain_mapping_[node] = current_object_;
+}
+
+// Visits an aggregate node, traverses all of its children.
+bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit,
+ glslang::TIntermAggregate* node)
+{
+ // This aggregate node might be a function definition node, in which case we need to
+ // cache this node, so we can get the preciseness information of the return value
+ // of this function later.
+ StateSettingGuard<glslang::TIntermAggregate*> current_function_definition_node_setting_guard(
+ &current_function_definition_node_);
+ if (node->getOp() == glslang::EOpFunction) {
+ // This is function definition node, we need to cache this node so that we can
+ // get the preciseness of the return value later.
+ current_function_definition_node_setting_guard.setState(node);
+ }
+ // Traverse the items in the sequence.
+ glslang::TIntermSequence& seq = node->getSequence();
+ for (int i = 0; i < (int)seq.size(); ++i) {
+ current_object_.clear();
+ seq[i]->traverse(this);
+ }
+ return false;
+}
+
+bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit,
+ glslang::TIntermBranch* node)
+{
+ if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() &&
+ current_function_definition_node_ &&
+ current_function_definition_node_->getType().getQualifier().noContraction) {
+ // This node is a return node with an expression, and its function has a
+ // precise return value. We need to find the involved objects in its
+ // expression and add them to the set of initial precise objects.
+ precise_return_nodes_.insert(node);
+ node->getExpression()->traverse(this);
+ }
+ return false;
+}
+
+// Visits a unary node. This might be an implicit assignment like i++, i--. etc.
+bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */,
+ glslang::TIntermUnary* node)
+{
+ current_object_.clear();
+ node->getOperand()->traverse(this);
+ if (isAssignOperation(node->getOp())) {
+ // We should always be able to get an access chain of the operand node.
+ assert(!current_object_.empty());
+
+ // If the operand node object is 'precise', we collect its access chain
+ // for the initial set of 'precise' objects.
+ if (isPreciseObjectNode(node->getOperand())) {
+ // The operand node is an 'precise' object node, add its
+ // access chain to the set of 'precise' objects. This is to collect
+ // the initial set of 'precise' objects.
+ precise_objects_.insert(current_object_);
+ }
+ // Gets the symbol ID from the object's access chain.
+ ObjectAccessChain id_symbol = getFrontElement(current_object_);
+ // Add a mapping from the symbol ID to this assignment operation node.
+ symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
+ }
+ // A unary node is not a dereference node, so we clear the access chain which
+ // is under construction.
+ current_object_.clear();
+ return false;
+}
+
+// Visits a binary node and updates the mapping from symbol IDs to the definition
+// nodes. Also collects the access chains for the initial precise objects.
+bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */,
+ glslang::TIntermBinary* node)
+{
+ // Traverses the left node to build the access chain info for the object.
+ current_object_.clear();
+ node->getLeft()->traverse(this);
+
+ if (isAssignOperation(node->getOp())) {
+ // We should always be able to get an access chain for the left node.
+ assert(!current_object_.empty());
+
+ // If the left node object is 'precise', it is an initial precise object
+ // specified in the shader source. Adds it to the initial work list to
+ // process later.
+ if (isPreciseObjectNode(node->getLeft())) {
+ // The left node is an 'precise' object node, add its access chain to
+ // the set of 'precise' objects. This is to collect the initial set
+ // of 'precise' objects.
+ precise_objects_.insert(current_object_);
+ }
+ // Gets the symbol ID from the object access chain, which should be the
+ // first element recorded in the access chain.
+ ObjectAccessChain id_symbol = getFrontElement(current_object_);
+ // Adds a mapping from the symbol ID to this assignment operation node.
+ symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
+
+ // Traverses the right node, there may be other 'assignment'
+ // operations in the right.
+ current_object_.clear();
+ node->getRight()->traverse(this);
+
+ } else if (isDereferenceOperation(node->getOp())) {
+ // The left node (parent node) is a struct type object. We need to
+ // record the access chain information of the current node into its
+ // object id.
+ if (node->getOp() == glslang::EOpIndexDirectStruct) {
+ unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight());
+ current_object_.push_back(ObjectAccesschainDelimiter);
+ current_object_.append(std::to_string(struct_dereference_index));
+ }
+ accesschain_mapping_[node] = current_object_;
+
+ // For a dereference node, there is no need to traverse the right child
+ // node as the right node should always be an integer type object.
+
+ } else {
+ // For other binary nodes, still traverse the right node.
+ current_object_.clear();
+ node->getRight()->traverse(this);
+ }
+ return false;
+}
+
+// Traverses the AST and returns a tuple of four members:
+// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols.
+// 2) a mapping from object nodes in the AST to the access chains of these objects.
+// 3) a set of access chains of precise objects.
+// 4) a set of return nodes with precise expressions.
+std::tuple<NodeMapping, AccessChainMapping, ObjectAccesschainSet, ReturnBranchNodeSet>
+getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate)
+{
+ auto result_tuple = std::make_tuple(NodeMapping(), AccessChainMapping(), ObjectAccesschainSet(),
+ ReturnBranchNodeSet());
+
+ TIntermNode* root = intermediate.getTreeRoot();
+ if (root == 0)
+ return result_tuple;
+
+ NodeMapping& symbol_definition_mapping = std::get<0>(result_tuple);
+ AccessChainMapping& accesschain_mapping = std::get<1>(result_tuple);
+ ObjectAccesschainSet& precise_objects = std::get<2>(result_tuple);
+ ReturnBranchNodeSet& precise_return_nodes = std::get<3>(result_tuple);
+
+ // Traverses the AST and populate the results.
+ TSymbolDefinitionCollectingTraverser collector(&symbol_definition_mapping, &accesschain_mapping,
+ &precise_objects, &precise_return_nodes);
+ root->traverse(&collector);
+
+ return result_tuple;
+}
+
+//
+// A traverser that determine whether the left node (or operand node for unary
+// node) of an assignment node is 'precise', containing 'precise' or not,
+// according to the access chain a given precise object which share the same
+// symbol as the left node.
+//
+// Post-orderly traverses the left node subtree of an binary assignment node and:
+//
+// 1) Propagates the 'precise' from the left object nodes to this object node.
+//
+// 2) Builds object access chain along the traversal, and also compares with
+// the access chain of the given 'precise' object along with the traversal to
+// tell if the node to be defined is 'precise' or not.
+//
+class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser {
+
+ enum DecisionStatus {
+ // The object node to be assigned to may contain 'precise' objects and also not 'precise' objects.
+ Mixed = 0,
+ // The object node to be assigned to is either a 'precise' object or a struct objects whose members are all 'precise'.
+ Precise = 1,
+ // The object node to be assigned to is not a 'precise' object.
+ NotPreicse = 2,
+ };
+
+public:
+ TNoContractionAssigneeCheckingTraverser(const AccessChainMapping& accesschain_mapping)
+ : TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping),
+ precise_object_(nullptr) {}
+
+ // Checks the preciseness of a given assignment node with a precise object
+ // represented as access chain. The precise object shares the same symbol
+ // with the assignee of the given assignment node. Return a tuple of two:
+ //
+ // 1) The preciseness of the assignee node of this assignment node. True
+ // if the assignee contains 'precise' objects or is 'precise', false if
+ // the assignee is not 'precise' according to the access chain of the given
+ // precise object.
+ //
+ // 2) The incremental access chain from the assignee node to its nested
+ // 'precise' object, according to the access chain of the given precise
+ // object. This incremental access chain can be empty, which means the
+ // assignee is 'precise'. Otherwise it shows the path to the nested
+ // precise object.
+ std::tuple<bool, ObjectAccessChain>
+ getPrecisenessAndRemainedAccessChain(glslang::TIntermOperator* node,
+ const ObjectAccessChain& precise_object)
+ {
+ assert(isAssignOperation(node->getOp()));
+ precise_object_ = &precise_object;
+ ObjectAccessChain assignee_object;
+ if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) {
+ // This is a binary assignment node, we need to check the
+ // preciseness of the left node.
+ assert(accesschain_mapping_.count(BN->getLeft()));
+ // The left node (assignee node) is an object node, traverse the
+ // node to let the 'precise' of nesting objects being transfered to
+ // nested objects.
+ BN->getLeft()->traverse(this);
+ // After traversing the left node, if the left node is 'precise',
+ // we can conclude this assignment should propagate 'precise'.
+ if (isPreciseObjectNode(BN->getLeft())) {
+ return make_tuple(true, ObjectAccessChain());
+ }
+ // If the preciseness of the left node (assignee node) can not
+ // be determined by now, we need to compare the access chain string
+ // of the assignee object with the given precise object.
+ assignee_object = accesschain_mapping_.at(BN->getLeft());
+
+ } else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) {
+ // This is a unary assignment node, we need to check the
+ // preciseness of the operand node. For unary assignment node, the
+ // operand node should always be an object node.
+ assert(accesschain_mapping_.count(UN->getOperand()));
+ // Traverse the operand node to let the 'precise' being propagated
+ // from lower nodes to upper nodes.
+ UN->getOperand()->traverse(this);
+ // After traversing the operand node, if the operand node is
+ // 'precise', this assignment should propagate 'precise'.
+ if (isPreciseObjectNode(UN->getOperand())) {
+ return make_tuple(true, ObjectAccessChain());
+ }
+ // If the preciseness of the operand node (assignee node) can not
+ // be determined by now, we need to compare the access chain string
+ // of the assignee object with the given precise object.
+ assignee_object = accesschain_mapping_.at(UN->getOperand());
+ } else {
+ // Not a binary or unary node, should not happen.
+ assert(false);
+ }
+
+ // Compare the access chain string of the assignee node with the given
+ // precise object to determine if this assignment should propagate
+ // 'precise'.
+ if (assignee_object.find(precise_object) == 0) {
+ // The access chain string of the given precise object is a prefix
+ // of assignee's access chain string. The assignee should be
+ // 'precise'.
+ return make_tuple(true, ObjectAccessChain());
+ } else if (precise_object.find(assignee_object) == 0) {
+ // The assignee's access chain string is a prefix of the given
+ // precise object, the assignee object contains 'precise' object,
+ // and we need to pass the remained access chain to the object nodes
+ // in the right.
+ return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object));
+ } else {
+ // The access chain strings do not match, the assignee object can
+ // not be labeled as 'precise' according to the given precise
+ // object.
+ return make_tuple(false, ObjectAccessChain());
+ }
+ }
+
+protected:
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override;
+ void visitSymbol(glslang::TIntermSymbol* node) override;
+
+ // A map from object nodes to their access chain string (used as object ID).
+ const AccessChainMapping& accesschain_mapping_;
+ // A given precise object, represented in it access chain string. This
+ // precise object is used to be compared with the assignee node to tell if
+ // the assignee node is 'precise', contains 'precise' object or not
+ // 'precise'.
+ const ObjectAccessChain* precise_object_;
+};
+
+// Visits a binary node. If the node is an object node, it must be a dereference
+// node. In such cases, if the left node is 'precise', this node should also be
+// 'precise'.
+bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit,
+ glslang::TIntermBinary* node)
+{
+ // Traverses the left so that we transfer the 'precise' from nesting object
+ // to its nested object.
+ node->getLeft()->traverse(this);
+ // If this binary node is an object node, we should have it in the
+ // accesschain_mapping_.
+ if (accesschain_mapping_.count(node)) {
+ // A binary object node must be a dereference node.
+ assert(isDereferenceOperation(node->getOp()));
+ // If the left node is 'precise', this node should also be precise,
+ // otherwise, compare with the given precise_object_. If the
+ // access chain of this node matches with the given precise_object_,
+ // this node should be marked as 'precise'.
+ if (isPreciseObjectNode(node->getLeft())) {
+ node->getWritableType().getQualifier().noContraction = true;
+ } else if (accesschain_mapping_.at(node) == *precise_object_) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+ }
+ return false;
+}
+
+// Visits a symbol node, if the symbol node ID (its access chain string) matches
+// with the given precise object, this node should be 'precise'.
+void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node)
+{
+ // A symbol node should always be an object node, and should have been added
+ // to the map from object nodes to their access chain strings.
+ assert(accesschain_mapping_.count(node));
+ if (accesschain_mapping_.at(node) == *precise_object_) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+}
+
+//
+// A traverser that only traverses the right side of binary assignment nodes
+// and the operand node of unary assignment nodes.
+//
+// 1) Marks arithmetic operations as 'NoContraction'.
+//
+// 2) Find the object which should be marked as 'precise' in the right and
+// update the 'precise' object work list.
+//
+class TNoContractionPropagator : public glslang::TIntermTraverser {
+public:
+ TNoContractionPropagator(ObjectAccesschainSet* precise_objects,
+ const AccessChainMapping& accesschain_mapping)
+ : TIntermTraverser(true, false, false), remained_accesschain_(),
+ precise_objects_(*precise_objects), accesschain_mapping_(accesschain_mapping),
+ added_precise_object_ids_() {}
+
+ // Propagates 'precise' in the right nodes of a given assignment node with
+ // access chain record from the assignee node to a 'precise' object it
+ // contains.
+ void
+ propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node,
+ const ObjectAccessChain& assignee_remained_accesschain)
+ {
+ remained_accesschain_ = assignee_remained_accesschain;
+ if (glslang::TIntermBinary* BN = defining_node->getAsBinaryNode()) {
+ assert(isAssignOperation(BN->getOp()));
+ BN->getRight()->traverse(this);
+ if (isArithmeticOperation(BN->getOp())) {
+ BN->getWritableType().getQualifier().noContraction = true;
+ }
+ } else if (glslang::TIntermUnary* UN = defining_node->getAsUnaryNode()) {
+ assert(isAssignOperation(UN->getOp()));
+ UN->getOperand()->traverse(this);
+ if (isArithmeticOperation(UN->getOp())) {
+ UN->getWritableType().getQualifier().noContraction = true;
+ }
+ }
+ }
+
+ // Propagates 'precise' in a given precise return node.
+ void propagateNoContractionInReturnNode(glslang::TIntermBranch* return_node)
+ {
+ remained_accesschain_ = "";
+ assert(return_node->getFlowOp() == glslang::EOpReturn && return_node->getExpression());
+ return_node->getExpression()->traverse(this);
+ }
+
+protected:
+ // Visits an aggregate node. The node can be a initializer list, in which
+ // case we need to find the 'precise' or 'precise' containing object node
+ // with the access chain record. In other cases, just need to traverse all
+ // the children nodes.
+ bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override
+ {
+ if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) {
+ // This is a struct initializer node, and the remained
+ // access chain is not empty, we need to refer to the
+ // assignee_remained_access_chain_ to find the nested
+ // 'precise' object. And we don't need to visit other nodes in this
+ // aggregate node.
+
+ // Gets the struct dereference index that leads to 'precise' object.
+ ObjectAccessChain precise_accesschain_index_str =
+ getFrontElement(remained_accesschain_);
+ unsigned precise_accesschain_index = strtoul(precise_accesschain_index_str.c_str(), nullptr, 10);
+ // Gets the node pointed by the access chain index extracted before.
+ glslang::TIntermTyped* potential_precise_node =
+ node->getSequence()[precise_accesschain_index]->getAsTyped();
+ assert(potential_precise_node);
+ // Pop the front access chain index from the path, and visit the nested node.
+ {
+ ObjectAccessChain next_level_accesschain =
+ subAccessChainFromSecondElement(remained_accesschain_);
+ StateSettingGuard<ObjectAccessChain> setup_remained_accesschain_for_next_level(
+ &remained_accesschain_, next_level_accesschain);
+ potential_precise_node->traverse(this);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // Visits a binary node. A binary node can be an object node, e.g. a dereference node.
+ // As only the top object nodes in the right side of an assignment needs to be visited
+ // and added to 'precise' work list, this traverser won't visit the children nodes of
+ // an object node. If the binary node does not represent an object node, it should
+ // go on to traverse its children nodes and if it is an arithmetic operation node, this
+ // operation should be marked as 'noContraction'.
+ bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override
+ {
+ if (isDereferenceOperation(node->getOp())) {
+ // This binary node is an object node. Need to update the precise
+ // object set with the access chain of this node + remained
+ // access chain .
+ ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
+ if (remained_accesschain_.empty()) {
+ node->getWritableType().getQualifier().noContraction = true;
+ } else {
+ new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
+ }
+ // Cache the access chain as added precise object, so we won't add the
+ // same object to the work list again.
+ if (!added_precise_object_ids_.count(new_precise_accesschain)) {
+ precise_objects_.insert(new_precise_accesschain);
+ added_precise_object_ids_.insert(new_precise_accesschain);
+ }
+ // Only the upper-most object nodes should be visited, so do not
+ // visit children of this object node.
+ return false;
+ }
+ // If this is an arithmetic operation, marks this node as 'noContraction'.
+ if (isArithmeticOperation(node->getOp()) && node->getBasicType() != glslang::EbtInt) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+ // As this node is not an object node, need to traverse the children nodes.
+ return true;
+ }
+
+ // Visits a unary node. A unary node can not be an object node. If the operation
+ // is an arithmetic operation, need to mark this node as 'noContraction'.
+ bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override
+ {
+ // If this is an arithmetic operation, marks this with 'noContraction'
+ if (isArithmeticOperation(node->getOp())) {
+ node->getWritableType().getQualifier().noContraction = true;
+ }
+ return true;
+ }
+
+ // Visits a symbol node. A symbol node is always an object node. So we
+ // should always be able to find its in our collected mapping from object
+ // nodes to access chains. As an object node, a symbol node can be either
+ // 'precise' or containing 'precise' objects according to unused
+ // access chain information we have when we visit this node.
+ void visitSymbol(glslang::TIntermSymbol* node) override
+ {
+ // Symbol nodes are object nodes and should always have an
+ // access chain collected before matches with it.
+ assert(accesschain_mapping_.count(node));
+ ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
+ // If the unused access chain is empty, this symbol node should be
+ // marked as 'precise'. Otherwise, the unused access chain should be
+ // appended to the symbol ID to build a new access chain which points to
+ // the nested 'precise' object in this symbol object.
+ if (remained_accesschain_.empty()) {
+ node->getWritableType().getQualifier().noContraction = true;
+ } else {
+ new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
+ }
+ // Add the new 'precise' access chain to the work list and make sure we
+ // don't visit it again.
+ if (!added_precise_object_ids_.count(new_precise_accesschain)) {
+ precise_objects_.insert(new_precise_accesschain);
+ added_precise_object_ids_.insert(new_precise_accesschain);
+ }
+ }
+
+ // A set of precise objects, represented as access chains.
+ ObjectAccesschainSet& precise_objects_;
+ // Visited symbol nodes, should not revisit these nodes.
+ ObjectAccesschainSet added_precise_object_ids_;
+ // The left node of an assignment operation might be an parent of 'precise' objects.
+ // This means the left node might not be an 'precise' object node, but it may contains
+ // 'precise' qualifier which should be propagated to the corresponding child node in
+ // the right. So we need the path from the left node to its nested 'precise' node to
+ // tell us how to find the corresponding 'precise' node in the right.
+ ObjectAccessChain remained_accesschain_;
+ // A map from node pointers to their access chains.
+ const AccessChainMapping& accesschain_mapping_;
+};
+}
+
+namespace glslang {
+
+void PropagateNoContraction(const glslang::TIntermediate& intermediate)
+{
+ // First, traverses the AST, records symbols with their defining operations
+ // and collects the initial set of precise symbols (symbol nodes that marked
+ // as 'noContraction') and precise return nodes.
+ auto mappings_and_precise_objects =
+ getSymbolToDefinitionMappingAndPreciseSymbolIDs(intermediate);
+
+ // The mapping of symbol node IDs to their defining nodes. This enables us
+ // to get the defining node directly from a given symbol ID without
+ // traversing the tree again.
+ NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects);
+
+ // The mapping of object nodes to their access chains recorded.
+ AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects);
+
+ // The initial set of 'precise' objects which are represented as the
+ // access chain toward them.
+ ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects);
+
+ // The set of 'precise' return nodes.
+ ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects);
+
+ // Second, uses the initial set of precise objects as a work list, pops an
+ // access chain, extract the symbol ID from it. Then:
+ // 1) Check the assignee object, see if it is 'precise' object node or
+ // contains 'precise' object. Obtain the incremental access chain from the
+ // assignee node to its nested 'precise' node (if any).
+ // 2) If the assignee object node is 'precise' or it contains 'precise'
+ // objects, traverses the right side of the assignment operation
+ // expression to mark arithmetic operations as 'noContration' and update
+ // 'precise' access chain work list with new found object nodes.
+ // Repeat above steps until the work list is empty.
+ TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping);
+ TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping);
+
+ // We have two initial precise work lists to handle:
+ // 1) precise return nodes
+ // 2) precise object access chains
+ // We should process the precise return nodes first and the involved
+ // objects in the return expression should be added to the precise object
+ // access chain set.
+ while (!precise_return_nodes.empty()) {
+ glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin();
+ propagator.propagateNoContractionInReturnNode(precise_return_node);
+ precise_return_nodes.erase(precise_return_node);
+ }
+
+ while (!precise_object_accesschains.empty()) {
+ // Get the access chain of a precise object from the work list.
+ ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin();
+ // Get the symbol id from the access chain.
+ ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain);
+ // Get all the defining nodes of that symbol ID.
+ std::pair<NodeMapping::iterator, NodeMapping::iterator> range =
+ symbol_definition_mapping.equal_range(symbol_id);
+ // Visits all the assignment nodes of that symbol ID and
+ // 1) Check if the assignee node is 'precise' or contains 'precise'
+ // objects.
+ // 2) Propagate the 'precise' to the top layer object nodes
+ // in the right side of the assignment operation, update the 'precise'
+ // work list with new access chains representing the new 'precise'
+ // objects, and mark arithmetic operations as 'noContraction'.
+ for (NodeMapping::iterator defining_node_iter = range.first;
+ defining_node_iter != range.second; defining_node_iter++) {
+ TIntermOperator* defining_node = defining_node_iter->second;
+ // Check the assignee node.
+ auto checker_result = checker.getPrecisenessAndRemainedAccessChain(
+ defining_node, precise_object_accesschain);
+ bool& contain_precise = std::get<0>(checker_result);
+ ObjectAccessChain& remained_accesschain = std::get<1>(checker_result);
+ // If the assignee node is 'precise' or contains 'precise', propagate the
+ // 'precise' to the right. Otherwise just skip this assignment node.
+ if (contain_precise) {
+ propagator.propagateNoContractionInOneExpression(defining_node,
+ remained_accesschain);
+ }
+ }
+ // Remove the last processed 'precise' object from the work list.
+ precise_object_accesschains.erase(precise_object_accesschain);
+ }
+}
+};
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.h
new file mode 100644
index 00000000000..3412c85dc6c
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.h
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2015-2016 Google, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Visit the nodes in the glslang intermediate tree representation to
+// propagate 'noContraction' qualifier.
+//
+
+#include "../Include/intermediate.h"
+
+namespace glslang {
+
+// Propagates the 'precise' qualifier for objects (objects marked with
+// 'noContraction' qualifier) from the shader source specified 'precise'
+// variables to all the involved objects, and add 'noContraction' qualifier for
+// the involved arithmetic operations.
+// Note that the same qualifier: 'noContraction' is used in both object nodes
+// and arithmetic operation nodes, but has different meaning. For object nodes,
+// 'noContraction' means the object is 'precise'; and for arithmetic operation
+// nodes, it means the operation should not be contracted.
+void PropagateNoContraction(const glslang::TIntermediate& intermediate);
+};
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp
new file mode 100644
index 00000000000..d3e04af7f97
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp
@@ -0,0 +1,761 @@
+//
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/Common.h"
+#include "reflection.h"
+#include "localintermediate.h"
+
+#include "gl_types.h"
+
+//
+// Grow the reflection database through a friend traverser class of TReflection and a
+// collection of functions to do a liveness traversal that note what uniforms are used
+// in semantically non-dead code.
+//
+// Can be used multiple times, once per stage, to grow a program reflection.
+//
+// High-level algorithm for one stage:
+//
+// 1. Put main() on list of live functions.
+//
+// 2. Traverse any live function, while skipping if-tests with a compile-time constant
+// condition of false, and while adding any encountered function calls to the live
+// function list.
+//
+// Repeat until the live function list is empty.
+//
+// 3. Add any encountered uniform variables and blocks to the reflection database.
+//
+// Can be attempted with a failed link, but will return false if recursion had been detected, or
+// there wasn't exactly one main.
+//
+
+namespace glslang {
+
+//
+// The traverser: mostly pass through, except
+// - processing function-call nodes to push live functions onto the stack of functions to process
+// - processing binary nodes to see if they are dereferences of an aggregates to track
+// - processing symbol nodes to see if they are non-aggregate objects to track
+// - processing selection nodes to trim semantically dead code
+//
+// This is in the glslang namespace directly so it can be a friend of TReflection.
+//
+
+class TLiveTraverser : public TIntermTraverser {
+public:
+ TLiveTraverser(const TIntermediate& i, TReflection& r) : intermediate(i), reflection(r) { }
+
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node);
+ virtual bool visitBinary(TVisit, TIntermBinary* node);
+ virtual void visitSymbol(TIntermSymbol* base);
+ virtual bool visitSelection(TVisit, TIntermSelection* node);
+
+ // Track live funtions as well as uniforms, so that we don't visit dead functions
+ // and only visit each function once.
+ void addFunctionCall(TIntermAggregate* call)
+ {
+ // just use the map to ensure we process each function at most once
+ if (reflection.nameToIndex.find(call->getName()) == reflection.nameToIndex.end()) {
+ reflection.nameToIndex[call->getName()] = -1;
+ pushFunction(call->getName());
+ }
+ }
+
+ // Add a simple reference to a uniform variable to the uniform database, no dereference involved.
+ // However, no dereference doesn't mean simple... it could be a complex aggregate.
+ void addUniform(const TIntermSymbol& base)
+ {
+ if (processedDerefs.find(&base) == processedDerefs.end()) {
+ processedDerefs.insert(&base);
+
+ // Use a degenerate (empty) set of dereferences to immediately put as at the end of
+ // the dereference change expected by blowUpActiveAggregate.
+ TList<TIntermBinary*> derefs;
+ blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0);
+ }
+ }
+
+ void addAttribute(const TIntermSymbol& base)
+ {
+ if (processedDerefs.find(&base) == processedDerefs.end()) {
+ processedDerefs.insert(&base);
+
+ const TString &name = base.getName();
+ const TType &type = base.getType();
+
+ TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
+ if (it == reflection.nameToIndex.end()) {
+ reflection.nameToIndex[name] = (int)reflection.indexToAttribute.size();
+ reflection.indexToAttribute.push_back(TObjectReflection(name, 0, mapToGlType(type), 0, 0));
+ }
+ }
+ }
+
+ // Lookup or calculate the offset of a block member, using the recursively
+ // defined block offset rules.
+ int getOffset(const TType& type, int index)
+ {
+ const TTypeList& memberList = *type.getStruct();
+
+ // Don't calculate offset if one is present, it could be user supplied
+ // and different than what would be calculated. That is, this is faster,
+ // but not just an optimization.
+ if (memberList[index].type->getQualifier().hasOffset())
+ return memberList[index].type->getQualifier().layoutOffset;
+
+ int memberSize;
+ int dummyStride;
+ int offset = 0;
+ for (int m = 0; m <= index; ++m) {
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+ int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride, type.getQualifier().layoutPacking == ElpStd140,
+ subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : type.getQualifier().layoutMatrix == ElmRowMajor);
+ RoundToPow2(offset, memberAlignment);
+ if (m < index)
+ offset += memberSize;
+ }
+
+ return offset;
+ }
+
+ // Calculate the block data size.
+ // Block arrayness is not taken into account, each element is backed by a separate buffer.
+ int getBlockSize(const TType& blockType)
+ {
+ const TTypeList& memberList = *blockType.getStruct();
+ int lastIndex = (int)memberList.size() - 1;
+ int lastOffset = getOffset(blockType, lastIndex);
+
+ int lastMemberSize;
+ int dummyStride;
+ intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, blockType.getQualifier().layoutPacking == ElpStd140,
+ blockType.getQualifier().layoutMatrix == ElmRowMajor);
+
+ return lastOffset + lastMemberSize;
+ }
+
+ // Traverse the provided deref chain, including the base, and
+ // - build a full reflection-granularity name, array size, etc. entry out of it, if it goes down to that granularity
+ // - recursively expand any variable array index in the middle of that traversal
+ // - recursively expand what's left at the end if the deref chain did not reach down to reflection granularity
+ //
+ // arraySize tracks, just for the final dereference in the chain, if there was a specific known size.
+ // A value of 0 for arraySize will mean to use the full array's size.
+ void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
+ TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize)
+ {
+ // process the part of the derefence chain that was explicit in the shader
+ TString name = baseName;
+ const TType* terminalType = &baseType;
+ for (; deref != derefs.end(); ++deref) {
+ TIntermBinary* visitNode = *deref;
+ terminalType = &visitNode->getType();
+ int index;
+ switch (visitNode->getOp()) {
+ case EOpIndexIndirect:
+ // Visit all the indices of this array, and for each one add on the remaining dereferencing
+ for (int i = 0; i < visitNode->getLeft()->getType().getOuterArraySize(); ++i) {
+ TString newBaseName = name;
+ if (baseType.getBasicType() != EbtBlock)
+ newBaseName.append(TString("[") + String(i) + "]");
+ TList<TIntermBinary*>::const_iterator nextDeref = deref;
+ ++nextDeref;
+ TType derefType(*terminalType, 0);
+ blowUpActiveAggregate(derefType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize);
+ }
+
+ // it was all completed in the recursive calls above
+ return;
+ case EOpIndexDirect:
+ index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (baseType.getBasicType() != EbtBlock)
+ name.append(TString("[") + String(index) + "]");
+ break;
+ case EOpIndexDirectStruct:
+ index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+ if (offset >= 0)
+ offset += getOffset(visitNode->getLeft()->getType(), index);
+ if (name.size() > 0)
+ name.append(".");
+ name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
+ break;
+ default:
+ break;
+ }
+ }
+
+ // if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it...
+ if (! isReflectionGranularity(*terminalType)) {
+ if (terminalType->isArray()) {
+ // Visit all the indices of this array, and for each one,
+ // fully explode the remaining aggregate to dereference
+ for (int i = 0; i < terminalType->getOuterArraySize(); ++i) {
+ TString newBaseName = name;
+ newBaseName.append(TString("[") + String(i) + "]");
+ TType derefType(*terminalType, 0);
+ blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0);
+ }
+ } else {
+ // Visit all members of this aggregate, and for each one,
+ // fully explode the remaining aggregate to dereference
+ const TTypeList& typeList = *terminalType->getStruct();
+ for (int i = 0; i < (int)typeList.size(); ++i) {
+ TString newBaseName = name;
+ newBaseName.append(TString(".") + typeList[i].type->getFieldName());
+ TType derefType(*terminalType, i);
+ blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0);
+ }
+ }
+
+ // it was all completed in the recursive calls above
+ return;
+ }
+
+ // Finally, add a full string to the reflection database, and update the array size if necessary.
+ // If the derefenced entity to record is an array, compute the size and update the maximum size.
+
+ // there might not be a final array dereference, it could have been copied as an array object
+ if (arraySize == 0)
+ arraySize = mapToGlArraySize(*terminalType);
+
+ TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
+ if (it == reflection.nameToIndex.end()) {
+ reflection.nameToIndex[name] = (int)reflection.indexToUniform.size();
+ reflection.indexToUniform.push_back(TObjectReflection(name, offset, mapToGlType(*terminalType), arraySize, blockIndex));
+ } else if (arraySize > 1) {
+ int& reflectedArraySize = reflection.indexToUniform[it->second].size;
+ reflectedArraySize = std::max(arraySize, reflectedArraySize);
+ }
+ }
+
+ // Add a uniform dereference where blocks/struct/arrays are involved in the access.
+ // Handles the situation where the left node is at the correct or too coarse a
+ // granularity for reflection. (That is, further dereferences up the tree will be
+ // skipped.) Earlier dereferences, down the tree, will be handled
+ // at the same time, and logged to prevent reprocessing as the tree is traversed.
+ //
+ // Note: Other things like the following must be caught elsewhere:
+ // - a simple non-array, non-struct variable (no dereference even conceivable)
+ // - an aggregrate consumed en masse, without a dereference
+ //
+ // So, this code is for cases like
+ // - a struct/block dereferencing a member (whether the member is array or not)
+ // - an array of struct
+ // - structs/arrays containing the above
+ //
+ void addDereferencedUniform(TIntermBinary* topNode)
+ {
+ // See if too fine-grained to process (wait to get further down the tree)
+ const TType& leftType = topNode->getLeft()->getType();
+ if ((leftType.isVector() || leftType.isMatrix()) && ! leftType.isArray())
+ return;
+
+ // We have an array or structure or block dereference, see if it's a uniform
+ // based dereference (if not, skip it).
+ TIntermSymbol* base = findBase(topNode);
+ if (! base || ! base->getQualifier().isUniformOrBuffer())
+ return;
+
+ // See if we've already processed this (e.g., in the middle of something
+ // we did earlier), and if so skip it
+ if (processedDerefs.find(topNode) != processedDerefs.end())
+ return;
+
+ // Process this uniform dereference
+
+ int offset = -1;
+ int blockIndex = -1;
+ bool anonymous = false;
+
+ // See if we need to record the block itself
+ bool block = base->getBasicType() == EbtBlock;
+ if (block) {
+ offset = 0;
+ anonymous = IsAnonymous(base->getName());
+ if (base->getType().isArray()) {
+ assert(! anonymous);
+ for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
+ blockIndex = addBlockName(base->getType().getTypeName() + "[" + String(e) + "]", getBlockSize(base->getType()));
+ } else
+ blockIndex = addBlockName(base->getType().getTypeName(), getBlockSize(base->getType()));
+ }
+
+ // Process the dereference chain, backward, accumulating the pieces for later forward traversal.
+ // If the topNode is a reflection-granularity-array dereference, don't include that last dereference.
+ TList<TIntermBinary*> derefs;
+ for (TIntermBinary* visitNode = topNode; visitNode; visitNode = visitNode->getLeft()->getAsBinaryNode()) {
+ if (isReflectionGranularity(visitNode->getLeft()->getType()))
+ continue;
+
+ derefs.push_front(visitNode);
+ processedDerefs.insert(visitNode);
+ }
+ processedDerefs.insert(base);
+
+ // See if we have a specific array size to stick to while enumerating the explosion of the aggregate
+ int arraySize = 0;
+ if (isReflectionGranularity(topNode->getLeft()->getType()) && topNode->getLeft()->isArray()) {
+ if (topNode->getOp() == EOpIndexDirect)
+ arraySize = topNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst() + 1;
+ }
+
+ // Put the dereference chain together, forward
+ TString baseName;
+ if (! anonymous) {
+ if (block)
+ baseName = base->getType().getTypeName();
+ else
+ baseName = base->getName();
+ }
+ blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize);
+ }
+
+ int addBlockName(const TString& name, int size)
+ {
+ int blockIndex;
+ TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name);
+ if (reflection.nameToIndex.find(name) == reflection.nameToIndex.end()) {
+ blockIndex = (int)reflection.indexToUniformBlock.size();
+ reflection.nameToIndex[name] = blockIndex;
+ reflection.indexToUniformBlock.push_back(TObjectReflection(name, -1, -1, size, -1));
+ } else
+ blockIndex = it->second;
+
+ return blockIndex;
+ }
+
+ //
+ // Given a function name, find its subroot in the tree, and push it onto the stack of
+ // functions left to process.
+ //
+ void pushFunction(const TString& name)
+ {
+ TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
+ for (unsigned int f = 0; f < globals.size(); ++f) {
+ TIntermAggregate* candidate = globals[f]->getAsAggregate();
+ if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
+ functions.push_back(candidate);
+ break;
+ }
+ }
+ }
+
+ // Are we at a level in a dereference chain at which individual active uniform queries are made?
+ bool isReflectionGranularity(const TType& type)
+ {
+ return type.getBasicType() != EbtBlock && type.getBasicType() != EbtStruct;
+ }
+
+ // For a binary operation indexing into an aggregate, chase down the base of the aggregate.
+ // Return 0 if the topology does not fit this situation.
+ TIntermSymbol* findBase(const TIntermBinary* node)
+ {
+ TIntermSymbol *base = node->getLeft()->getAsSymbolNode();
+ if (base)
+ return base;
+ TIntermBinary* left = node->getLeft()->getAsBinaryNode();
+ if (! left)
+ return nullptr;
+
+ return findBase(left);
+ }
+
+ //
+ // Translate a glslang sampler type into the GL API #define number.
+ //
+ int mapSamplerToGlType(TSampler sampler)
+ {
+ if (! sampler.image) {
+ // a sampler...
+ switch (sampler.type) {
+ case EbtFloat:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY : GL_SAMPLER_1D;
+ case true: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY_SHADOW : GL_SAMPLER_1D_SHADOW;
+ }
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY : GL_SAMPLER_2D;
+ case true: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY_SHADOW : GL_SAMPLER_2D_SHADOW;
+ }
+ case true: return sampler.arrayed ? GL_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_SAMPLER_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_SAMPLER_3D;
+ case EsdCube:
+ switch ((int)sampler.shadow) {
+ case false: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY : GL_SAMPLER_CUBE;
+ case true: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW : GL_SAMPLER_CUBE_SHADOW;
+ }
+ case EsdRect:
+ return sampler.shadow ? GL_SAMPLER_2D_RECT_SHADOW : GL_SAMPLER_2D_RECT;
+ case EsdBuffer:
+ return GL_SAMPLER_BUFFER;
+ }
+ case EbtInt:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_INT_SAMPLER_1D_ARRAY : GL_INT_SAMPLER_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_INT_SAMPLER_2D_ARRAY : GL_INT_SAMPLER_2D;
+ case true: return sampler.arrayed ? GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_INT_SAMPLER_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_INT_SAMPLER_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_INT_SAMPLER_CUBE_MAP_ARRAY : GL_INT_SAMPLER_CUBE;
+ case EsdRect:
+ return GL_INT_SAMPLER_2D_RECT;
+ case EsdBuffer:
+ return GL_INT_SAMPLER_BUFFER;
+ }
+ case EbtUint:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_1D_ARRAY : GL_UNSIGNED_INT_SAMPLER_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D;
+ case true: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_UNSIGNED_INT_SAMPLER_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_SAMPLER_CUBE;
+ case EsdRect:
+ return GL_UNSIGNED_INT_SAMPLER_2D_RECT;
+ case EsdBuffer:
+ return GL_UNSIGNED_INT_SAMPLER_BUFFER;
+ }
+ default:
+ return 0;
+ }
+ } else {
+ // an image...
+ switch (sampler.type) {
+ case EbtFloat:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_IMAGE_1D_ARRAY : GL_IMAGE_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_IMAGE_2D_ARRAY : GL_IMAGE_2D;
+ case true: return sampler.arrayed ? GL_IMAGE_2D_MULTISAMPLE_ARRAY : GL_IMAGE_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_IMAGE_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_IMAGE_CUBE_MAP_ARRAY : GL_IMAGE_CUBE;
+ case EsdRect:
+ return GL_IMAGE_2D_RECT;
+ case EsdBuffer:
+ return GL_IMAGE_BUFFER;
+ }
+ case EbtInt:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_INT_IMAGE_1D_ARRAY : GL_INT_IMAGE_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_INT_IMAGE_2D_ARRAY : GL_INT_IMAGE_2D;
+ case true: return sampler.arrayed ? GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY : GL_INT_IMAGE_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_INT_IMAGE_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_INT_IMAGE_CUBE_MAP_ARRAY : GL_INT_IMAGE_CUBE;
+ case EsdRect:
+ return GL_INT_IMAGE_2D_RECT;
+ case EsdBuffer:
+ return GL_INT_IMAGE_BUFFER;
+ }
+ case EbtUint:
+ switch ((int)sampler.dim) {
+ case Esd1D:
+ return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_1D_ARRAY : GL_UNSIGNED_INT_IMAGE_1D;
+ case Esd2D:
+ switch ((int)sampler.ms) {
+ case false: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_ARRAY : GL_UNSIGNED_INT_IMAGE_2D;
+ case true: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY : GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
+ }
+ case Esd3D:
+ return GL_UNSIGNED_INT_IMAGE_3D;
+ case EsdCube:
+ return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_IMAGE_CUBE;
+ case EsdRect:
+ return GL_UNSIGNED_INT_IMAGE_2D_RECT;
+ case EsdBuffer:
+ return GL_UNSIGNED_INT_IMAGE_BUFFER;
+ }
+ default:
+ return 0;
+ }
+ }
+ }
+
+ //
+ // Translate a glslang type into the GL API #define number.
+ // Ignores arrayness.
+ //
+ int mapToGlType(const TType& type)
+ {
+ switch (type.getBasicType()) {
+ case EbtSampler:
+ return mapSamplerToGlType(type.getSampler());
+ case EbtStruct:
+ case EbtBlock:
+ case EbtVoid:
+ return 0;
+ default:
+ break;
+ }
+
+ if (type.isVector()) {
+ int offset = type.getVectorSize() - 2;
+ switch (type.getBasicType()) {
+ case EbtFloat: return GL_FLOAT_VEC2 + offset;
+ case EbtDouble: return GL_DOUBLE_VEC2 + offset;
+ case EbtInt: return GL_INT_VEC2 + offset;
+ case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset;
+ case EbtInt64: return GL_INT64_ARB + offset;
+ case EbtUint64: return GL_UNSIGNED_INT64_ARB + offset;
+ case EbtBool: return GL_BOOL_VEC2 + offset;
+ case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
+ default: return 0;
+ }
+ }
+ if (type.isMatrix()) {
+ switch (type.getBasicType()) {
+ case EbtFloat:
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT_MAT2;
+ case 3: return GL_FLOAT_MAT2x3;
+ case 4: return GL_FLOAT_MAT2x4;
+ default: return 0;
+ }
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT_MAT3x2;
+ case 3: return GL_FLOAT_MAT3;
+ case 4: return GL_FLOAT_MAT3x4;
+ default: return 0;
+ }
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_FLOAT_MAT4x2;
+ case 3: return GL_FLOAT_MAT4x3;
+ case 4: return GL_FLOAT_MAT4;
+ default: return 0;
+ }
+ }
+ case EbtDouble:
+ switch (type.getMatrixCols()) {
+ case 2:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_DOUBLE_MAT2;
+ case 3: return GL_DOUBLE_MAT2x3;
+ case 4: return GL_DOUBLE_MAT2x4;
+ default: return 0;
+ }
+ case 3:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_DOUBLE_MAT3x2;
+ case 3: return GL_DOUBLE_MAT3;
+ case 4: return GL_DOUBLE_MAT3x4;
+ default: return 0;
+ }
+ case 4:
+ switch (type.getMatrixRows()) {
+ case 2: return GL_DOUBLE_MAT4x2;
+ case 3: return GL_DOUBLE_MAT4x3;
+ case 4: return GL_DOUBLE_MAT4;
+ default: return 0;
+ }
+ }
+ default:
+ return 0;
+ }
+ }
+ if (type.getVectorSize() == 1) {
+ switch (type.getBasicType()) {
+ case EbtFloat: return GL_FLOAT;
+ case EbtDouble: return GL_DOUBLE;
+ case EbtInt: return GL_INT;
+ case EbtUint: return GL_UNSIGNED_INT;
+ case EbtInt64: return GL_INT64_ARB;
+ case EbtUint64: return GL_UNSIGNED_INT64_ARB;
+ case EbtBool: return GL_BOOL;
+ case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER;
+ default: return 0;
+ }
+ }
+
+ return 0;
+ }
+
+ int mapToGlArraySize(const TType& type)
+ {
+ return type.isArray() ? type.getOuterArraySize() : 1;
+ }
+
+ typedef std::list<TIntermAggregate*> TFunctionStack;
+ TFunctionStack functions;
+ const TIntermediate& intermediate;
+ TReflection& reflection;
+ std::set<const TIntermNode*> processedDerefs;
+
+protected:
+ TLiveTraverser(TLiveTraverser&);
+ TLiveTraverser& operator=(TLiveTraverser&);
+};
+
+//
+// Implement the traversal functions of interest.
+//
+
+// To catch which function calls are not dead, and hence which functions must be visited.
+bool TLiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
+{
+ if (node->getOp() == EOpFunctionCall)
+ addFunctionCall(node);
+
+ return true; // traverse this subtree
+}
+
+// To catch dereferenced aggregates that must be reflected.
+// This catches them at the highest level possible in the tree.
+bool TLiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
+{
+ switch (node->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ addDereferencedUniform(node);
+ break;
+ default:
+ break;
+ }
+
+ // still need to visit everything below, which could contain sub-expressions
+ // containing different uniforms
+ return true;
+}
+
+// To reflect non-dereferenced objects.
+void TLiveTraverser::visitSymbol(TIntermSymbol* base)
+{
+ if (base->getQualifier().storage == EvqUniform)
+ addUniform(*base);
+
+ if (intermediate.getStage() == EShLangVertex && base->getQualifier().isPipeInput())
+ addAttribute(*base);
+}
+
+// To prune semantically dead paths.
+bool TLiveTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
+{
+ TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
+ if (constant) {
+ // cull the path that is dead
+ if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
+ node->getTrueBlock()->traverse(this);
+ if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
+ node->getFalseBlock()->traverse(this);
+
+ return false; // don't traverse any more, we did it all above
+ } else
+ return true; // traverse the whole subtree
+}
+
+//
+// Implement TReflection methods.
+//
+
+// Merge live symbols from 'intermediate' into the existing reflection database.
+//
+// Returns false if the input is too malformed to do this.
+bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
+{
+ if (intermediate.getNumMains() != 1 || intermediate.isRecursive())
+ return false;
+
+ TLiveTraverser it(intermediate, *this);
+
+ // put main() on functions to process
+ it.pushFunction("main(");
+
+ // process all the functions
+ while (! it.functions.empty()) {
+ TIntermNode* function = it.functions.back();
+ it.functions.pop_back();
+ function->traverse(&it);
+ }
+
+ return true;
+}
+
+void TReflection::dump()
+{
+ printf("Uniform reflection:\n");
+ for (size_t i = 0; i < indexToUniform.size(); ++i)
+ indexToUniform[i].dump();
+ printf("\n");
+
+ printf("Uniform block reflection:\n");
+ for (size_t i = 0; i < indexToUniformBlock.size(); ++i)
+ indexToUniformBlock[i].dump();
+ printf("\n");
+
+ printf("Vertex attribute reflection:\n");
+ for (size_t i = 0; i < indexToAttribute.size(); ++i)
+ indexToAttribute[i].dump();
+ printf("\n");
+
+ //printf("Live names\n");
+ //for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it)
+ // printf("%s: %d\n", it->first.c_str(), it->second);
+ //printf("\n");
+}
+
+} // end namespace glslang
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.h
new file mode 100644
index 00000000000..5d930c7a2a1
--- /dev/null
+++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/reflection.h
@@ -0,0 +1,134 @@
+//
+//Copyright (C) 2013 LunarG, Inc.
+//
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _REFLECTION_INCLUDED
+#define _REFLECTION_INCLUDED
+
+#include "../Public/ShaderLang.h"
+
+#include <list>
+#include <set>
+
+//
+// A reflection database and its interface, consistent with the OpenGL API reflection queries.
+//
+
+namespace glslang {
+
+class TIntermediate;
+class TIntermAggregate;
+class TLiveTraverser;
+
+// Data needed for just a single object at the granularity exchanged by the reflection API
+class TObjectReflection {
+public:
+ TObjectReflection(const TString& pName, int pOffset, int pGLDefineType, int pSize, int pIndex) :
+ name(pName), offset(pOffset), glDefineType(pGLDefineType), size(pSize), index(pIndex) { }
+ void dump() const { printf("%s: offset %d, type %x, size %d, index %d\n", name.c_str(), offset, glDefineType, size, index); }
+ TString name;
+ int offset;
+ int glDefineType;
+ int size; // data size in bytes for a block, array size for a (non-block) object that's an array
+ int index;
+};
+
+// The full reflection database
+class TReflection {
+public:
+ TReflection() : badReflection("__bad__", -1, -1, -1, -1) {}
+ virtual ~TReflection() {}
+
+ // grow the reflection stage by stage
+ bool addStage(EShLanguage, const TIntermediate&);
+
+ // for mapping a uniform index to a uniform object's description
+ int getNumUniforms() { return (int)indexToUniform.size(); }
+ const TObjectReflection& getUniform(int i) const
+ {
+ if (i >= 0 && i < (int)indexToUniform.size())
+ return indexToUniform[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping a block index to the block's description
+ int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); }
+ const TObjectReflection& getUniformBlock(int i) const
+ {
+ if (i >= 0 && i < (int)indexToUniformBlock.size())
+ return indexToUniformBlock[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping an attribute index to the attribute's description
+ int getNumAttributes() { return (int)indexToAttribute.size(); }
+ const TObjectReflection& getAttribute(int i) const
+ {
+ if (i >= 0 && i < (int)indexToAttribute.size())
+ return indexToAttribute[i];
+ else
+ return badReflection;
+ }
+
+ // for mapping any name to its index (block names, uniform names and attribute names)
+ int getIndex(const char* name) const
+ {
+ TNameToIndex::const_iterator it = nameToIndex.find(name);
+ if (it == nameToIndex.end())
+ return -1;
+ else
+ return it->second;
+ }
+
+ void dump();
+
+protected:
+ friend class glslang::TLiveTraverser;
+
+ // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
+ typedef std::map<TString, int> TNameToIndex;
+ typedef std::vector<TObjectReflection> TMapIndexToReflection;
+
+ TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this
+ TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed
+ TMapIndexToReflection indexToUniform;
+ TMapIndexToReflection indexToUniformBlock;
+ TMapIndexToReflection indexToAttribute;
+};
+
+} // end namespace glslang
+
+#endif // _REFLECTION_INCLUDED