Commit 613b959d by Olli Etuaho Committed by Commit Bot

Clean up qualification order checks

Move determining whether qualification order checks are relaxed to QualifierTypes.cpp. The ParseContext only needs to construct TTypeQualifierBuilder with the shader version as a parameter, and it will make the decision based on that. ParseContext still passes diagnostics to the TTypeQualifierBuilder functions that return variable qualification to make it more explicit when errors are generated. Also encapsulate looking for symbols in the AST inside compiler_test.cpp. BUG=angleproject:1442 TEST=angle_unittests Change-Id: I4190e6a680ace0cc0568a517e86353a95cc63c08 Reviewed-on: https://chromium-review.googlesource.com/380556 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent b6b1a4a6
...@@ -16,17 +16,6 @@ ...@@ -16,17 +16,6 @@
#include "compiler/translator/ValidateGlobalInitializer.h" #include "compiler/translator/ValidateGlobalInitializer.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace
{
// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout
// declarations
// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification
bool AreTypeQualifierChecksRelaxed(int shaderVersion)
{
return shaderVersion >= 310;
}
} // namespace
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// Sub- vector and matrix fields // Sub- vector and matrix fields
...@@ -945,8 +934,7 @@ void TParseContext::checkIsParameterQualifierValid( ...@@ -945,8 +934,7 @@ void TParseContext::checkIsParameterQualifierValid(
const TTypeQualifierBuilder &typeQualifierBuilder, const TTypeQualifierBuilder &typeQualifierBuilder,
TType *type) TType *type)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier( TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(&mDiagnostics);
&mDiagnostics, AreTypeQualifierChecksRelaxed(mShaderVersion));
if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut) if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
{ {
...@@ -1414,8 +1402,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, ...@@ -1414,8 +1402,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
const TPublicType &typeSpecifier) const TPublicType &typeSpecifier)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier( TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
&mDiagnostics, AreTypeQualifierChecksRelaxed(mShaderVersion));
TPublicType returnType = typeSpecifier; TPublicType returnType = typeSpecifier;
returnType.qualifier = typeQualifier.qualifier; returnType.qualifier = typeQualifier.qualifier;
...@@ -1717,8 +1704,7 @@ TIntermAggregate *TParseContext::parseInvariantDeclaration( ...@@ -1717,8 +1704,7 @@ TIntermAggregate *TParseContext::parseInvariantDeclaration(
const TString *identifier, const TString *identifier,
const TSymbol *symbol) const TSymbol *symbol)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier( TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
&mDiagnostics, AreTypeQualifierChecksRelaxed(mShaderVersion));
if (!typeQualifier.invariant) if (!typeQualifier.invariant)
{ {
...@@ -1926,8 +1912,7 @@ TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &pub ...@@ -1926,8 +1912,7 @@ TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &pub
void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier( TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
&mDiagnostics, AreTypeQualifierChecksRelaxed(mShaderVersion));
const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier, checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
...@@ -2507,8 +2492,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock( ...@@ -2507,8 +2492,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(
{ {
checkIsNotReserved(nameLine, blockName); checkIsNotReserved(nameLine, blockName);
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier( TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
&mDiagnostics, AreTypeQualifierChecksRelaxed(mShaderVersion));
if (typeQualifier.qualifier != EvqUniform) if (typeQualifier.qualifier != EvqUniform)
{ {
...@@ -3191,6 +3175,13 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp ...@@ -3191,6 +3175,13 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp
return qualifier; return qualifier;
} }
TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
{
return new TTypeQualifierBuilder(
new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
mShaderVersion);
}
TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
TLayoutQualifier rightQualifier, TLayoutQualifier rightQualifier,
const TSourceLoc &rightQualifierLocation) const TSourceLoc &rightQualifierLocation)
...@@ -3204,8 +3195,7 @@ TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( ...@@ -3204,8 +3195,7 @@ TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
TPublicType *typeSpecifier, TPublicType *typeSpecifier,
TFieldList *fieldList) TFieldList *fieldList)
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier( TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics);
&mDiagnostics, AreTypeQualifierChecksRelaxed(mShaderVersion));
typeSpecifier->qualifier = typeQualifier.qualifier; typeSpecifier->qualifier = typeQualifier.qualifier;
typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
......
...@@ -327,6 +327,7 @@ class TParseContext : angle::NonCopyable ...@@ -327,6 +327,7 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &qualifierTypeLine, const TSourceLoc &qualifierTypeLine,
int intValue, int intValue,
const TSourceLoc &intValueLine); const TSourceLoc &intValueLine);
TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc);
TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier,
TLayoutQualifier rightQualifier, TLayoutQualifier rightQualifier,
const TSourceLoc &rightQualifierLocation); const TSourceLoc &rightQualifierLocation);
......
...@@ -54,6 +54,14 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, ...@@ -54,6 +54,14 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
namespace namespace
{ {
// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout
// declarations.
// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification
bool AreTypeQualifierChecksRelaxed(int shaderVersion)
{
return shaderVersion >= 310;
}
#if defined(ANGLE_ENABLE_ASSERTS) #if defined(ANGLE_ENABLE_ASSERTS)
bool IsScopeQualifier(TQualifier qualifier) bool IsScopeQualifier(TQualifier qualifier)
{ {
...@@ -525,7 +533,9 @@ TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) ...@@ -525,7 +533,9 @@ TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
ASSERT(IsScopeQualifier(qualifier)); ASSERT(IsScopeQualifier(qualifier));
} }
TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope) TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope,
int shaderVersion)
: mShaderVersion(shaderVersion)
{ {
ASSERT(IsScopeQualifier(scope->getQualifier())); ASSERT(IsScopeQualifier(scope->getQualifier()));
mQualifiers.push_back(scope); mQualifiers.push_back(scope);
...@@ -536,9 +546,9 @@ void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifi ...@@ -536,9 +546,9 @@ void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifi
mQualifiers.push_back(qualifier); mQualifiers.push_back(qualifier);
} }
bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics, bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const
bool areQualifierChecksRelaxed) const
{ {
bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion);
std::string errorMessage; std::string errorMessage;
if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage)) if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage))
{ {
...@@ -557,15 +567,13 @@ bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics, ...@@ -557,15 +567,13 @@ bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics,
return true; return true;
} }
TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier( TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const
TDiagnostics *diagnostics,
bool areQualifierChecksRelaxed) const
{ {
ASSERT(IsInvariantCorrect(mQualifiers)); ASSERT(IsInvariantCorrect(mQualifiers));
ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() == ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() ==
EvqTemporary); EvqTemporary);
if (!checkSequenceIsValid(diagnostics, areQualifierChecksRelaxed)) if (!checkSequenceIsValid(diagnostics))
{ {
return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine()); return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine());
} }
...@@ -573,7 +581,7 @@ TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier( ...@@ -573,7 +581,7 @@ TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(
// If the qualifier checks are relaxed, then it is easier to sort the qualifiers so // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
// that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
// combine the qualifiers. // combine the qualifiers.
if (areQualifierChecksRelaxed) if (AreTypeQualifierChecksRelaxed(mShaderVersion))
{ {
// Copy the qualifier sequence so that we can sort them. // Copy the qualifier sequence so that we can sort them.
QualifierSequence sortedQualifierSequence = mQualifiers; QualifierSequence sortedQualifierSequence = mQualifiers;
...@@ -583,12 +591,11 @@ TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier( ...@@ -583,12 +591,11 @@ TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(
return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics); return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
} }
TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics, TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const
bool areQualifierChecksRelaxed) const
{ {
ASSERT(IsInvariantCorrect(mQualifiers)); ASSERT(IsInvariantCorrect(mQualifiers));
if (!checkSequenceIsValid(diagnostics, areQualifierChecksRelaxed)) if (!checkSequenceIsValid(diagnostics))
{ {
return TTypeQualifier( return TTypeQualifier(
static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(), static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(),
...@@ -598,7 +605,7 @@ TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *dia ...@@ -598,7 +605,7 @@ TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *dia
// If the qualifier checks are relaxed, then it is easier to sort the qualifiers so // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
// that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
// combine the qualifiers. // combine the qualifiers.
if (areQualifierChecksRelaxed) if (AreTypeQualifierChecksRelaxed(mShaderVersion))
{ {
// Copy the qualifier sequence so that we can sort them. // Copy the qualifier sequence so that we can sort them.
QualifierSequence sortedQualifierSequence = mQualifiers; QualifierSequence sortedQualifierSequence = mQualifiers;
......
...@@ -150,23 +150,22 @@ class TTypeQualifierBuilder : angle::NonCopyable ...@@ -150,23 +150,22 @@ class TTypeQualifierBuilder : angle::NonCopyable
using QualifierSequence = std::vector<const TQualifierWrapperBase *>; using QualifierSequence = std::vector<const TQualifierWrapperBase *>;
public: public:
TTypeQualifierBuilder(const TStorageQualifierWrapper *scope); TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion);
// Adds the passed qualifier to the end of the sequence. // Adds the passed qualifier to the end of the sequence.
void appendQualifier(const TQualifierWrapperBase *qualifier); void appendQualifier(const TQualifierWrapperBase *qualifier);
// Checks for the order of qualification and repeating qualifiers. // Checks for the order of qualification and repeating qualifiers.
bool checkSequenceIsValid(TDiagnostics *diagnostics, bool areQualifierChecksRelaxed) const; bool checkSequenceIsValid(TDiagnostics *diagnostics) const;
// Goes over the qualifier sequence and parses it to form a type qualifier for a function // Goes over the qualifier sequence and parses it to form a type qualifier for a function
// parameter. // parameter.
// The returned object is initialized even if the parsing fails. // The returned object is initialized even if the parsing fails.
TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics, TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const;
bool areQualifierChecksRelaxed) const;
// Goes over the qualifier sequence and parses it to form a type qualifier for a variable. // Goes over the qualifier sequence and parses it to form a type qualifier for a variable.
// The returned object is initialized even if the parsing fails. // The returned object is initialized even if the parsing fails.
TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics, TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const;
bool areQualifierChecksRelaxed) const;
private: private:
QualifierSequence mQualifiers; QualifierSequence mQualifiers;
int mShaderVersion;
}; };
#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ #endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
...@@ -836,7 +836,7 @@ interpolation_qualifier ...@@ -836,7 +836,7 @@ interpolation_qualifier
type_qualifier type_qualifier
: single_type_qualifier { : single_type_qualifier {
$$ = new TTypeQualifierBuilder(new TStorageQualifierWrapper(context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, @1)); $$ = context->createTypeQualifierBuilder(@1);
$$->appendQualifier($1); $$->appendQualifier($1);
} }
| type_qualifier single_type_qualifier { | type_qualifier single_type_qualifier {
......
...@@ -3414,7 +3414,7 @@ yyreduce: ...@@ -3414,7 +3414,7 @@ yyreduce:
case 125: case 125:
{ {
(yyval.interm.typeQualifierBuilder) = new TTypeQualifierBuilder(new TStorageQualifierWrapper(context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, (yylsp[0]))); (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0]));
(yyval.interm.typeQualifierBuilder)->appendQualifier((yyvsp[0].interm.qualifierWrapper)); (yyval.interm.typeQualifierBuilder)->appendQualifier((yyvsp[0].interm.qualifierWrapper));
} }
......
...@@ -41,11 +41,9 @@ class QualificationVertexShaderTestESSL31 : public testing::Test ...@@ -41,11 +41,9 @@ class QualificationVertexShaderTestESSL31 : public testing::Test
return mASTRoot != nullptr; return mASTRoot != nullptr;
} }
const TIntermSymbol *findSymbolInAST(const TString &stringToFind, TBasicType basicType) const TIntermSymbol *findSymbolInAST(const TString &symbolName, TBasicType basicType)
{ {
ShaderVariableFinder finder(stringToFind, basicType); return FindSymbolNode(mASTRoot, symbolName, basicType);
mASTRoot->traverse(&finder);
return finder.getNode();
} }
protected: protected:
......
...@@ -11,6 +11,39 @@ ...@@ -11,6 +11,39 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/Compiler.h" #include "compiler/translator/Compiler.h"
namespace
{
class ShaderVariableFinder : public TIntermTraverser
{
public:
ShaderVariableFinder(const TString &variableName, TBasicType basicType)
: TIntermTraverser(true, false, false),
mVariableName(variableName),
mNodeFound(nullptr),
mBasicType(basicType)
{
}
void visitSymbol(TIntermSymbol *node)
{
if (node->getBasicType() == mBasicType && node->getSymbol() == mVariableName)
{
mNodeFound = node;
}
}
bool isFound() const { return mNodeFound != nullptr; }
const TIntermSymbol *getNode() const { return mNodeFound; }
private:
TString mVariableName;
TIntermSymbol *mNodeFound;
TBasicType mBasicType;
};
} // anonymous namespace
bool compileTestShader(GLenum type, bool compileTestShader(GLenum type,
ShShaderSpec spec, ShShaderSpec spec,
ShShaderOutput output, ShShaderOutput output,
...@@ -172,3 +205,12 @@ bool MatchOutputCodeTest::notFoundInCode(const char *stringToFind) const ...@@ -172,3 +205,12 @@ bool MatchOutputCodeTest::notFoundInCode(const char *stringToFind) const
} }
return true; return true;
} }
const TIntermSymbol *FindSymbolNode(TIntermNode *root,
const TString &symbolName,
TBasicType basicType)
{
ShaderVariableFinder finder(symbolName, basicType);
root->traverse(&finder);
return finder.getNode();
}
...@@ -87,32 +87,8 @@ class MatchOutputCodeTest : public testing::Test ...@@ -87,32 +87,8 @@ class MatchOutputCodeTest : public testing::Test
std::map<ShShaderOutput, std::string> mOutputCode; std::map<ShShaderOutput, std::string> mOutputCode;
}; };
class ShaderVariableFinder : public TIntermTraverser const TIntermSymbol *FindSymbolNode(TIntermNode *root,
{ const TString &symbolName,
public: TBasicType basicType);
ShaderVariableFinder(const TString &variableName, TBasicType basicType)
: TIntermTraverser(true, false, false),
mVariableName(variableName),
mNodeFound(nullptr),
mBasicType(basicType)
{
}
void visitSymbol(TIntermSymbol *node)
{
if (node->getBasicType() == mBasicType && node->getSymbol() == mVariableName)
{
mNodeFound = node;
}
}
bool isFound() const { return mNodeFound != nullptr; }
const TIntermSymbol *getNode() const { return mNodeFound; }
private:
TString mVariableName;
TIntermSymbol *mNodeFound;
TBasicType mBasicType;
};
#endif // TESTS_TEST_UTILS_COMPILER_TEST_H_ #endif // TESTS_TEST_UTILS_COMPILER_TEST_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment