From ebeeece6a7c84b468982985a464f12f77b34e155 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Fri, 5 Apr 2013 04:05:39 +0000 Subject: [PATCH] Add uint type (big change). For both int/uint, add the operators >>, <<, &, |, and ^. Also added unsigned literals and uint precision support. Also fixed how int/uint literal underflow/overflow is handled. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21054 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/precision.frag | 6 +- Test/specExamples.frag | 10 +- Test/testlist | 1 + Test/uint.frag | 105 +++++++++++++++ glslang/Include/ConstantUnion.h | 34 ++++- glslang/Include/Types.h | 5 + glslang/Include/intermediate.h | 18 +++ glslang/MachineIndependent/Constant.cpp | 13 +- glslang/MachineIndependent/Intermediate.cpp | 142 +++++++++++++++++--- glslang/MachineIndependent/ParseHelper.cpp | 35 +++-- glslang/MachineIndependent/ParseHelper.h | 4 +- glslang/MachineIndependent/SymbolTable.cpp | 1 + glslang/MachineIndependent/Versions.cpp | 13 ++ glslang/MachineIndependent/glslang.l | 12 +- glslang/MachineIndependent/glslang.y | 137 +++++++++++++------ glslang/MachineIndependent/intermOut.cpp | 39 +++++- 16 files changed, 473 insertions(+), 102 deletions(-) create mode 100644 Test/uint.frag diff --git a/Test/precision.frag b/Test/precision.frag index c9b1d7ab..c4339ae0 100644 --- a/Test/precision.frag +++ b/Test/precision.frag @@ -10,7 +10,11 @@ lowp vec2 foo(mediump vec3 mv3) int global_medium; -precision highp int; +precision highp int; +precision highp ivec2; // ERROR +precision mediump int[2]; // ERROR +precision lowp uint; // ERROR +precision mediump vec4; // ERROR int global_high; diff --git a/Test/specExamples.frag b/Test/specExamples.frag index 1877de13..ffaf994f 100644 --- a/Test/specExamples.frag +++ b/Test/specExamples.frag @@ -3,22 +3,22 @@ #extension GL_3DL_array_objects : enable int a = 0xffffffff; // 32 bits, a gets the value -1 -//int b = 0xffffffffU; // ERROR: can't convert uint to int +int b = 0xffffffffU; // ERROR: can't convert uint to int uint c = 0xffffffff; // 32 bits, c gets the value 0xFFFFFFFF -//uint d = 0xffffffffU; // 32 bits, d gets the value 0xFFFFFFFF +uint d = 0xffffffffU; // 32 bits, d gets the value 0xFFFFFFFF int e = -1; // the literal is "1", then negation is performed, // and the resulting non-literal 32-bit signed // bit pattern of 0xFFFFFFFF is assigned, giving e // the value of -1. -//uint f = -1u; // the literal is "1u", then negation is performed, +uint f = -1u; // the literal is "1u", then negation is performed, // and the resulting non-literal 32-bit unsigned // bit pattern of 0xFFFFFFFF is assigned, giving f // the value of 0xFFFFFFFF. int g = 3000000000; // a signed decimal literal taking 32 bits, // setting the sign bit, g gets -1294967296 int h = 0xA0000000; // okay, 32-bit signed hexadecimal -//int i = 5000000000; // ERROR: needs more than 32 bits -//int j = 0xFFFFFFFFF; // ERROR: needs more that 32 bits +int i = 5000000000; // ERROR: needs more than 32 bits +int j = 0xFFFFFFFFF; // ERROR: needs more that 32 bits int k = 0x80000000; // k gets -2147483648 == 0x80000000 int l = 2147483648; // l gets -2147483648 (the literal set the sign bit) diff --git a/Test/testlist b/Test/testlist index b8ac11e8..b01e2fc2 100644 --- a/Test/testlist +++ b/Test/testlist @@ -29,3 +29,4 @@ constErrors.frag constFold.frag errors.frag forwardRef.frag +uint.frag diff --git a/Test/uint.frag b/Test/uint.frag new file mode 100644 index 00000000..0942a9ec --- /dev/null +++ b/Test/uint.frag @@ -0,0 +1,105 @@ +#version 300 es + +in uvec2 t; +in float f; +in vec2 tc; + +uniform uvec4 v; +uniform int i; +uniform bool b; + +out uvec4 c; + +uniform usampler2D usampler; + +void main() +{ + int count = 1; + + uint u = t.y + 3u; + const uint cu1error = 0xFFFFFFFF; // ERROR + const uint cu1 = 0xFFFFFFFFU; + const uint cu2 = -1u; // 0xFFFFFFFF + const uint cu3 = 1U; + const uint cu4error = 1; // ERROR + const uint cu4 = 1u; + + if (cu1 == cu2) + count *= 2; // done + if (cu3 == cu4) + count *= 3; // done + if (cu2 == cu3) + count *= 5; // not done + + const uint cushiftediierror = 0xFFFFFFFF >> 10; // ERROR + const int cshiftedii = 0xFFFFFFFF >> 10; + const uint cushiftedui = 0xFFFFFFFFu >> 10; + const uint cushiftediuerror = 0xFFFFFFFF >> 10u; // ERROR + const int cshiftediu = 0xFFFFFFFF >> 10u; + const uint cushifteduu = 0xFFFFFFFFu >> 10u; + + if (cshiftedii == cshiftediu) + count *= 7; // done + if (cushiftedui == cushifteduu) + count *= 11; // done + if (cshiftedii == int(cushiftedui)) + count *= 13; // not done + + uint shiftediierror = 0xFFFFFFFF >> 10; // ERROR + int shiftedii = 0xFFFFFFFF >> 10; + uint shiftedui = 0xFFFFFFFFu >> 10; + uint shiftediuerror = 0xFFFFFFFF >> 10u; // ERROR + int shiftediu = 0xFFFFFFFF >> 10u; + uint shifteduu = 0xFFFFFFFFu >> 10u; + + if (shiftedii == shiftediu) + c = texture(usampler, tc); + if (shiftedui == shifteduu) + c = texture(usampler, tc + float(1u)); + if (shiftedii == int(shiftedui)) + c = texture(usampler, tc - vec2(2u)); + + if (t.x > 4u) { + float af = float(u); + bool ab = bool(u); + int ai = int(u); + + c += uvec4(uint(af), uint(ab), uint(ai), count); + } + + const uint cmask1 = 0x0A1u; + const uint cmask2 = 0xA10u; + const uint cmask3 = cmask1 << 4; + const uint cmask4 = 0xAB1u; + + if (cmask3 == cmask2) + count *= 17; // done + + if ((cmask3 & cmask1) != 0u) + count *= 19; // not done + + if ((cmask1 | cmask3) == cmask4) + count *= 23; // done + + if ((cmask1 ^ cmask4) == 0xA10u) + count *= 27; // done + + uint mask1 = 0x0A1u; + uint mask2 = 0xA10u; + uint mask3 = mask1 << 4; + uint mask4 = 0xAB1u; + + if (mask3 == mask2) + count *= 100; + + if ((mask3 & mask1) != 0u) + count *= 101; + + if ((mask1 | mask3) == mask4) + count *= 102; + + if ((mask1 ^ mask4) == 0xA10u) + count *= 103; + + c += uvec4(count); +} diff --git a/glslang/Include/ConstantUnion.h b/glslang/Include/ConstantUnion.h index cd6a88c7..e792c752 100644 --- a/glslang/Include/ConstantUnion.h +++ b/glslang/Include/ConstantUnion.h @@ -285,10 +285,21 @@ public: constUnion operator>>(const constUnion& constant) const { constUnion returnValue; - assert(type == constant.type); switch (type) { - case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; + default: assert(false && "Default missing"); + } + break; default: assert(false && "Default missing"); } @@ -298,10 +309,21 @@ public: constUnion operator<<(const constUnion& constant) const { constUnion returnValue; - assert(type == constant.type); switch (type) { - case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; + default: assert(false && "Default missing"); + } + break; default: assert(false && "Default missing"); } diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 644e6b86..c179d64c 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -269,6 +269,11 @@ public: matrixCols = c; vectorSize = 0; } + + bool isScalar() + { + return matrixCols == 0 && vectorSize == 1 && arraySizes == 0 && userDef == 0; + } }; typedef std::map TStructureMap; diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index d0a4d67c..e8de09a7 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -75,11 +75,25 @@ enum TOperator { EOpPreDecrement, EOpConvIntToBool, + EOpConvUintToBool, EOpConvFloatToBool, + EOpConvDoubleToBool, EOpConvBoolToFloat, EOpConvIntToFloat, + EOpConvUintToFloat, + EOpConvDoubleToFloat, + EOpConvUintToInt, EOpConvFloatToInt, EOpConvBoolToInt, + EOpConvDoubleToInt, + EOpConvIntToUint, + EOpConvFloatToUint, + EOpConvBoolToUint, + EOpConvDoubleToUint, + EOpConvIntToDouble, + EOpConvUintToDouble, + EOpConvFloatToDouble, + EOpConvBoolToDouble, // // binary operations @@ -192,6 +206,7 @@ enum TOperator { EOpConstructGuardStart, EOpConstructInt, + EOpConstructUint, EOpConstructBool, EOpConstructFloat, EOpConstructDouble, @@ -207,6 +222,9 @@ enum TOperator { EOpConstructIVec2, EOpConstructIVec3, EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, EOpConstructMat2x2, EOpConstructMat2x3, EOpConstructMat2x4, diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index 9ea3806e..0b1c9911 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -120,11 +120,6 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod TIntermConstantUnion *node = constantNode->getAsConstantUnion(); constUnion *rightUnionArray = node->getUnionArrayPointer(); - if (getType().getBasicType() != node->getBasicType()) { - infoSink.info.message(EPrefixInternalError, "Constant folding basic types don't match", getLine()); - return 0; - } - if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { // for a case like float f = vec4(2,3,4,5) + 1.2; rightUnionArray = new constUnion[objectSize]; @@ -190,6 +185,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod } else newConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); break; + + case EbtUint: + if (rightUnionArray[i] == 0) { + newConstArray[i].setUConst(0xFFFFFFFF); + } else + newConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst()); + break; default: infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); return 0; @@ -388,6 +390,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType, switch (getType().getBasicType()) { case EbtFloat: newConstArray[i].setFConst(-unionArray[i].getFConst()); break; case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break; + case EbtUint: newConstArray[i].setUConst(static_cast(-static_cast(unionArray[i].getUConst()))); break; default: infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); return 0; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 09bb9586..c9ea0302 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -227,9 +227,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // TBasicType newType = EbtVoid; switch (op) { - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructBool: newType = EbtBool; break; - case EOpConstructFloat: newType = EbtFloat; break; + case EOpConstructInt: newType = EbtInt; break; + case EOpConstructUint: newType = EbtUint; break; + case EOpConstructBool: newType = EbtBool; break; + case EOpConstructFloat: newType = EbtFloat; break; case EOpConstructDouble: newType = EbtDouble; break; default: break; // some compilers want this } @@ -248,6 +249,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // switch (op) { case EOpConstructInt: + case EOpConstructUint: case EOpConstructBool: case EOpConstructFloat: case EOpConstructDouble: @@ -380,6 +382,9 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EOpConstructInt: promoteTo = EbtInt; break; + case EOpConstructUint: + promoteTo = EbtUint; + break; // // List all the binary ops that can implicitly convert one operand to the other's type; @@ -424,6 +429,22 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt 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) && + (node->getType().getBasicType() == EbtInt || + node->getType().getBasicType() == EbtUint)) + + return node; + else + return 0; + default: // default is to require a match; all exceptions should have case statements above @@ -449,37 +470,55 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt switch (promoteTo) { case EbtDouble: //switch (node->getBasicType()) { - //case EbtInt: newOp = EOpConvIntToDouble; break; - //case EbtBool: newOp = EOpConvBoolToDouble; break; - //case EbtFloat: newOp = EOpConvFloatToDouble; break; - //default: + //case EbtInt: newOp = EOpConvIntToDouble; break; + //case EbtUint: newOp = EOpConvUintToDouble; break; + //case EbtBool: newOp = EOpConvBoolToDouble; break; + //case EbtFloat: newOp = EOpConvFloatToDouble; break; + //default: infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); return 0; //} break; case EbtFloat: switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToFloat; break; - case EbtBool: newOp = EOpConvBoolToFloat; break; - default: + case EbtInt: newOp = EOpConvIntToFloat; break; + case EbtUint: newOp = EOpConvUintToFloat; break; + case EbtBool: newOp = EOpConvBoolToFloat; break; + case EbtDouble: newOp = EOpConvDoubleToFloat; break; + default: infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); return 0; } break; case EbtBool: switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToBool; break; - case EbtFloat: newOp = EOpConvFloatToBool; break; - default: + case EbtInt: newOp = EOpConvIntToBool; break; + case EbtUint: newOp = EOpConvUintToBool; break; + case EbtFloat: newOp = EOpConvFloatToBool; break; + case EbtDouble: newOp = EOpConvDoubleToBool; break; + default: infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); return 0; } break; case EbtInt: switch (node->getBasicType()) { + case EbtUint: newOp = EOpConvUintToInt; break; case EbtBool: newOp = EOpConvBoolToInt; break; case EbtFloat: newOp = EOpConvFloatToInt; break; - default: + case EbtDouble: newOp = EOpConvDoubleToInt; break; + default: + infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + 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; + default: infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); return 0; } @@ -978,7 +1017,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) break; // - // And and Or operate on conditionals + // And and Or operate only on conditionals // case EOpLogicalAnd: case EOpLogicalOr: @@ -996,7 +1035,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink) case EOpAnd: case EOpInclusiveOr: case EOpExclusiveOr: - if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt) + if ( left->getBasicType() != EbtInt && left->getBasicType() != EbtUint || + right->getBasicType() != EbtInt && right->getBasicType() != EbtUint) return false; break; case EOpModAssign: @@ -1005,7 +1045,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink) case EOpExclusiveOrAssign: case EOpLeftShiftAssign: case EOpRightShiftAssign: - if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt) + if ( left->getBasicType() != EbtInt && left->getBasicType() != EbtUint || + right->getBasicType() != EbtInt && right->getBasicType() != EbtUint) return false; // fall through @@ -1166,7 +1207,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision) { - if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtFloat)) + if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat)) return; getQualifier().precision = newPrecision; @@ -1228,12 +1269,40 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC case EbtInt: leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getIConst())); break; + case EbtUint: + leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getUConst())); + break; case EbtBool: leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getBConst())); break; case EbtFloat: leftUnionArray[i] = rightUnionArray[i]; break; + case EbtDouble: + leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getBConst())); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtDouble: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getIConst())); + break; + case EbtUint: + leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getUConst())); + break; + case EbtBool: + leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getBConst())); + break; + case EbtFloat: + leftUnionArray[i].setDConst(static_cast(rightUnionArray[i].getFConst())); + break; + case EbtDouble: + leftUnionArray[i] = rightUnionArray[i]; + break; default: infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); return 0; @@ -1244,12 +1313,40 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC case EbtInt: leftUnionArray[i] = rightUnionArray[i]; break; + case EbtUint: + leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getUConst())); + break; case EbtBool: leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getBConst())); break; case EbtFloat: leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getFConst())); break; + case EbtDouble: + leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getDConst())); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtUint: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getIConst())); + break; + case EbtUint: + leftUnionArray[i] = rightUnionArray[i]; + break; + case EbtBool: + leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getBConst())); + break; + case EbtFloat: + leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getFConst())); + break; + case EbtDouble: + leftUnionArray[i].setUConst(static_cast(rightUnionArray[i].getDConst())); + break; default: infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); return 0; @@ -1260,17 +1357,22 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC case EbtInt: leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0); break; + case EbtUint: + leftUnionArray[i].setBConst(rightUnionArray[i].getUConst() != 0); + break; case EbtBool: leftUnionArray[i] = rightUnionArray[i]; break; case EbtFloat: leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f); break; + case EbtDouble: + leftUnionArray[i].setBConst(rightUnionArray[i].getDConst() != 0.0f); + break; default: infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); return 0; - } - + } break; default: infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 93c23c23..f65ff1fd 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -54,12 +54,14 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E switch (language) { case EShLangVertex: defaultPrecision[EbtInt] = EpqHigh; + defaultPrecision[EbtUint] = EpqHigh; defaultPrecision[EbtFloat] = EpqHigh; defaultPrecision[EbtSampler] = EpqLow; // TODO: functionality: need default precisions per sampler type break; case EShLangFragment: defaultPrecision[EbtInt] = EpqMedium; + defaultPrecision[EbtUint] = EpqMedium; defaultPrecision[EbtSampler] = EpqLow; // TODO: give error when using float in frag shader without default precision break; @@ -399,10 +401,10 @@ bool TParseContext::constErrorCheck(TIntermTyped* node) // bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) { - if (node->getBasicType() == EbtInt && node->getVectorSize() == 1) + if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->getVectorSize() == 1 && ! node->isArray()) return false; - error(node->getLine(), "integer expression required", token, ""); + error(node->getLine(), "scalar integer expression required", token, ""); return true; } @@ -728,14 +730,22 @@ bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& left, const return bad; } -void TParseContext::setDefaultPrecision(int line, TBasicType type, TPrecisionQualifier qualifier) +void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrecisionQualifier qualifier) { - if (type == EbtSampler || type == EbtInt || type == EbtFloat) { - defaultPrecision[type] = qualifier; - } else { - error(line, "cannot apply precision statement to this type", TType::getBasicString(type), ""); - recover(); + TBasicType basicType = publicType.type; + + if (basicType == EbtSampler || basicType == EbtInt || basicType == EbtFloat) { + if (publicType.isScalar()) { + defaultPrecision[basicType] = qualifier; + if (basicType == EbtInt) + defaultPrecision[EbtUint] = qualifier; + + return; // all is well + } } + + error(line, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); + recover(); } bool TParseContext::parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type) @@ -800,7 +810,7 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel() bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) { TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant == 0 || constant->getBasicType() != EbtInt) { + if (constant == 0 || (constant->getBasicType() != EbtInt && constant->getBasicType() != EbtUint)) { error(line, "array size must be a constant integer expression", "", ""); size = 1; return true; @@ -1299,6 +1309,13 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T basicOp = EOpConstructInt; break; + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + case EOpConstructUint: + basicOp = EOpConstructUint; + break; + case EOpConstructBVec2: case EOpConstructBVec3: case EOpConstructBVec4: diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 1c80147f..33017912 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -123,7 +123,7 @@ struct TParseContext { bool globalQualifierFixAndErrorCheck(int line, TQualifier&); bool structQualifierErrorCheck(int line, const TPublicType& pType); bool mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right); - void setDefaultPrecision(int line, TBasicType, TPrecisionQualifier); + void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier); bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type); bool containsSampler(const TType& type); bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type); @@ -146,6 +146,8 @@ struct TParseContext { void profileRequires(int line, EProfile callingProfile, int minVersion, const char* extension, const char *featureDesc); void checkDeprecated(int line, EProfile callingProfile, int depVersion, const char *featureDesc); void requireNotRemoved(int line, EProfile callingProfile, int removedVersion, const char *featureDesc); + void fullIntegerCheck(int line, const char* op); + void doubleCheck(int line, const char* op); }; int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&); diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 1a958eb0..d65a5f49 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -59,6 +59,7 @@ void TType::buildMangledName(TString& mangledName) case EbtFloat: mangledName += 'f'; break; case EbtDouble: mangledName += 'd'; break; case EbtInt: mangledName += 'i'; break; + case EbtUint: mangledName += 'u'; break; case EbtBool: mangledName += 'b'; break; case EbtSampler: switch (sampler.type) { diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 0fe65bd7..3ea068a3 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -160,3 +160,16 @@ void TParseContext::requireNotRemoved(int line, EProfile callingProfile, int rem } } } + +void TParseContext::fullIntegerCheck(int line, const char* op) +{ + profileRequires(line, ENoProfile, 130, 0, op); + profileRequires(line, EEsProfile, 300, 0, op); +} + +void TParseContext::doubleCheck(int line, const char* op) +{ + requireProfile(line, (EProfileMask)(ECoreProfileMask | ECompatibilityProfileMask), op); + profileRequires(line, ECoreProfile, 400, 0, op); + profileRequires(line, ECompatibilityProfile, 400, 0, op); +} diff --git a/glslang/MachineIndependent/glslang.l b/glslang/MachineIndependent/glslang.l index 3cf4cc82..0e22616b 100644 --- a/glslang/MachineIndependent/glslang.l +++ b/glslang/MachineIndependent/glslang.l @@ -355,15 +355,15 @@ int yy_input(char* buf, int max_size); return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol); } -0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } -0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return(INTCONSTANT); } +0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return(INTCONSTANT); } 0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;} -{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return(INTCONSTANT); } -0[xX]{H}+{U} { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(UINTCONSTANT); } -0{O}+{U} { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(UINTCONSTANT); } +0[xX]{H}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return(UINTCONSTANT); } +0{O}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return(UINTCONSTANT); } 0{D}+{U} { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;} -{D}+{U} { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(UINTCONSTANT); } +{D}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return(UINTCONSTANT); } {D}+{F} { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } {D}+{E}{F}? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast(atof(yytext)); return(FLOATCONSTANT); } diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 00d098f3..ad1e9c0a 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -82,6 +82,7 @@ extern void yyerror(const char*); TString *string; float f; int i; + unsigned int u; bool b; double d; }; @@ -120,7 +121,7 @@ extern void yyerror(const char*); %token CONST BOOL FLOAT DOUBLE INT UINT %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT SUBROUTINE %token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4 -%token MAT2 MAT3 MAT4 CENTROID IN OUT INOUT +%token MAT2 MAT3 MAT4 CENTROID IN OUT INOUT %token UNIFORM PATCH SAMPLE BUFFER SHARED %token COHERENT VOLATILE RESTRICT READONLY WRITEONLY %token DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4 @@ -146,20 +147,20 @@ extern void yyerror(const char*); %token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS %token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY -%token IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D +%token IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D %token UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D -%token IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT +%token IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT %token IMAGECUBE IIMAGECUBE UIMAGECUBE %token IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER -%token IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY +%token IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY %token IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY %token IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY -%token IMAGE2DMS IIMAGE2DMS UIMAGE2DMS +%token IMAGE2DMS IIMAGE2DMS UIMAGE2DMS %token IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY %token STRUCT VOID WHILE -%token IDENTIFIER TYPE_NAME +%token IDENTIFIER TYPE_NAME %token FLOATCONSTANT DOUBLECONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT %token FIELD_SELECTION %token LEFT_OP RIGHT_OP @@ -254,10 +255,11 @@ primary_expression unionArray->setIConst($1.i); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line); } - | UINTCONSTANT { + | UINTCONSTANT { + parseContext.fullIntegerCheck($1.line, "unsigned literal"); constUnion *unionArray = new constUnion[1]; - unionArray->setIConst($1.i); - $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line); + unionArray->setUConst($1.u); + $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.line); } | FLOATCONSTANT { constUnion *unionArray = new constUnion[1]; @@ -265,6 +267,7 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line); } | DOUBLECONSTANT { + parseContext.doubleCheck($1.line, "double literal"); constUnion *unionArray = new constUnion[1]; unionArray->setDConst($1.d); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtDouble, EvqConst), $1.line); @@ -538,7 +541,7 @@ function_call // if (fnCandidate->getParamCount() == 1) { // - // Treat it like a built-in unary operator. + // Treat it like a built-in unary operator. // addUnaryMath() should get the type correct on its own; // including constness (which would differ from the prototype). // @@ -748,6 +751,15 @@ function_identifier default: break; // some compilers want this } break; + case EbtUint: + switch($1.vectorSize) { + 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 EbtBool: switch($1.vectorSize) { case 1: op = EOpConstructBool; break; @@ -913,6 +925,7 @@ additive_expression shift_expression : additive_expression { $$ = $1; } | shift_expression LEFT_OP additive_expression { + parseContext.fullIntegerCheck($2.line, "bit shift left"); $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line, parseContext.symbolTable); if ($$ == 0) { parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString()); @@ -921,6 +934,7 @@ shift_expression } } | shift_expression RIGHT_OP additive_expression { + parseContext.fullIntegerCheck($2.line, "bit shift right"); $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line, parseContext.symbolTable); if ($$ == 0) { parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString()); @@ -1003,6 +1017,7 @@ equality_expression and_expression : equality_expression { $$ = $1; } | and_expression AMPERSAND equality_expression { + parseContext.fullIntegerCheck($2.line, "bitwise and"); $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line, parseContext.symbolTable); if ($$ == 0) { parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString()); @@ -1015,6 +1030,7 @@ and_expression exclusive_or_expression : and_expression { $$ = $1; } | exclusive_or_expression CARET and_expression { + parseContext.fullIntegerCheck($2.line, "bitwise exclusive or"); $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line, parseContext.symbolTable); if ($$ == 0) { parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString()); @@ -1027,6 +1043,7 @@ exclusive_or_expression inclusive_or_expression : exclusive_or_expression { $$ = $1; } | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { + parseContext.fullIntegerCheck($2.line, "bitwise inclusive or"); $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line, parseContext.symbolTable); if ($$ == 0) { parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString()); @@ -1115,11 +1132,26 @@ assignment_operator | MOD_ASSIGN { $$.line = $1.line; $$.op = EOpModAssign; } | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; } | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; } - | LEFT_ASSIGN { $$.line = $1.line; $$.op = EOpLeftShiftAssign; } - | RIGHT_ASSIGN { $$.line = $1.line; $$.op = EOpRightShiftAssign; } - | AND_ASSIGN { $$.line = $1.line; $$.op = EOpAndAssign; } - | XOR_ASSIGN { $$.line = $1.line; $$.op = EOpExclusiveOrAssign; } - | OR_ASSIGN { $$.line = $1.line; $$.op = EOpInclusiveOrAssign; } + | LEFT_ASSIGN { + parseContext.fullIntegerCheck($1.line, "bit-shift left assign"); + $$.line = $1.line; $$.op = EOpLeftShiftAssign; + } + | RIGHT_ASSIGN { + parseContext.fullIntegerCheck($1.line, "bit-shift right assign"); + $$.line = $1.line; $$.op = EOpRightShiftAssign; + } + | AND_ASSIGN { + parseContext.fullIntegerCheck($1.line, "bitwise-and assign"); + $$.line = $1.line; $$.op = EOpAndAssign; + } + | XOR_ASSIGN { + parseContext.fullIntegerCheck($1.line, "bitwise-xor assign"); + $$.line = $1.line; $$.op = EOpExclusiveOrAssign; + } + | OR_ASSIGN { + parseContext.fullIntegerCheck($1.line, "bitwise-or assign"); + $$.line = $1.line; $$.op = EOpInclusiveOrAssign; + } ; expression @@ -1156,11 +1188,11 @@ declaration } | PRECISION precision_qualifier type_specifier SEMICOLON { parseContext.profileRequires($1.line, ENoProfile, 130, 0, "precision statement"); - + // lazy setting of the previous scope's defaults, only takes on first one in a particular scope parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); - parseContext.setDefaultPrecision($1.line, $3.type, $2.qualifier.precision); + parseContext.setDefaultPrecision($1.line, $3, $2.qualifier.precision); $$ = 0; } | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON { @@ -1217,7 +1249,7 @@ function_prototype } for (int i = 0; i < prevDec->getParamCount(); ++i) { if ((*prevDec)[i].type->getQualifier().storage != (*$1)[i].type->getQualifier().storage) { - parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", + parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getStorageQualifierString(), ""); parseContext.recover(); } @@ -1278,7 +1310,7 @@ function_header_with_parameters function_header : fully_specified_type IDENTIFIER LEFT_PAREN { if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) { - parseContext.error($2.line, "no qualifiers allowed for function return", + parseContext.error($2.line, "no qualifiers allowed for function return", getStorageQualifierString($1.qualifier.storage), ""); parseContext.recover(); } @@ -1307,7 +1339,7 @@ parameter_declarator } if (parseContext.reservedErrorCheck($2.line, *$2.string)) parseContext.recover(); - + TParameter param = {$2.string, new TType($1)}; $$.line = $2.line; $$.param = param; @@ -1361,7 +1393,7 @@ parameter_declaration $$ = $2; if ($1.qualifier.precision != EpqNone) $$.param.type->getQualifier().precision = $1.qualifier.precision; - + if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type)) parseContext.recover(); if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type)) @@ -1595,12 +1627,12 @@ fully_specified_type } if ($1.qualifier.storage == EvqAttribute && - ($2.type == EbtBool || $2.type == EbtInt)) { + ($2.type == EbtBool || $2.type == EbtInt || $2.type == EbtUint)) { parseContext.error($2.line, "cannot be bool or int", getStorageQualifierString($1.qualifier.storage), ""); parseContext.recover(); } if (($1.qualifier.storage == EvqVaryingIn || $1.qualifier.storage == EvqVaryingOut) && - ($2.type == EbtBool || $2.type == EbtInt)) { + ($2.type == EbtBool || $2.type == EbtInt || $2.type == EbtUint)) { parseContext.error($2.line, "cannot be bool or int", getStorageQualifierString($1.qualifier.storage), ""); parseContext.recover(); } @@ -1734,12 +1766,12 @@ storage_qualifier parseContext.checkDeprecated($1.line, ECoreProfile, 150, "varying"); parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "varying"); parseContext.requireNotRemoved($1.line, EEsProfile, 300, "varying"); - + if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying")) parseContext.recover(); $$.init($1.line); - if (parseContext.language == EShLangVertex) + if (parseContext.language == EShLangVertex) $$.qualifier.storage = EvqVaryingOut; else $$.qualifier.storage = EvqVaryingIn; @@ -1792,7 +1824,7 @@ storage_qualifier if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "buffer")) parseContext.recover(); $$.init($1.line); - $$.qualifier.storage = EvqUniform; + $$.qualifier.storage = EvqUniform; $$.qualifier.buffer = true; } | SHARED { @@ -1896,6 +1928,7 @@ type_specifier_nonarray $$.type = EbtFloat; } | DOUBLE { + parseContext.doubleCheck($1.line, "double"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; } @@ -1904,9 +1937,9 @@ type_specifier_nonarray $$.type = EbtInt; } | UINT { - // TODO: implement EbtUint, check all int types + parseContext.fullIntegerCheck($1.line, "unsigned integer"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); - $$.type = EbtInt; + $$.type = EbtUint; } | BOOL { $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); @@ -1928,16 +1961,19 @@ type_specifier_nonarray $$.setVector(4); } | DVEC2 { + parseContext.doubleCheck($1.line, "double vector"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setVector(2); } | DVEC3 { + parseContext.doubleCheck($1.line, "double vector"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setVector(3); } | DVEC4 { + parseContext.doubleCheck($1.line, "double vector"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setVector(4); @@ -1973,18 +2009,21 @@ type_specifier_nonarray $$.setVector(4); } | UVEC2 { + parseContext.fullIntegerCheck($1.line, "unsigned integer vector"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); - $$.type = EbtInt; + $$.type = EbtUint; $$.setVector(2); } | UVEC3 { + parseContext.fullIntegerCheck($1.line, "unsigned integer vector"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); - $$.type = EbtInt; + $$.type = EbtUint; $$.setVector(3); } | UVEC4 { + parseContext.fullIntegerCheck($1.line, "unsigned integer vector"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); - $$.type = EbtInt; + $$.type = EbtUint; $$.setVector(4); } | MAT2 { @@ -2048,61 +2087,73 @@ type_specifier_nonarray $$.setMatrix(4, 4); } | DMAT2 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(2, 2); } | DMAT3 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(3, 3); } | DMAT4 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(4, 4); } | DMAT2X2 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(2, 2); } | DMAT2X3 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(2, 3); } | DMAT2X4 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(2, 4); } | DMAT3X2 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(3, 2); } | DMAT3X3 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(3, 3); } | DMAT3X4 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(3, 4); } | DMAT4X2 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(4, 2); } | DMAT4X3 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(4, 3); } | DMAT4X4 { + parseContext.doubleCheck($1.line, "double matrix"); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtDouble; $$.setMatrix(4, 4); @@ -2494,7 +2545,7 @@ type_specifier_nonarray // This is for user defined type names. The lexical phase looked up the // type. // - if (TVariable* variable = ($1.symbol)->getAsVariable()) { + if (TVariable* variable = ($1.symbol)->getAsVariable()) { const TType& structure = variable->getType(); $$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.type = EbtStruct; @@ -2642,10 +2693,10 @@ initializer : assignment_expression { $$ = $1; } - | LEFT_BRACE initializer_list RIGHT_BRACE { + | LEFT_BRACE initializer_list RIGHT_BRACE { $$ = $2; } - | LEFT_BRACE initializer_list COMMA RIGHT_BRACE { + | LEFT_BRACE initializer_list COMMA RIGHT_BRACE { $$ = $2; } ; @@ -2683,8 +2734,8 @@ simple_statement compound_statement : LEFT_BRACE RIGHT_BRACE { $$ = 0; } - | LEFT_BRACE { parseContext.symbolTable.push(); } - statement_list { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); } + | LEFT_BRACE { parseContext.symbolTable.push(); } + statement_list { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); } RIGHT_BRACE { if ($3 != 0) $3->setOperator(EOpSequence); @@ -2790,9 +2841,9 @@ case_label ; iteration_statement - : WHILE LEFT_PAREN { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; + : WHILE LEFT_PAREN { + parseContext.symbolTable.push(); + ++parseContext.loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); @@ -2806,10 +2857,10 @@ iteration_statement $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line); --parseContext.loopNestingLevel; } - | FOR LEFT_PAREN { + | FOR LEFT_PAREN { parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - } + ++parseContext.loopNestingLevel; + } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); $$ = parseContext.intermediate.makeAggregate($4, $2.line); @@ -2941,7 +2992,7 @@ function_definition // Remember the return type for later checking for RETURN statements. // parseContext.currentFunctionType = &(prevDec->getReturnType()); - } else + } else parseContext.currentFunctionType = new TType(EbtVoid); parseContext.functionReturnsValue = false; diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index b7b81095..9a769a1f 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -176,12 +176,26 @@ bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it) case EOpPreIncrement: out.debug << "Pre-Increment"; break; case EOpPreDecrement: out.debug << "Pre-Decrement"; break; - case EOpConvIntToBool: out.debug << "Convert int to bool"; break; - case EOpConvFloatToBool:out.debug << "Convert float to bool";break; - case EOpConvBoolToFloat:out.debug << "Convert bool to float";break; - case EOpConvIntToFloat: out.debug << "Convert int to float"; break; - case EOpConvFloatToInt: out.debug << "Convert float to int"; break; - case EOpConvBoolToInt: out.debug << "Convert bool to int"; 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 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 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 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 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 EOpRadians: out.debug << "radians"; break; case EOpDegrees: out.debug << "degrees"; break; @@ -258,6 +272,10 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers 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 EOpConstructMat2x2: out.debug << "Construct mat2"; break; case EOpConstructMat2x3: out.debug << "Construct mat2x3"; break; case EOpConstructMat2x4: out.debug << "Construct mat2x4"; break; @@ -398,6 +416,15 @@ void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it) out.debug << buf << "\n"; } break; + case EbtUint: + { + const int maxSize = 300; + char buf[maxSize]; + snprintf(buf, maxSize, "%u (%s)", node->getUnionArrayPointer()[i].getUConst(), "const uint"); + + out.debug << buf << "\n"; + } + break; default: out.info.message(EPrefixInternalError, "Unknown constant", node->getLine()); break;