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
This commit is contained in:
John Kessenich 2013-04-05 04:05:39 +00:00
parent ae722a6230
commit ebeeece6a7
16 changed files with 473 additions and 102 deletions

View File

@ -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;

View File

@ -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)

View File

@ -29,3 +29,4 @@ constErrors.frag
constFold.frag
errors.frag
forwardRef.frag
uint.frag

105
Test/uint.frag Normal file
View File

@ -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);
}

View File

@ -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");
}

View File

@ -269,6 +269,11 @@ public:
matrixCols = c;
vectorSize = 0;
}
bool isScalar()
{
return matrixCols == 0 && vectorSize == 1 && arraySizes == 0 && userDef == 0;
}
};
typedef std::map<TTypeList*, TTypeList*> TStructureMap;

View File

@ -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,

View File

@ -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<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
return 0;

View File

@ -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<float>(rightUnionArray[i].getIConst()));
break;
case EbtUint:
leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getUConst()));
break;
case EbtBool:
leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
break;
case EbtFloat:
leftUnionArray[i] = rightUnionArray[i];
break;
case EbtDouble:
leftUnionArray[i].setFConst(static_cast<float>(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<float>(rightUnionArray[i].getIConst()));
break;
case EbtUint:
leftUnionArray[i].setDConst(static_cast<float>(rightUnionArray[i].getUConst()));
break;
case EbtBool:
leftUnionArray[i].setDConst(static_cast<float>(rightUnionArray[i].getBConst()));
break;
case EbtFloat:
leftUnionArray[i].setDConst(static_cast<float>(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<int>(rightUnionArray[i].getUConst()));
break;
case EbtBool:
leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
break;
case EbtFloat:
leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
break;
case EbtDouble:
leftUnionArray[i].setIConst(static_cast<int>(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<unsigned int>(rightUnionArray[i].getIConst()));
break;
case EbtUint:
leftUnionArray[i] = rightUnionArray[i];
break;
case EbtBool:
leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getBConst()));
break;
case EbtFloat:
leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getFConst()));
break;
case EbtDouble:
leftUnionArray[i].setUConst(static_cast<unsigned int>(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());

View File

@ -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:

View File

@ -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&);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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<float>(atof(yytext)); return(FLOATCONSTANT); }
{D}+{E}{F}? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }

View File

@ -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 <lex> CONST BOOL FLOAT DOUBLE INT UINT
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT SUBROUTINE
%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4
%token <lex> MAT2 MAT3 MAT4 CENTROID IN OUT INOUT
%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
@ -146,20 +147,20 @@ extern void yyerror(const char*);
%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
%token <lex> SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
%token <lex> IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D
%token <lex> IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D
%token <lex> UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D
%token <lex> IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT
%token <lex> IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT
%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
%token <lex> IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
%token <lex> IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY
%token <lex> IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY
%token <lex> IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
%token <lex> IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY
%token <lex> IMAGE2DMS IIMAGE2DMS UIMAGE2DMS
%token <lex> IMAGE2DMS IIMAGE2DMS UIMAGE2DMS
%token <lex> IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY
%token <lex> STRUCT VOID WHILE
%token <lex> IDENTIFIER TYPE_NAME
%token <lex> IDENTIFIER TYPE_NAME
%token <lex> FLOATCONSTANT DOUBLECONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
%token <lex> FIELD_SELECTION
%token <lex> 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;

View File

@ -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;