diff options
author | John Kessenich <cepheus@frii.com> | 2013-11-08 07:13:18 +0000 |
---|---|---|
committer | John Kessenich <cepheus@frii.com> | 2013-11-08 07:13:18 +0000 |
commit | 01c22afa37a0d1bfff6d56742f0c06e5eb82e449 (patch) | |
tree | 6028b51c609d93622659630cd98987838efcbfc4 /glslang/MachineIndependent/ParseHelper.cpp | |
parent | c999ba281610ae75b30c8185d1137140a6c03e62 (diff) | |
download | glslang-01c22afa37a0d1bfff6d56742f0c06e5eb82e449.tar.gz |
Add some missing invariant semantic checks, replace some misplaced sampler semantic checks, add parameter and structure member checks against new qualifiers.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23962 e7fa87d3-cd2b-0410-9028-fcbf551c1848
Diffstat (limited to 'glslang/MachineIndependent/ParseHelper.cpp')
-rw-r--r-- | glslang/MachineIndependent/ParseHelper.cpp | 120 |
1 files changed, 85 insertions, 35 deletions
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index d21d95dd..565abba2 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -415,7 +415,7 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt TType* type; if (variable->isReadOnly()) { type = new TType; - // break sharing with built-ins + // break type sharing with built-ins type->deepCopy(variable->getType()); // track use of unredeclared gl_FragCoord @@ -477,7 +477,7 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable"); if (base->getBasicType() == EbtBlock) requireProfile(base->getLoc(), ~EEsProfile, "variable indexing block array"); - else if (language == EShLangFragment && base->getQualifier().storage == EvqVaryingOut) + else if (language == EShLangFragment && base->getQualifier().isPipeOutput()) requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader ouput array"); else if (base->getBasicType() == EbtSampler && version >= 130) { const char* explanation = "variable indexing sampler array"; @@ -720,7 +720,7 @@ TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& fu const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; if (prevDec) { if (prevDec->getType() != function.getType()) { - error(loc, "overloaded functions must have the same return type", function.getType().getCompleteTypeString().c_str(), ""); + error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), ""); } for (int i = 0; i < prevDec->getParamCount(); ++i) { if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage) @@ -783,7 +783,7 @@ TIntermAggregate* TParseContext::handleFunctionPrototype(TSourceLoc loc, TFuncti if (function.getParamCount() > 0) error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); if (function.getType().getBasicType() != EbtVoid) - error(loc, "", function.getType().getCompleteTypeString().c_str(), "main function cannot return a value"); + error(loc, "", function.getType().getBasicTypeString().c_str(), "main function cannot return a value"); intermediate.addMainCount(); } @@ -1495,23 +1495,15 @@ void TParseContext::boolCheck(TSourceLoc loc, const TPublicType& pType) error(loc, "boolean expression expected", "", ""); } -bool TParseContext::samplerErrorCheck(TSourceLoc loc, const TPublicType& pType, const char* reason) +void TParseContext::samplerCheck(TSourceLoc loc, const TType& type, const TString& identifier) { - if (pType.basicType == EbtStruct) { - if (containsSampler(*pType.userDef)) { - error(loc, reason, TType::getBasicString(pType.basicType), "(structure cannot contain a sampler or image)"); - - return true; - } - - return false; - } else if (pType.basicType == EbtSampler) { - error(loc, reason, TType::getBasicString(pType.basicType), ""); - - return true; - } + if (type.getQualifier().storage == EvqUniform) + return; - return false; + if (type.getBasicType() == EbtStruct && containsSampler(type)) + error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str()); + else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) + error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); } // @@ -1544,11 +1536,6 @@ void TParseContext::globalQualifierCheck(TSourceLoc loc, const TQualifier& quali if (! symbolTable.atGlobalLevel()) return; - // Do non-in/out error checks - - if (qualifier.storage != EvqUniform && samplerErrorCheck(loc, publicType, "samplers and images must be uniform")) - return; - if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) return; @@ -1738,7 +1725,7 @@ void TParseContext::precisionQualifierCheck(TSourceLoc loc, TPublicType& publicT void TParseContext::parameterSamplerCheck(TSourceLoc loc, TStorageQualifier qualifier, const TType& type) { if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && type.getBasicType() == EbtSampler) - error(loc, "samplers cannot be output parameters", type.getCompleteTypeString().c_str(), ""); + error(loc, "samplers cannot be output parameters", type.getBasicTypeString().c_str(), ""); } bool TParseContext::containsSampler(const TType& type) @@ -2147,28 +2134,41 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c return true; } -void TParseContext::paramCheck(TSourceLoc loc, const TStorageQualifier& qualifier, TType* type) +void TParseContext::paramCheckFix(TSourceLoc loc, const TStorageQualifier& qualifier, TType& type) { switch (qualifier) { case EvqConst: case EvqConstReadOnly: - type->getQualifier().storage = EvqConstReadOnly; + type.getQualifier().storage = EvqConstReadOnly; break; case EvqIn: case EvqOut: case EvqInOut: - type->getQualifier().storage = qualifier; + type.getQualifier().storage = qualifier; break; case EvqTemporary: - type->getQualifier().storage = EvqIn; + type.getQualifier().storage = EvqIn; break; default: - type->getQualifier().storage = EvqIn; - error(loc, "qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), ""); + type.getQualifier().storage = EvqIn; + error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), ""); break; } } +void TParseContext::paramCheckFix(TSourceLoc loc, const TQualifier& qualifier, TType& type) +{ + if (qualifier.isAuxiliary() || + qualifier.isInterpolation()) + error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", ""); + if (qualifier.hasLayout()) + error(loc, "cannot use layout qualifiers on a function parameter", "", ""); + if (qualifier.invariant) + error(loc, "cannot use invariant qualifier on a function parameter", "", ""); + + paramCheckFix(loc, qualifier.storage, type); +} + void TParseContext::nestedBlockCheck(TSourceLoc loc) { if (structNestingLevel > 0) @@ -2192,6 +2192,33 @@ void TParseContext::arrayObjectCheck(TSourceLoc loc, const TType& type, const ch } } +void TParseContext::opaqueCheck(TSourceLoc loc, const TType& type, const char* op) +{ + if (containsSampler(type)) + error(loc, "can't use with samplers or structs containing samplers", op, ""); +} + +void TParseContext::structTypeCheck(TSourceLoc loc, TPublicType& publicType) +{ + TTypeList& typeList = *publicType.userDef->getStruct(); + + // fix and check for member storage qualifiers and types that don't belong within a structure + for (unsigned int member = 0; member < typeList.size(); ++member) { + TQualifier& memberQualifier = typeList[member].type->getQualifier(); + TSourceLoc memberLoc = typeList[member].loc; + if (memberQualifier.isAuxiliary() || + memberQualifier.isInterpolation() || + (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal)) + error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); + if (memberQualifier.isMemory()) + error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); + if (memberQualifier.hasLayout()) + error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); + if (memberQualifier.invariant) + error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), ""); + } +} + // // See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: // @@ -2738,6 +2765,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, if (! initializer) nonInitConstCheck(loc, identifier, type); + invariantCheck(loc, type, identifier); + samplerCheck(loc, type, identifier); + // Pick up defaults if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut) type.getQualifier().layoutStream = globalOutputDefaults.layoutStream; @@ -2775,6 +2805,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); } + if (! symbol) + return 0; + // Deal with initializer TIntermNode* initNode = 0; if (symbol && initializer) { @@ -2787,11 +2820,10 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, } // look for errors/adjustments in layout qualifier use - if (symbol) - layoutTypeCheck(loc, *symbol); + layoutTypeCheck(loc, *symbol); // see if it's a linker-level object to track - if (symbol && newDeclaration && symbolTable.atGlobalLevel()) + if (newDeclaration && symbolTable.atGlobalLevel()) intermediate.addSymbolLinkageNode(linkage, *symbol); return initNode; @@ -3339,8 +3371,10 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, if (symbol->isReadOnly()) symbol = symbolTable.copyUp(symbol); - if (qualifier.invariant) + if (qualifier.invariant) { symbol->getWritableType().getQualifier().invariant = true; + invariantCheck(loc, symbol->getType(), identifier); + } } void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, TIdentifierList& identifiers) @@ -3349,6 +3383,22 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, addQualifierToExisting(loc, qualifier, *identifiers[i]); } +void TParseContext::invariantCheck(TSourceLoc loc, const TType& type, const TString& identifier) +{ + if (! type.getQualifier().invariant) + return; + + bool pipeOut = type.getQualifier().isPipeOutput(); + bool pipeIn = type.getQualifier().isPipeInput(); + if (version >= 300 || profile != EEsProfile && version >= 420) { + if (! pipeOut) + error(loc, "can only apply to an output\n", "invariant", identifier.c_str()); + } else { + if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn)) + error(loc, "can only apply to an output or an input in a non-vertex stage\n", "invariant", ""); + } +} + // // Updating default qualifier for the case of a declaration with just a qualifier, // no type, block, or identifier. |