diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-08-05 11:35:53 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-08-05 11:35:53 +0200 |
commit | 6bd66b1728eeddb058066edda740aaeb2ceaec23 (patch) | |
tree | 985faf01c526763515731569fa01a99f4dbef36e /gfx/angle/src/compiler/translator | |
parent | e0a8dcfed131ffa58a5e2cb1d30fe48c745c2fdc (diff) | |
parent | 559824514dc95e02fbe81f1786e6ac13ee8e9d55 (diff) | |
download | UXP-6bd66b1728eeddb058066edda740aaeb2ceaec23.tar UXP-6bd66b1728eeddb058066edda740aaeb2ceaec23.tar.gz UXP-6bd66b1728eeddb058066edda740aaeb2ceaec23.tar.lz UXP-6bd66b1728eeddb058066edda740aaeb2ceaec23.tar.xz UXP-6bd66b1728eeddb058066edda740aaeb2ceaec23.zip |
Merge branch 'master' into js-modules
Diffstat (limited to 'gfx/angle/src/compiler/translator')
167 files changed, 8003 insertions, 11349 deletions
diff --git a/gfx/angle/src/compiler/translator/64bit-lexer-safety.patch b/gfx/angle/src/compiler/translator/64bit-lexer-safety.patch index e7e403771..db3b2fab5 100755 --- a/gfx/angle/src/compiler/translator/64bit-lexer-safety.patch +++ b/gfx/angle/src/compiler/translator/64bit-lexer-safety.patch @@ -1,13 +1,6 @@ -diff --git a/src/compiler/translator/glslang_lex.cpp b/src/compiler/translator/glslang_lex.cpp -index 1ba63df..2a206ab 100644 ---- a/src/compiler/translator/glslang_lex.cpp -+++ b/src/compiler/translator/glslang_lex.cpp -@@ -1,4 +1,3 @@ --#line 17 "./glslang.l" - // - // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. - // Use of this source code is governed by a BSD-style license that can be -@@ -149,6 +148,7 @@ typedef int16_t flex_int16_t; +--- a/src/compiler/glslang_lex.cpp ++++ b/src/compiler/glslang_lex.cpp +@@ -68,6 +68,7 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; @@ -15,10 +8,10 @@ index 1ba63df..2a206ab 100644 #else typedef signed char flex_int8_t; typedef short int flex_int16_t; -@@ -335,6 +335,11 @@ typedef size_t yy_size_t; - - - +@@ -191,6 +192,11 @@ typedef void* yyscan_t; + typedef struct yy_buffer_state *YY_BUFFER_STATE; + #endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; @@ -27,96 +20,21 @@ index 1ba63df..2a206ab 100644 #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 -@@ -351,8 +356,8 @@ typedef size_t yy_size_t; +@@ -204,7 +210,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; */ #define YY_LESS_LINENO(n) \ do { \ - int yyl;\ -- for ( yyl = n; yyl < yyleng; ++yyl )\ + yy_size_t yyl;\ -+ for ( yyl = n; yyl < static_cast<yy_site_t>(yyleng); ++yyl )\ + for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ - }while(0) -@@ -1692,7 +1697,7 @@ yy_find_action: - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - yy_size_t yyl; -- for ( yyl = 0; yyl < yyleng; ++yyl ) -+ for ( yyl = 0; yyl < static_cast<yy_size_t>(yyleng); ++yyl ) - if ( yytext[yyl] == '\n' ) - - do{ yylineno++; -@@ -2655,7 +2660,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) - else - { - int num_to_read = -- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; -+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - static_cast<int>(number_to_move) - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ -@@ -2690,7 +2695,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) - yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - -- number_to_move - 1; -+ static_cast<int>(number_to_move) - 1; - - } - -@@ -2698,8 +2703,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ -+ size_t result = 0; - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), -- yyg->yy_n_chars, num_to_read ); -+ result, num_to_read ); -+ yyg->yy_n_chars = static_cast<int>(result); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } -@@ -2725,13 +2732,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner) - - if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ -- int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); -+ int new_size = yyg->yy_n_chars + static_cast<int>(number_to_move) + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - -- yyg->yy_n_chars += number_to_move; -+ yyg->yy_n_chars += static_cast<int>(number_to_move); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - -@@ -3158,7 +3165,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner) - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; - -- num_to_alloc = yyg->yy_buffer_stack_max + grow_size; -+ num_to_alloc = static_cast<int>(yyg->yy_buffer_stack_max + grow_size); - yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc - (yyg->yy_buffer_stack, - num_to_alloc * sizeof(struct yy_buffer_state*) -@@ -3196,7 +3203,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscann - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - -- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ -+ b->yy_buf_size = static_cast<int>(size) - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = NULL; -@@ -3251,7 +3258,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yysc - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - -- for ( i = 0; i < _yybytes_len; ++i ) -+ for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; +@@ -378,7 +379,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + */ + #define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ +- yyleng = (size_t) (yy_cp - yy_bp); \ ++ yyleng = (yy_size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; diff --git a/gfx/angle/src/compiler/translator/ASTMetadataHLSL.cpp b/gfx/angle/src/compiler/translator/ASTMetadataHLSL.cpp index ba991b709..31bfae996 100755 --- a/gfx/angle/src/compiler/translator/ASTMetadataHLSL.cpp +++ b/gfx/angle/src/compiler/translator/ASTMetadataHLSL.cpp @@ -11,9 +11,6 @@ #include "compiler/translator/CallDAG.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - namespace { @@ -34,7 +31,7 @@ class PullGradient : public TIntermTraverser ASSERT(index < metadataList->size()); } - void traverse(TIntermFunctionDefinition *node) + void traverse(TIntermAggregate *node) { node->traverse(this); ASSERT(mParents.empty()); @@ -75,9 +72,9 @@ class PullGradient : public TIntermTraverser return true; } - bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override + bool visitSelection(Visit visit, TIntermSelection *selection) override { - visitControlFlow(visit, ifElse); + visitControlFlow(visit, selection); return true; } @@ -106,8 +103,9 @@ class PullGradient : public TIntermTraverser { if (node->isUserDefined()) { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); + size_t calleeIndex = mDag.findIndex(node); ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); + UNUSED_ASSERTION_VARIABLE(mIndex); if ((*mMetadataList)[calleeIndex].mUsesGradient) { onGradient(); @@ -115,8 +113,7 @@ class PullGradient : public TIntermTraverser } else { - TString name = - TFunction::unmangleName(node->getFunctionSymbolInfo()->getName()); + TString name = TFunction::unmangleName(node->getName()); if (name == "texture2D" || name == "texture2DProj" || @@ -160,7 +157,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser { } - void traverse(TIntermFunctionDefinition *node) + void traverse(TIntermAggregate *node) { node->traverse(this); ASSERT(mLoopsAndSwitches.empty()); @@ -199,7 +196,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser return true; } - bool visitIfElse(Visit visit, TIntermIfElse *node) override + bool visitSelection(Visit visit, TIntermSelection *node) override { if (visit == PreVisit) { @@ -278,8 +275,9 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser { if (node->isUserDefined()) { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); + size_t calleeIndex = mDag.findIndex(node); ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); + UNUSED_ASSERTION_VARIABLE(mIndex); if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph) { @@ -312,7 +310,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser const CallDAG &mDag; std::vector<TIntermNode*> mLoopsAndSwitches; - std::vector<TIntermIfElse *> mIfs; + std::vector<TIntermSelection*> mIfs; }; // Tags all the functions called in a discontinuous loop @@ -329,7 +327,7 @@ class PushDiscontinuousLoops : public TIntermTraverser { } - void traverse(TIntermFunctionDefinition *node) + void traverse(TIntermAggregate *node) { node->traverse(this); ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)); @@ -358,8 +356,9 @@ class PushDiscontinuousLoops : public TIntermTraverser case EOpFunctionCall: if (visit == PreVisit && node->isUserDefined() && mNestedDiscont > 0) { - size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo()); + size_t calleeIndex = mDag.findIndex(node); ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex); + UNUSED_ASSERTION_VARIABLE(mIndex); (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true; } @@ -386,7 +385,7 @@ bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node) return mControlFlowsContainingGradient.count(node) > 0; } -bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node) +bool ASTMetadataHLSL::hasGradientLoop(TIntermSelection *node) { return mIfsContainingGradientLoop.count(node) > 0; } @@ -450,5 +449,3 @@ MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag) return metadataList; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ASTMetadataHLSL.h b/gfx/angle/src/compiler/translator/ASTMetadataHLSL.h index f8ed5af4a..39e671e3e 100755 --- a/gfx/angle/src/compiler/translator/ASTMetadataHLSL.h +++ b/gfx/angle/src/compiler/translator/ASTMetadataHLSL.h @@ -12,12 +12,9 @@ #include <set> #include <vector> -namespace sh -{ - class CallDAG; class TIntermNode; -class TIntermIfElse; +class TIntermSelection; class TIntermLoop; struct ASTMetadataHLSL @@ -33,7 +30,7 @@ struct ASTMetadataHLSL // Here "something uses a gradient" means here that it either contains a // gradient operation, or a call to a function that uses a gradient. bool hasGradientInCallGraph(TIntermLoop *node); - bool hasGradientLoop(TIntermIfElse *node); + bool hasGradientLoop(TIntermSelection *node); // Does the function use a gradient. bool mUsesGradient; @@ -47,7 +44,7 @@ struct ASTMetadataHLSL bool mCalledInDiscontinuousLoop; bool mHasGradientLoopInCallGraph; std::set<TIntermLoop*> mDiscontinuousLoops; - std::set<TIntermIfElse *> mIfsContainingGradientLoop; + std::set<TIntermSelection *> mIfsContainingGradientLoop; // Will we need to generate a Lod0 version of the function. bool mNeedsLod0; @@ -58,6 +55,4 @@ typedef std::vector<ASTMetadataHLSL> MetadataList; // Return the AST analysis result, in the order defined by the call DAG MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag); -} // namespace sh - #endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/gfx/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp deleted file mode 100644 index 0177fea96..000000000 --- a/gfx/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/AddAndTrueToLoopCondition.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that rewrites for and while loops by replacing "condition" with -// "condition && true" to work around condition bug on Intel Mac. -class AddAndTrueToLoopConditionTraverser : public TIntermTraverser -{ - public: - AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {} - - bool visitLoop(Visit, TIntermLoop *loop) override - { - // do-while loop doesn't have this bug. - if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile) - { - return true; - } - - // For loop may not have a condition. - if (loop->getCondition() == nullptr) - { - return true; - } - - // Constant true. - TConstantUnion *trueConstant = new TConstantUnion(); - trueConstant->setBConst(true); - TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool)); - - // CONDITION && true. - TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue); - loop->setCondition(andOp); - - return true; - } -}; - -} // anonymous namespace - -void AddAndTrueToLoopCondition(TIntermNode *root) -{ - AddAndTrueToLoopConditionTraverser traverser; - root->traverse(&traverser); -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/AddAndTrueToLoopCondition.h b/gfx/angle/src/compiler/translator/AddAndTrueToLoopCondition.h deleted file mode 100644 index 34debe0ed..000000000 --- a/gfx/angle/src/compiler/translator/AddAndTrueToLoopCondition.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Rewrite condition in for and while loops to work around driver bug on Intel Mac. - -#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ -#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ - -class TIntermNode; -namespace sh -{ - -void AddAndTrueToLoopCondition(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ diff --git a/gfx/angle/src/compiler/translator/AddDefaultReturnStatements.cpp b/gfx/angle/src/compiler/translator/AddDefaultReturnStatements.cpp index 5767aea2b..97111d1a1 100755 --- a/gfx/angle/src/compiler/translator/AddDefaultReturnStatements.cpp +++ b/gfx/angle/src/compiler/translator/AddDefaultReturnStatements.cpp @@ -31,16 +31,21 @@ class AddDefaultReturnStatementsTraverser : private TIntermTraverser private: AddDefaultReturnStatementsTraverser() : TIntermTraverser(true, false, false) {} - static bool IsFunctionWithoutReturnStatement(TIntermFunctionDefinition *node, TType *returnType) + static bool IsFunctionWithoutReturnStatement(TIntermAggregate *node, TType *returnType) { *returnType = node->getType(); - if (node->getType().getBasicType() == EbtVoid) + if (node->getOp() != EOpFunction || node->getType().getBasicType() == EbtVoid) { return false; } - TIntermBlock *bodyNode = node->getBody(); - TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode(); + TIntermAggregate *lastNode = node->getSequence()->back()->getAsAggregate(); + if (lastNode == nullptr) + { + return true; + } + + TIntermBranch *returnNode = lastNode->getSequence()->front()->getAsBranchNode(); if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn) { return false; @@ -49,16 +54,51 @@ class AddDefaultReturnStatementsTraverser : private TIntermTraverser return true; } - bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *node) override + static TIntermTyped *GenerateTypeConstructor(const TType &returnType) + { + // Base case, constructing a single element + if (!returnType.isArray()) + { + size_t objectSize = returnType.getObjectSize(); + TConstantUnion *constantUnion = new TConstantUnion[objectSize]; + for (size_t constantIdx = 0; constantIdx < objectSize; constantIdx++) + { + constantUnion[constantIdx].setFConst(0.0f); + } + + TIntermConstantUnion *intermConstantUnion = + new TIntermConstantUnion(constantUnion, returnType); + return intermConstantUnion; + } + + // Recursive case, construct an array of single elements + TIntermAggregate *constructorAggrigate = + new TIntermAggregate(TypeToConstructorOperator(returnType)); + constructorAggrigate->setType(returnType); + + size_t arraySize = returnType.getArraySize(); + for (size_t arrayIdx = 0; arrayIdx < arraySize; arrayIdx++) + { + TType arrayElementType(returnType); + arrayElementType.clearArrayness(); + + constructorAggrigate->getSequence()->push_back( + GenerateTypeConstructor(arrayElementType)); + } + + return constructorAggrigate; + } + + bool visitAggregate(Visit, TIntermAggregate *node) override { TType returnType; if (IsFunctionWithoutReturnStatement(node, &returnType)) { TIntermBranch *branch = - new TIntermBranch(EOpReturn, TIntermTyped::CreateZero(returnType)); + new TIntermBranch(EOpReturn, GenerateTypeConstructor(returnType)); - TIntermBlock *bodyNode = node->getBody(); - bodyNode->getSequence()->push_back(branch); + TIntermAggregate *lastNode = node->getSequence()->back()->getAsAggregate(); + lastNode->getSequence()->push_back(branch); return false; } diff --git a/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp index 766f700ee..af5bb9ce3 100755 --- a/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp +++ b/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp @@ -10,9 +10,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - namespace { @@ -44,7 +41,8 @@ TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, TIntermT TIntermAggregate *replacementCall = new TIntermAggregate(EOpFunctionCall); replacementCall->setType(TType(EbtVoid)); replacementCall->setUserDefined(); - *replacementCall->getFunctionSymbolInfo() = *originalCall->getFunctionSymbolInfo(); + replacementCall->setNameObj(originalCall->getNameObj()); + replacementCall->setFunctionId(originalCall->getFunctionId()); replacementCall->setLine(originalCall->getLine()); TIntermSequence *replacementParameters = replacementCall->getSequence(); TIntermSequence *originalParameters = originalCall->getSequence(); @@ -63,7 +61,6 @@ class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser private: ArrayReturnValueToOutParameterTraverser(); - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitBranch(Visit visit, TIntermBranch *node) override; bool visitBinary(Visit visit, TIntermBinary *node) override; @@ -85,47 +82,35 @@ ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser { } -bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition( - Visit visit, - TIntermFunctionDefinition *node) +bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { - if (node->isArray() && visit == PreVisit) + if (visit == PreVisit) { - // Replace the parameters child node of the function definition with another node - // that has the out parameter added. - // Also set the function to return void. - - TIntermAggregate *params = node->getFunctionParameters(); - ASSERT(params != nullptr && params->getOp() == EOpParameters); + if (node->isArray()) + { + if (node->getOp() == EOpFunction) + { + // Replace the parameters child node of the function definition with another node + // that has the out parameter added. + // Also set the function to return void. - TIntermAggregate *replacementParams = new TIntermAggregate; - replacementParams->setOp(EOpParameters); - CopyAggregateChildren(params, replacementParams); - replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType())); - replacementParams->setLine(params->getLine()); + TIntermAggregate *params = node->getSequence()->front()->getAsAggregate(); + ASSERT(params != nullptr && params->getOp() == EOpParameters); - queueReplacementWithParent(node, params, replacementParams, OriginalNode::IS_DROPPED); + TIntermAggregate *replacementParams = new TIntermAggregate; + replacementParams->setOp(EOpParameters); + CopyAggregateChildren(params, replacementParams); + replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType())); + replacementParams->setLine(params->getLine()); - node->setType(TType(EbtVoid)); + queueReplacementWithParent(node, params, replacementParams, + OriginalNode::IS_DROPPED); - mInFunctionWithArrayReturnValue = true; - } - if (visit == PostVisit) - { - // This isn't conditional on node->isArray() since the type has already been changed on - // PreVisit. - mInFunctionWithArrayReturnValue = false; - } - return true; -} + node->setType(TType(EbtVoid)); -bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node) -{ - if (visit == PreVisit) - { - if (node->isArray()) - { - if (node->getOp() == EOpPrototype) + mInFunctionWithArrayReturnValue = true; + } + else if (node->getOp() == EOpPrototype) { // Replace the whole prototype node with another node that has the out parameter added. TIntermAggregate *replacement = new TIntermAggregate; @@ -133,7 +118,8 @@ bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TInter CopyAggregateChildren(node, replacement); replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType())); replacement->setUserDefined(); - *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo(); + replacement->setNameObj(node->getNameObj()); + replacement->setFunctionId(node->getFunctionId()); replacement->setLine(node->getLine()); replacement->setType(TType(EbtVoid)); @@ -150,21 +136,27 @@ bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TInter // Cases 2 to 4 are already converted to simpler cases by SeparateExpressionsReturningArrays, so we // only need to worry about the case where a function call returning an array forms an expression by // itself. - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - if (parentBlock) + TIntermAggregate *parentAgg = getParentNode()->getAsAggregate(); + if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence) { nextTemporaryIndex(); TIntermSequence replacements; replacements.push_back(createTempDeclaration(node->getType())); TIntermSymbol *returnSymbol = createTempSymbol(node->getType()); replacements.push_back(CreateReplacementCall(node, returnSymbol)); - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements)); } return false; } } } + else if (visit == PostVisit) + { + if (node->getOp() == EOpFunction) + { + mInFunctionWithArrayReturnValue = false; + } + } return true; } @@ -175,11 +167,12 @@ bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBr // Instead of returning a value, assign to the out parameter and then return. TIntermSequence replacements; + TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign); TIntermTyped *expression = node->getExpression(); ASSERT(expression != nullptr); - TIntermSymbol *returnValueSymbol = CreateReturnValueSymbol(expression->getType()); - TIntermBinary *replacementAssignment = - new TIntermBinary(EOpAssign, returnValueSymbol, expression); + replacementAssignment->setLeft(CreateReturnValueSymbol(expression->getType())); + replacementAssignment->setRight(node->getExpression()); + replacementAssignment->setType(expression->getType()); replacementAssignment->setLine(expression->getLine()); replacements.push_back(replacementAssignment); @@ -187,8 +180,7 @@ bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBr replacementBranch->setLine(node->getLine()); replacements.push_back(replacementBranch); - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements)); + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsAggregate(), node, replacements)); } return false; } @@ -213,5 +205,3 @@ void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIn { ArrayReturnValueToOutParameterTraverser::apply(root, temporaryIndex); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h b/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h index e030f6ffe..983e203e6 100755 --- a/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h +++ b/gfx/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h @@ -9,11 +9,8 @@ #ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ #define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ -namespace sh -{ class TIntermNode; void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex); -} // namespace sh #endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ diff --git a/gfx/angle/src/compiler/translator/BaseTypes.h b/gfx/angle/src/compiler/translator/BaseTypes.h index e050c88da..72ecb50f4 100755 --- a/gfx/angle/src/compiler/translator/BaseTypes.h +++ b/gfx/angle/src/compiler/translator/BaseTypes.h @@ -13,9 +13,6 @@ #include "common/debug.h" #include "GLSLANG/ShaderLang.h" -namespace sh -{ - // // Precision qualifiers // @@ -35,10 +32,10 @@ inline const char* getPrecisionString(TPrecision p) { switch(p) { - case EbpHigh: return "highp"; - case EbpMedium: return "mediump"; - case EbpLow: return "lowp"; - default: return "mediump"; // Safest fallback + case EbpHigh: return "highp"; break; + case EbpMedium: return "mediump"; break; + case EbpLow: return "lowp"; break; + default: return "mediump"; break; // Safest fallback } } @@ -79,98 +76,19 @@ enum TBasicType EbtSampler2DShadow, EbtSamplerCubeShadow, EbtSampler2DArrayShadow, - EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D - EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D - EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube - EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and - // usampler2DArray - - // images - EbtGuardImageBegin, - EbtImage2D, - EbtIImage2D, - EbtUImage2D, - EbtImage3D, - EbtIImage3D, - EbtUImage3D, - EbtImage2DArray, - EbtIImage2DArray, - EbtUImage2DArray, - EbtImageCube, - EbtIImageCube, - EbtUImageCube, - EbtGuardImageEnd, - - EbtGuardGImageBegin, - EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D - EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D - EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray - EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube - EbtGuardGImageEnd, - + EbtGuardSamplerEnd, // non type: see implementation of IsSampler() + EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D + EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D + EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube + EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray EbtStruct, EbtInterfaceBlock, - EbtAddress, // should be deprecated?? + EbtAddress, // should be deprecated?? // end of list EbtLast }; -inline TBasicType convertGImageToFloatImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtImage2D; - case EbtGImage3D: - return EbtImage3D; - case EbtGImage2DArray: - return EbtImage2DArray; - case EbtGImageCube: - return EbtImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -inline TBasicType convertGImageToIntImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtIImage2D; - case EbtGImage3D: - return EbtIImage3D; - case EbtGImage2DArray: - return EbtIImage2DArray; - case EbtGImageCube: - return EbtIImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - -inline TBasicType convertGImageToUnsignedImage(TBasicType type) -{ - switch (type) - { - case EbtGImage2D: - return EbtUImage2D; - case EbtGImage3D: - return EbtUImage3D; - case EbtGImage2DArray: - return EbtUImage2DArray; - case EbtGImageCube: - return EbtUImageCube; - default: - UNREACHABLE(); - } - return EbtLast; -} - const char* getBasicString(TBasicType t); inline bool IsSampler(TBasicType type) @@ -178,22 +96,6 @@ inline bool IsSampler(TBasicType type) return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; } -inline bool IsImage(TBasicType type) -{ - return type > EbtGuardImageBegin && type < EbtGuardImageEnd; -} - -inline bool IsGImage(TBasicType type) -{ - return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd; -} - -inline bool IsOpaqueType(TBasicType type) -{ - // TODO (mradev): add atomic types as opaque. - return IsSampler(type) || IsImage(type); -} - inline bool IsIntegerSampler(TBasicType type) { switch (type) @@ -224,56 +126,6 @@ inline bool IsIntegerSampler(TBasicType type) return false; } -inline bool IsFloatImage(TBasicType type) -{ - switch (type) - { - case EbtImage2D: - case EbtImage3D: - case EbtImage2DArray: - case EbtImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsIntegerImage(TBasicType type) -{ - - switch (type) - { - case EbtIImage2D: - case EbtIImage3D: - case EbtIImage2DArray: - case EbtIImageCube: - return true; - default: - break; - } - - return false; -} - -inline bool IsUnsignedImage(TBasicType type) -{ - - switch (type) - { - case EbtUImage2D: - case EbtUImage3D: - case EbtUImage2DArray: - case EbtUImageCube: - return true; - default: - break; - } - - return false; -} - inline bool IsSampler2D(TBasicType type) { switch (type) @@ -431,7 +283,7 @@ inline bool IsInteger(TBasicType type) inline bool SupportsPrecision(TBasicType type) { - return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type); + return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type); } // @@ -489,11 +341,10 @@ enum TQualifier EvqLastFragData, // GLSL ES 3.0 vertex output and fragment input - EvqSmooth, // Incomplete qualifier, smooth is the default - EvqFlat, // Incomplete qualifier - EvqCentroid, // Incomplete qualifier - EvqSmoothOut, - EvqFlatOut, + EvqSmooth, // Incomplete qualifier, smooth is the default + EvqFlat, // Incomplete qualifier + EvqSmoothOut = EvqSmooth, + EvqFlatOut = EvqFlat, EvqCentroidOut, // Implies smooth EvqSmoothIn, EvqFlatIn, @@ -508,40 +359,10 @@ enum TQualifier EvqGlobalInvocationID, EvqLocalInvocationIndex, - // GLSL ES 3.1 memory qualifiers - EvqReadOnly, - EvqWriteOnly, - EvqCoherent, - EvqRestrict, - EvqVolatile, - // end of list EvqLast }; -inline bool IsQualifierUnspecified(TQualifier qualifier) -{ - return (qualifier == EvqTemporary || qualifier == EvqGlobal); -} - -enum TLayoutImageInternalFormat -{ - EiifUnspecified, - EiifRGBA32F, - EiifRGBA16F, - EiifR32F, - EiifRGBA32UI, - EiifRGBA16UI, - EiifRGBA8UI, - EiifR32UI, - EiifRGBA32I, - EiifRGBA16I, - EiifRGBA8I, - EiifR32I, - EiifRGBA8, - EiifRGBA8_SNORM -}; - enum TLayoutMatrixPacking { EmpUnspecified, @@ -560,44 +381,36 @@ enum TLayoutBlockStorage struct TLayoutQualifier { int location; - unsigned int locationsSpecified; TLayoutMatrixPacking matrixPacking; TLayoutBlockStorage blockStorage; // Compute shader layout qualifiers. sh::WorkGroupSize localSize; - // Image format layout qualifier - TLayoutImageInternalFormat imageInternalFormat; - static TLayoutQualifier create() { TLayoutQualifier layoutQualifier; layoutQualifier.location = -1; - layoutQualifier.locationsSpecified = 0; layoutQualifier.matrixPacking = EmpUnspecified; layoutQualifier.blockStorage = EbsUnspecified; layoutQualifier.localSize.fill(-1); - layoutQualifier.imageInternalFormat = EiifUnspecified; return layoutQualifier; } bool isEmpty() const { return location == -1 && matrixPacking == EmpUnspecified && - blockStorage == EbsUnspecified && !localSize.isAnyValueSet() && - imageInternalFormat == EiifUnspecified; + blockStorage == EbsUnspecified && !localSize.isAnyValueSet(); } bool isCombinationValid() const { bool workSizeSpecified = localSize.isAnyValueSet(); bool otherLayoutQualifiersSpecified = - (location != -1 || matrixPacking != EmpUnspecified || blockStorage != EbsUnspecified || - imageInternalFormat != EiifUnspecified); + (location != -1 || matrixPacking != EmpUnspecified || blockStorage != EbsUnspecified); // we can have either the work group size specified, or the other layout qualifiers return !(workSizeSpecified && otherLayoutQualifiersSpecified); @@ -609,37 +422,6 @@ struct TLayoutQualifier } }; -struct TMemoryQualifier -{ - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - // An image can be qualified as both readonly and writeonly. It still can be can be used with - // imageSize(). - bool readonly; - bool writeonly; - bool coherent; - - // restrict and volatile are reserved keywords in C/C++ - bool restrictQualifier; - bool volatileQualifier; - static TMemoryQualifier create() - { - TMemoryQualifier memoryQualifier; - - memoryQualifier.readonly = false; - memoryQualifier.writeonly = false; - memoryQualifier.coherent = false; - memoryQualifier.restrictQualifier = false; - memoryQualifier.volatileQualifier = false; - - return memoryQualifier; - } - - bool isEmpty() - { - return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier; - } -}; - inline const char *getWorkGroupSizeString(size_t dimension) { switch (dimension) @@ -700,9 +482,6 @@ inline const char* getQualifierString(TQualifier q) case EvqSmoothIn: return "smooth in"; case EvqFlatIn: return "flat in"; case EvqCentroidIn: return "smooth centroid in"; - case EvqCentroid: return "centroid"; - case EvqFlat: return "flat"; - case EvqSmooth: return "smooth"; case EvqComputeIn: return "in"; case EvqNumWorkGroups: return "NumWorkGroups"; case EvqWorkGroupSize: return "WorkGroupSize"; @@ -710,8 +489,6 @@ inline const char* getQualifierString(TQualifier q) case EvqLocalInvocationID: return "LocalInvocationID"; case EvqGlobalInvocationID: return "GlobalInvocationID"; case EvqLocalInvocationIndex: return "LocalInvocationIndex"; - case EvqReadOnly: return "readonly"; - case EvqWriteOnly: return "writeonly"; default: UNREACHABLE(); return "unknown qualifier"; } // clang-format on @@ -740,42 +517,18 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq) } } -inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq) +inline const char* getInterpolationString(TQualifier q) { - switch (iifq) + switch(q) { - case EiifRGBA32F: - return "rgba32f"; - case EiifRGBA16F: - return "rgba16f"; - case EiifR32F: - return "r32f"; - case EiifRGBA32UI: - return "rgba32ui"; - case EiifRGBA16UI: - return "rgba16ui"; - case EiifRGBA8UI: - return "rgba8ui"; - case EiifR32UI: - return "r32ui"; - case EiifRGBA32I: - return "rgba32i"; - case EiifRGBA16I: - return "rgba16i"; - case EiifRGBA8I: - return "rgba8i"; - case EiifR32I: - return "r32i"; - case EiifRGBA8: - return "rgba8"; - case EiifRGBA8_SNORM: - return "rgba8_snorm"; - default: - UNREACHABLE(); - return "unknown internal image format"; + case EvqSmoothOut: return "smooth"; break; + case EvqCentroidOut: return "smooth centroid"; break; + case EvqFlatOut: return "flat"; break; + case EvqSmoothIn: return "smooth"; break; + case EvqCentroidIn: return "smooth centroid"; break; + case EvqFlatIn: return "flat"; break; + default: UNREACHABLE(); return "unknown interpolation"; } } -} // namespace sh - #endif // COMPILER_TRANSLATOR_BASETYPES_H_ diff --git a/gfx/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/gfx/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp deleted file mode 100644 index 018e72cd1..000000000 --- a/gfx/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend -// may record a variable as aliasing another. Sometimes the alias information gets garbled -// so we work around this issue by breaking the aliasing chain in inner loops. - -#include "BreakVariableAliasingInInnerLoops.h" - -#include "compiler/translator/IntermNode.h" - -// A HLSL compiler developer gave us more details on the root cause and the workaround needed: -// The root problem is that if the HLSL compiler is applying aliasing information even on -// incomplete simulations (in this case, a single pass). The bug is triggered by an assignment -// that comes from a series of assignments, possibly with swizzled or ternary operators with -// known conditionals, where the source is before the loop. -// So, a workaround is to add a +0 term to variables the first time they are assigned to in -// an inner loop (if they are declared in an outside scope, otherwise there is no need). -// This will break the aliasing chain. - -// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because -// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure -// assignment don't need a workaround. - -namespace sh -{ - -namespace -{ - -class AliasingBreaker : public TIntermTraverser -{ - public: - AliasingBreaker() : TIntermTraverser(true, false, true) {} - - protected: - bool visitBinary(Visit visit, TIntermBinary *binary) - { - if (visit != PreVisit) - { - return false; - } - - if (mLoopLevel < 2 || !binary->isAssignment()) - { - return true; - } - - TIntermTyped *B = binary->getRight(); - TType type = B->getType(); - - if (!type.isScalar() && !type.isVector() && !type.isMatrix()) - { - return true; - } - - if (type.isArray() || IsSampler(type.getBasicType())) - { - return true; - } - - // We have a scalar / vector / matrix assignment with loop depth 2. - // Transform it from - // A = B - // to - // A = (B + typeof<B>(0)); - - TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, TIntermTyped::CreateZero(type)); - bPlusZero->setLine(B->getLine()); - - binary->replaceChildNode(B, bPlusZero); - - return true; - } - - bool visitLoop(Visit visit, TIntermLoop *loop) - { - if (visit == PreVisit) - { - mLoopLevel++; - } - else - { - ASSERT(mLoopLevel > 0); - mLoopLevel--; - } - - return true; - } - - private: - int mLoopLevel = 0; -}; - -} // anonymous namespace - -void BreakVariableAliasingInInnerLoops(TIntermNode *root) -{ - AliasingBreaker breaker; - root->traverse(&breaker); -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h b/gfx/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h deleted file mode 100644 index b1d906f91..000000000 --- a/gfx/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend -// may record a variable as aliasing another. Sometimes the alias information gets garbled -// so we work around this issue by breaking the aliasing chain in inner loops. - -#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ -#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ - -class TIntermNode; - -namespace sh -{ - -void BreakVariableAliasingInInnerLoops(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp index 152251fde..483fb4467 100755 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -9,9 +9,6 @@ #include "compiler/translator/SymbolTable.h" #include "compiler/translator/Cache.h" -namespace sh -{ - class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser { public: @@ -245,5 +242,3 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy { return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3)); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h index db5c202d2..6976edfd5 100755 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -10,9 +10,6 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" -namespace sh -{ - // // This class decides which built-in functions need to be replaced with the // emulated ones. @@ -85,6 +82,4 @@ class BuiltInFunctionEmulator std::vector<FunctionId> mFunctions; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp index 74397fb7f..075a55361 100755 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp @@ -11,68 +11,32 @@ #include "compiler/translator/SymbolTable.h" #include "compiler/translator/VersionGLSL.h" -namespace sh +void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType) { - -void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType) -{ - if (shaderType == GL_VERTEX_SHADER) - { - const TType *int1 = TCache::getType(EbtInt); - emu->addEmulatedFunction(EOpAbs, int1, "int webgl_abs_emu(int x) { return x * sign(x); }"); - } -} - -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - // isnan() is supported since GLSL 1.3. - if (targetGLSLVersion < GLSL_VERSION_130) - return; + // we use macros here instead of function definitions to work around more GLSL + // compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are + // problematic because if the argument has side-effects they will be repeatedly + // evaluated. This is unlikely to show up in real shaders, but is something to + // consider. const TType *float1 = TCache::getType(EbtFloat); const TType *float2 = TCache::getType(EbtFloat, 2); const TType *float3 = TCache::getType(EbtFloat, 3); const TType *float4 = TCache::getType(EbtFloat, 4); - // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. - emu->addEmulatedFunction( - EOpIsNan, float1, - "bool webgl_isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); - emu->addEmulatedFunction( - EOpIsNan, float2, - "bvec2 webgl_isnan_emu(vec2 x)\n" - "{\n" - " bvec2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - EOpIsNan, float3, - "bvec3 webgl_isnan_emu(vec3 x)\n" - "{\n" - " bvec3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - emu->addEmulatedFunction( - EOpIsNan, float4, - "bvec4 webgl_isnan_emu(vec4 x)\n" - "{\n" - " bvec4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); + if (shaderType == GL_FRAGMENT_SHADER) + { + emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }"); + } + emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))"); + emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))"); + emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))"); + emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))"); + emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))"); + emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1, "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))"); } // Emulate built-in functions missing from GLSL 1.30 and higher @@ -217,9 +181,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator " float scale;\n" " if(exponent < 0)\n" " {\n" - " // The negative unary operator is buggy on OSX.\n" - " // Work around this by using abs instead.\n" - " scale = 1.0 / (1 << abs(exponent));\n" + " scale = 1.0 / (1 << -exponent);\n" " }\n" " else\n" " {\n" @@ -251,5 +213,3 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator // clang-format on } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h index 09fc85b0d..56242598a 100755 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h @@ -9,27 +9,17 @@ #include "GLSLANG/ShaderLang.h" -namespace sh -{ class BuiltInFunctionEmulator; // -// This works around bug in Intel Mac drivers. +// This is only a workaround for OpenGL driver bugs, and isn't needed in general. // -void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - sh::GLenum shaderType); - -// -// This works around isnan() bug in Intel Mac drivers -// -void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); +void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType); // // This function is emulating built-in functions missing from GLSL 1.30 and higher. // void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, sh::GLenum shaderType, int targetGLSLVersion); -} // namespace sh #endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp index c51062e1e..50e15cbc2 100755 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp @@ -8,62 +8,6 @@ #include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" #include "compiler/translator/SymbolTable.h" -#include "compiler/translator/VersionGLSL.h" - -namespace sh -{ - -void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion) -{ - if (targetGLSLVersion < GLSL_VERSION_130) - return; - - TType *float1 = new TType(EbtFloat); - TType *float2 = new TType(EbtFloat, 2); - TType *float3 = new TType(EbtFloat, 3); - TType *float4 = new TType(EbtFloat, 4); - - emu->addEmulatedFunction(EOpIsNan, float1, - "bool webgl_isnan_emu(float x)\n" - "{\n" - " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n" - "}\n" - "\n"); - - emu->addEmulatedFunction(EOpIsNan, float2, - "bool2 webgl_isnan_emu(float2 x)\n" - "{\n" - " bool2 isnan;\n" - " for (int i = 0; i < 2; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - - emu->addEmulatedFunction(EOpIsNan, float3, - "bool3 webgl_isnan_emu(float3 x)\n" - "{\n" - " bool3 isnan;\n" - " for (int i = 0; i < 3; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); - - emu->addEmulatedFunction(EOpIsNan, float4, - "bool4 webgl_isnan_emu(float4 x)\n" - "{\n" - " bool4 isnan;\n" - " for (int i = 0; i < 4; i++)\n" - " {\n" - " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n" - " }\n" - " return isnan;\n" - "}\n"); -} void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) { @@ -495,5 +439,3 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) "}\n"); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h index 48da73f58..4c45a93dc 100755 --- a/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h +++ b/gfx/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h @@ -9,19 +9,8 @@ #include "GLSLANG/ShaderLang.h" -namespace sh -{ - class BuiltInFunctionEmulator; void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu); -// -// This works around isnan() bug on some Intel drivers. -// -void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, - int targetGLSLVersion); - -} // namespace sh - #endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/Cache.cpp b/gfx/angle/src/compiler/translator/Cache.cpp index 094e3ff57..57a43700c 100755 --- a/gfx/angle/src/compiler/translator/Cache.cpp +++ b/gfx/angle/src/compiler/translator/Cache.cpp @@ -12,9 +12,6 @@ #include "common/debug.h" #include "compiler/translator/Cache.h" -namespace sh -{ - namespace { @@ -47,6 +44,7 @@ TCache::TypeKey::TypeKey(TBasicType basicType, "TypeKey::value is too small"); const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max(); + UNUSED_ASSERTION_VARIABLE(MaxEnumValue); // TODO: change to static_assert() once we deprecate MSVC 2013 support ASSERT(MaxEnumValue >= EbtLast && @@ -100,5 +98,3 @@ const TType *TCache::getType(TBasicType basicType, return type; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Cache.h b/gfx/angle/src/compiler/translator/Cache.h index 9a5607f24..1d2abb77e 100755 --- a/gfx/angle/src/compiler/translator/Cache.h +++ b/gfx/angle/src/compiler/translator/Cache.h @@ -16,9 +16,6 @@ #include "compiler/translator/Types.h" #include "compiler/translator/PoolAlloc.h" -namespace sh -{ - class TCache { public: @@ -90,6 +87,4 @@ class TCache static TCache *sCache; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_CACHE_H_ diff --git a/gfx/angle/src/compiler/translator/CallDAG.cpp b/gfx/angle/src/compiler/translator/CallDAG.cpp index 00aa833b8..10f0eb937 100755 --- a/gfx/angle/src/compiler/translator/CallDAG.cpp +++ b/gfx/angle/src/compiler/translator/CallDAG.cpp @@ -11,9 +11,6 @@ #include "compiler/translator/CallDAG.h" #include "compiler/translator/InfoSink.h" -namespace sh -{ - // The CallDAGCreator does all the processing required to create the CallDAG // structure so that the latter contains only the necessary variables. class CallDAG::CallDAGCreator : public TIntermTraverser @@ -47,7 +44,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser skipped++; } } - ASSERT(mFunctions.size() == mCurrentIndex + skipped); return INITDAG_SUCCESS; } @@ -79,8 +75,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser record.callees.push_back(static_cast<int>(callee->index)); } - (*idToIndex)[data.node->getFunctionSymbolInfo()->getId()] = - static_cast<int>(data.index); + (*idToIndex)[data.node->getFunctionId()] = static_cast<int>(data.index); } } @@ -97,39 +92,13 @@ class CallDAG::CallDAGCreator : public TIntermTraverser } std::set<CreatorFunctionData*> callees; - TIntermFunctionDefinition *node; + TIntermAggregate *node; TString name; size_t index; bool indexAssigned; bool visiting; }; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override - { - // Create the record if need be and remember the node. - if (visit == PreVisit) - { - auto it = mFunctions.find(node->getFunctionSymbolInfo()->getName()); - - if (it == mFunctions.end()) - { - mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getName()]; - } - else - { - mCurrentFunction = &it->second; - } - - mCurrentFunction->node = node; - mCurrentFunction->name = node->getFunctionSymbolInfo()->getName(); - } - else if (visit == PostVisit) - { - mCurrentFunction = nullptr; - } - return true; - } - // Aggregates the AST node for each function as well as the name of the functions called by it bool visitAggregate(Visit visit, TIntermAggregate *node) override { @@ -139,10 +108,36 @@ class CallDAG::CallDAGCreator : public TIntermTraverser if (visit == PreVisit) { // Function declaration, create an empty record. - auto &record = mFunctions[node->getFunctionSymbolInfo()->getName()]; - record.name = node->getFunctionSymbolInfo()->getName(); + auto& record = mFunctions[node->getName()]; + record.name = node->getName(); } break; + case EOpFunction: + { + // Function definition, create the record if need be and remember the node. + if (visit == PreVisit) + { + auto it = mFunctions.find(node->getName()); + + if (it == mFunctions.end()) + { + mCurrentFunction = &mFunctions[node->getName()]; + } + else + { + mCurrentFunction = &it->second; + } + + mCurrentFunction->node = node; + mCurrentFunction->name = node->getName(); + + } + else if (visit == PostVisit) + { + mCurrentFunction = nullptr; + } + break; + } case EOpFunctionCall: { // Function call, add the callees @@ -151,7 +146,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser // Do not handle calls to builtin functions if (node->isUserDefined()) { - auto it = mFunctions.find(node->getFunctionSymbolInfo()->getName()); + auto it = mFunctions.find(node->getName()); ASSERT(it != mFunctions.end()); // We might be in a top-level function call to set a global variable @@ -170,102 +165,52 @@ class CallDAG::CallDAGCreator : public TIntermTraverser } // Recursively assigns indices to a sub DAG - InitResult assignIndicesInternal(CreatorFunctionData *root) + InitResult assignIndicesInternal(CreatorFunctionData *function) { - // Iterative implementation of the index assignment algorithm. A recursive version - // would be prettier but since the CallDAG creation runs before the limiting of the - // call depth, we might get stack overflows (computation of the call depth uses the - // CallDAG). + ASSERT(function); - ASSERT(root); + if (!function->node) + { + *mCreationInfo << "Undefined function '" << function->name + << ")' used in the following call chain:"; + return INITDAG_UNDEFINED; + } - if (root->indexAssigned) + if (function->indexAssigned) { return INITDAG_SUCCESS; } - // If we didn't have to detect recursion, functionsToProcess could be a simple queue - // in which we add the function being processed's callees. However in order to detect - // recursion we need to know which functions we are currently visiting. For that reason - // functionsToProcess will look like a concatenation of segments of the form - // [F visiting = true, subset of F callees with visiting = false] and the following - // segment (if any) will be start with a callee of F. - // This way we can remember when we started visiting a function, to put visiting back - // to false. - TVector<CreatorFunctionData *> functionsToProcess; - functionsToProcess.push_back(root); - - InitResult result = INITDAG_SUCCESS; - - while (!functionsToProcess.empty()) + if (function->visiting) { - CreatorFunctionData *function = functionsToProcess.back(); - - if (function->visiting) - { - function->visiting = false; - function->index = mCurrentIndex++; - function->indexAssigned = true; - - functionsToProcess.pop_back(); - continue; - } - - if (!function->node) - { - *mCreationInfo << "Undefined function '" << function->name - << ")' used in the following call chain:"; - result = INITDAG_UNDEFINED; - break; - } - - if (function->indexAssigned) - { - functionsToProcess.pop_back(); - continue; - } - - function->visiting = true; - - for (auto callee : function->callees) + if (mCreationInfo) { - functionsToProcess.push_back(callee); - - // Check if the callee is already being visited after pushing it so that it appears - // in the chain printed in the info log. - if (callee->visiting) - { - *mCreationInfo << "Recursive function call in the following call chain:"; - result = INITDAG_RECURSION; - break; - } - } - - if (result != INITDAG_SUCCESS) - { - break; + *mCreationInfo << "Recursive function call in the following call chain:" << function->name; } + return INITDAG_RECURSION; } + function->visiting = true; - // The call chain is made of the function we were visiting when the error was detected. - if (result != INITDAG_SUCCESS) + for (auto &callee : function->callees) { - bool first = true; - for (auto function : functionsToProcess) + InitResult result = assignIndicesInternal(callee); + if (result != INITDAG_SUCCESS) { - if (function->visiting) + // We know that there is an issue with the call chain in the AST, + // print the link of the chain we were processing. + if (mCreationInfo) { - if (!first) - { - *mCreationInfo << " -> "; - } - *mCreationInfo << function->name << ")"; - first = false; + *mCreationInfo << " <- " << function->name << ")"; } + return result; } } - return result; + function->index = mCurrentIndex++; + function->indexAssigned = true; + + function->visiting = false; + return INITDAG_SUCCESS; } TInfoSinkBase *mCreationInfo; @@ -287,9 +232,13 @@ CallDAG::~CallDAG() const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max(); -size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const +size_t CallDAG::findIndex(const TIntermAggregate *function) const { - auto it = mFunctionIdToIndex.find(functionInfo->getId()); + TOperator op = function->getOp(); + ASSERT(op == EOpPrototype || op == EOpFunction || op == EOpFunctionCall); + UNUSED_ASSERTION_VARIABLE(op); + + auto it = mFunctionIdToIndex.find(function->getFunctionId()); if (it == mFunctionIdToIndex.end()) { @@ -309,7 +258,7 @@ const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const { - size_t index = findIndex(function->getFunctionSymbolInfo()); + size_t index = findIndex(function); ASSERT(index != InvalidIndex && index < mRecords.size()); return mRecords[index]; } @@ -327,8 +276,6 @@ void CallDAG::clear() CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info) { - ASSERT(info); - CallDAGCreator creator(info); // Creates the mapping of functions to callees @@ -344,5 +291,3 @@ CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info) creator.fillDataStructures(&mRecords, &mFunctionIdToIndex); return INITDAG_SUCCESS; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/CallDAG.h b/gfx/angle/src/compiler/translator/CallDAG.h index 90c056878..06c377db0 100755 --- a/gfx/angle/src/compiler/translator/CallDAG.h +++ b/gfx/angle/src/compiler/translator/CallDAG.h @@ -16,8 +16,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/VariableInfo.h" -namespace sh -{ // The translator needs to analyze the the graph of the function calls // to run checks and analyses; since in GLSL recursion is not allowed @@ -43,7 +41,7 @@ class CallDAG : angle::NonCopyable struct Record { std::string name; - TIntermFunctionDefinition *node; + TIntermAggregate *node; std::vector<int> callees; }; @@ -59,7 +57,7 @@ class CallDAG : angle::NonCopyable InitResult init(TIntermNode *root, TInfoSinkBase *info); // Returns InvalidIndex if the function wasn't found - size_t findIndex(const TFunctionSymbolInfo *functionInfo) const; + size_t findIndex(const TIntermAggregate *function) const; const Record &getRecordFromIndex(size_t index) const; const Record &getRecord(const TIntermAggregate *function) const; @@ -74,6 +72,4 @@ class CallDAG : angle::NonCopyable class CallDAGCreator; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_CALLDAG_H_ diff --git a/gfx/angle/src/compiler/translator/CodeGen.cpp b/gfx/angle/src/compiler/translator/CodeGen.cpp index 22f2afc98..f099bccf1 100755 --- a/gfx/angle/src/compiler/translator/CodeGen.cpp +++ b/gfx/angle/src/compiler/translator/CodeGen.cpp @@ -6,79 +6,71 @@ #ifdef ANGLE_ENABLE_ESSL #include "compiler/translator/TranslatorESSL.h" -#endif // ANGLE_ENABLE_ESSL +#endif #ifdef ANGLE_ENABLE_GLSL #include "compiler/translator/TranslatorGLSL.h" -#endif // ANGLE_ENABLE_GLSL +#endif #ifdef ANGLE_ENABLE_HLSL #include "compiler/translator/TranslatorHLSL.h" -#endif // ANGLE_ENABLE_HLSL - -namespace sh -{ +#endif // ANGLE_ENABLE_HLSL // // This function must be provided to create the actual // compile object used by higher level code. It returns // a subclass of TCompiler. // -TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) +TCompiler* ConstructCompiler( + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) { - switch (output) - { - case SH_ESSL_OUTPUT: + switch (output) { + case SH_ESSL_OUTPUT: #ifdef ANGLE_ENABLE_ESSL - return new TranslatorESSL(type, spec); + return new TranslatorESSL(type, spec); #else - // This compiler is not supported in this configuration. Return NULL per the - // sh::ConstructCompiler API. - return nullptr; -#endif // ANGLE_ENABLE_ESSL - - case SH_GLSL_130_OUTPUT: - case SH_GLSL_140_OUTPUT: - case SH_GLSL_150_CORE_OUTPUT: - case SH_GLSL_330_CORE_OUTPUT: - case SH_GLSL_400_CORE_OUTPUT: - case SH_GLSL_410_CORE_OUTPUT: - case SH_GLSL_420_CORE_OUTPUT: - case SH_GLSL_430_CORE_OUTPUT: - case SH_GLSL_440_CORE_OUTPUT: - case SH_GLSL_450_CORE_OUTPUT: - case SH_GLSL_COMPATIBILITY_OUTPUT: + // This compiler is not supported in this + // configuration. Return NULL per the ShConstructCompiler API. + return nullptr; +#endif // ANGLE_ENABLE_ESSL + case SH_GLSL_130_OUTPUT: + case SH_GLSL_140_OUTPUT: + case SH_GLSL_150_CORE_OUTPUT: + case SH_GLSL_330_CORE_OUTPUT: + case SH_GLSL_400_CORE_OUTPUT: + case SH_GLSL_410_CORE_OUTPUT: + case SH_GLSL_420_CORE_OUTPUT: + case SH_GLSL_430_CORE_OUTPUT: + case SH_GLSL_440_CORE_OUTPUT: + case SH_GLSL_450_CORE_OUTPUT: + case SH_GLSL_COMPATIBILITY_OUTPUT: #ifdef ANGLE_ENABLE_GLSL - return new TranslatorGLSL(type, spec, output); + return new TranslatorGLSL(type, spec, output); #else - // This compiler is not supported in this configuration. Return NULL per the - // sh::ConstructCompiler API. - return nullptr; -#endif // ANGLE_ENABLE_GLSL - - case SH_HLSL_3_0_OUTPUT: - case SH_HLSL_4_1_OUTPUT: - case SH_HLSL_4_0_FL9_3_OUTPUT: + // This compiler is not supported in this + // configuration. Return NULL per the ShConstructCompiler API. + return nullptr; +#endif // ANGLE_ENABLE_GLSL + case SH_HLSL_3_0_OUTPUT: + case SH_HLSL_4_1_OUTPUT: + case SH_HLSL_4_0_FL9_3_OUTPUT: #ifdef ANGLE_ENABLE_HLSL - return new TranslatorHLSL(type, spec, output); + return new TranslatorHLSL(type, spec, output); #else - // This compiler is not supported in this configuration. Return NULL per the - // sh::ConstructCompiler API. - return nullptr; -#endif // ANGLE_ENABLE_HLSL - - default: - // Unknown format. Return NULL per the sh::ConstructCompiler API. - return nullptr; + // This compiler is not supported in this + // configuration. Return NULL per the ShConstructCompiler API. + return nullptr; +#endif // ANGLE_ENABLE_HLSL + default: + // Unknown format. Return NULL per the ShConstructCompiler API. + return nullptr; } } // // Delete the compiler made by ConstructCompiler // -void DeleteCompiler(TCompiler *compiler) +void DeleteCompiler(TCompiler* compiler) { - SafeDelete(compiler); + delete compiler; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Common.h b/gfx/angle/src/compiler/translator/Common.h index 853317891..60223232a 100755 --- a/gfx/angle/src/compiler/translator/Common.h +++ b/gfx/angle/src/compiler/translator/Common.h @@ -18,9 +18,6 @@ #include "common/debug.h" #include "compiler/translator/PoolAlloc.h" -namespace sh -{ - struct TSourceLoc { int first_file; int first_line; @@ -95,6 +92,4 @@ inline TString str(T i) return buffer; } -} // namespace sh - #endif // COMPILER_TRANSLATOR_COMMON_H_ diff --git a/gfx/angle/src/compiler/translator/Compiler.cpp b/gfx/angle/src/compiler/translator/Compiler.cpp index e085ed588..0257dd3a7 100755 --- a/gfx/angle/src/compiler/translator/Compiler.cpp +++ b/gfx/angle/src/compiler/translator/Compiler.cpp @@ -4,18 +4,11 @@ // found in the LICENSE file. // -#include "compiler/translator/Compiler.h" - -#include <sstream> - -#include "angle_gl.h" -#include "common/utilities.h" -#include "compiler/translator/AddAndTrueToLoopCondition.h" #include "compiler/translator/Cache.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/CallDAG.h" #include "compiler/translator/DeferGlobalInitializers.h" #include "compiler/translator/EmulateGLFragColorBroadcast.h" -#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/ForLoopUnroll.h" #include "compiler/translator/Initialize.h" #include "compiler/translator/InitializeParseContext.h" @@ -23,100 +16,41 @@ #include "compiler/translator/ParseContext.h" #include "compiler/translator/PruneEmptyDeclarations.h" #include "compiler/translator/RegenerateStructNames.h" -#include "compiler/translator/RemoveInvariantDeclaration.h" #include "compiler/translator/RemovePow.h" +#include "compiler/translator/RenameFunction.h" #include "compiler/translator/RewriteDoWhile.h" #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/UnfoldShortCircuitAST.h" -#include "compiler/translator/UseInterfaceBlockFields.h" #include "compiler/translator/ValidateLimitations.h" #include "compiler/translator/ValidateMaxParameters.h" #include "compiler/translator/ValidateOutputs.h" #include "compiler/translator/VariablePacker.h" +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/timing/RestrictFragmentShaderTiming.h" +#include "compiler/translator/timing/RestrictVertexShaderTiming.h" #include "third_party/compiler/ArrayBoundsClamper.h" - -namespace sh -{ - -namespace -{ - -#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) -void DumpFuzzerCase(char const *const *shaderStrings, - size_t numStrings, - uint32_t type, - uint32_t spec, - uint32_t output, - uint64_t options) -{ - static int fileIndex = 0; - - std::ostringstream o; - o << "corpus/" << fileIndex++ << ".sample"; - std::string s = o.str(); - - // Must match the input format of the fuzzer - FILE *f = fopen(s.c_str(), "w"); - fwrite(&type, sizeof(type), 1, f); - fwrite(&spec, sizeof(spec), 1, f); - fwrite(&output, sizeof(output), 1, f); - fwrite(&options, sizeof(options), 1, f); - - char zero[128 - 20] = {0}; - fwrite(&zero, 128 - 20, 1, f); - - for (size_t i = 0; i < numStrings; i++) - { - fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f); - } - fwrite(&zero, 1, 1, f); - - fclose(f); -} -#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) -} // anonymous namespace +#include "angle_gl.h" +#include "common/utilities.h" bool IsWebGLBasedSpec(ShShaderSpec spec) { - return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC); + return (spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC || spec == SH_WEBGL2_SPEC || + spec == SH_WEBGL3_SPEC); } bool IsGLSL130OrNewer(ShShaderOutput output) { - return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || - output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || - output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT || - output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || - output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); -} - -bool IsGLSL420OrNewer(ShShaderOutput output) -{ - return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT || - output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT); -} - -bool IsGLSL410OrOlder(ShShaderOutput output) -{ - return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT || - output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT || - output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT); -} - -bool RemoveInvariant(sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput outputType, - ShCompileOptions compileOptions) -{ - if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 && - shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType)) - return true; - - if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 && - shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER && IsGLSL410OrOlder(outputType)) - return true; - - return false; + return (output == SH_GLSL_130_OUTPUT || + output == SH_GLSL_140_OUTPUT || + output == SH_GLSL_150_CORE_OUTPUT || + output == SH_GLSL_330_CORE_OUTPUT || + output == SH_GLSL_400_CORE_OUTPUT || + output == SH_GLSL_410_CORE_OUTPUT || + output == SH_GLSL_420_CORE_OUTPUT || + output == SH_GLSL_430_CORE_OUTPUT || + output == SH_GLSL_440_CORE_OUTPUT || + output == SH_GLSL_450_CORE_OUTPUT); } size_t GetGlobalMaxTokenSize(ShShaderSpec spec) @@ -125,10 +59,11 @@ size_t GetGlobalMaxTokenSize(ShShaderSpec spec) // size undefined. ES3 defines a max size of 1024 characters. switch (spec) { - case SH_WEBGL_SPEC: - return 256; - default: - return 1024; + case SH_WEBGL_SPEC: + case SH_CSS_SHADERS_SPEC: + return 256; + default: + return 1024; } } @@ -174,18 +109,19 @@ int MapSpecToShaderVersion(ShShaderSpec spec) { switch (spec) { - case SH_GLES2_SPEC: - case SH_WEBGL_SPEC: - return 100; - case SH_GLES3_SPEC: - case SH_WEBGL2_SPEC: - return 300; - case SH_GLES3_1_SPEC: - case SH_WEBGL3_SPEC: - return 310; - default: - UNREACHABLE(); - return 0; + case SH_GLES2_SPEC: + case SH_WEBGL_SPEC: + case SH_CSS_SHADERS_SPEC: + return 100; + case SH_GLES3_SPEC: + case SH_WEBGL2_SPEC: + return 300; + case SH_GLES3_1_SPEC: + case SH_WEBGL3_SPEC: + return 310; + default: + UNREACHABLE(); + return 0; } } @@ -226,7 +162,7 @@ TCompiler::~TCompiler() { } -bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const +bool TCompiler::shouldRunLoopAndIndexingValidation(int compileOptions) const { // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API, // validate loop and indexing as well (to verify that the shader only uses minimal functionality @@ -261,16 +197,15 @@ bool TCompiler::Init(const ShBuiltInResources& resources) return true; } -TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) +TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[], + size_t numStrings, int compileOptions) { return compileTreeImpl(shaderStrings, numStrings, compileOptions); } -TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, - const ShCompileOptions compileOptions) +TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[], + size_t numStrings, + const int compileOptions) { clearResults(); @@ -288,7 +223,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ++firstSource; } - TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec, + TIntermediate intermediate(infoSink); + TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec, compileOptions, true, infoSink, getResources()); parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh); @@ -311,7 +247,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], success = false; } - TIntermBlock *root = nullptr; + TIntermNode *root = nullptr; if (success) { @@ -322,6 +258,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize(); root = parseContext.getTreeRoot(); + root = intermediate.postProcess(root); // Highp might have been auto-enabled based on shader version fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh(); @@ -358,17 +295,11 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], if (success && shouldRunLoopAndIndexingValidation(compileOptions)) success = validateLimitations(root); - // Fail compilation if precision emulation not supported. - if (success && getResources().WEBGL_debug_shader_precision && - getPragma().debugShaderPrecision) - { - if (!EmulatePrecision::SupportedInLanguage(outputType)) - { - infoSink.info.prefix(EPrefixError); - infoSink.info << "Precision emulation not supported for this output type."; - success = false; - } - } + if (success && (compileOptions & SH_TIMING_RESTRICTIONS)) + success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0); + + if (success && shaderSpec == SH_CSS_SHADERS_SPEC) + rewriteCSSShader(root); // Unroll for-loop markup needs to happen after validateLimitations pass. if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) @@ -410,16 +341,10 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], (outputType == SH_GLSL_COMPATIBILITY_OUTPUT))) initializeGLPosition(root); - if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions)) - sh::RemoveInvariantDeclaration(root); - // This pass might emit short circuits so keep it before the short circuit unfolding if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)) RewriteDoWhile(root, getTemporaryIndex()); - if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)) - sh::AddAndTrueToLoopCondition(root); - if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)) { UnfoldShortCircuitAST unfoldShortCircuit; @@ -435,10 +360,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], if (success && shouldCollectVariables(compileOptions)) { collectVariables(root); - if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) - { - useAllMembersInUnusedStandardAndSharedBlocks(root); - } if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) { success = enforcePackingRestrictions(); @@ -456,8 +377,9 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) { - ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, - &mTemporaryIndex); + ScalarizeVecAndMatConstructorArgs scalarizer( + shaderType, fragmentPrecisionHigh); + root->traverse(&scalarizer); } if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES)) @@ -486,18 +408,12 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], return NULL; } -bool TCompiler::compile(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptionsIn) +bool TCompiler::compile(const char *const shaderStrings[], size_t numStrings, int compileOptionsIn) { -#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) - DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn); -#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT) - if (numStrings == 0) return true; - ShCompileOptions compileOptions = compileOptionsIn; + int compileOptions = compileOptionsIn; // Apply key workarounds. if (shouldFlattenPragmaStdglInvariantAll()) @@ -506,19 +422,8 @@ bool TCompiler::compile(const char *const shaderStrings[], compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL; } - ShCompileOptions unrollFlags = - SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX | SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX; - if ((compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) != 0 && - (compileOptions & unrollFlags) != 0) - { - infoSink.info.prefix(EPrefixError); - infoSink.info - << "Unsupported compile flag combination: unroll & ADD_TRUE_TO_LOOP_CONDITION"; - return false; - } - TScopedPoolAllocator scopedAlloc(&allocator); - TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); + TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); if (root) { @@ -547,26 +452,32 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) symbolTable.push(); // ESSL3_1_BUILTINS TPublicType integer; - integer.initializeBasicType(EbtInt); + integer.type = EbtInt; + integer.primarySize = 1; + integer.secondarySize = 1; + integer.array = false; TPublicType floatingPoint; - floatingPoint.initializeBasicType(EbtFloat); + floatingPoint.type = EbtFloat; + floatingPoint.primarySize = 1; + floatingPoint.secondarySize = 1; + floatingPoint.array = false; - switch (shaderType) + switch(shaderType) { - case GL_FRAGMENT_SHADER: - symbolTable.setDefaultPrecision(integer, EbpMedium); - break; - case GL_VERTEX_SHADER: - symbolTable.setDefaultPrecision(integer, EbpHigh); - symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); - break; - case GL_COMPUTE_SHADER: - symbolTable.setDefaultPrecision(integer, EbpHigh); - symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); - break; - default: - assert(false && "Language not supported"); + case GL_FRAGMENT_SHADER: + symbolTable.setDefaultPrecision(integer, EbpMedium); + break; + case GL_VERTEX_SHADER: + symbolTable.setDefaultPrecision(integer, EbpHigh); + symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); + break; + case GL_COMPUTE_SHADER: + symbolTable.setDefaultPrecision(integer, EbpHigh); + symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); + break; + default: + assert(false && "Language not supported"); } // Set defaults for sampler types that have default precision, even those that are // only available if an extension exists. @@ -589,7 +500,10 @@ void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType) { ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd); TPublicType sampler; - sampler.initializeBasicType(samplerType); + sampler.primarySize = 1; + sampler.secondarySize = 1; + sampler.array = false; + sampler.type = samplerType; symbolTable.setDefaultPrecision(sampler, EbpLow); } @@ -599,60 +513,60 @@ void TCompiler::setResourceString() // clang-format off strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs - << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors - << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors - << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits - << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits - << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits - << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors - << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers - << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives - << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external - << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3 - << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external - << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle - << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers - << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh - << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity - << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth - << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters - << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended - << ":EXT_frag_depth:" << compileResources.EXT_frag_depth - << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod - << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch - << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch - << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch - << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors - << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors - << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset - << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset - << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers - << ":NV_draw_buffers:" << compileResources.NV_draw_buffers - << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision - << ":MaxImageUnits:" << compileResources.MaxImageUnits - << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms - << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms - << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms - << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms - << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources - << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0] - << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1] - << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2] - << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0] - << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1] - << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2] - << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents - << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits - << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters - << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers - << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters - << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters - << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters - << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings - << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers - << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers - << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers - << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize; + << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors + << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors + << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits + << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits + << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits + << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors + << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers + << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives + << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external + << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3 + << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external + << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle + << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers + << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh + << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity + << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth + << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters + << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended + << ":EXT_frag_depth:" << compileResources.EXT_frag_depth + << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod + << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch + << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch + << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch + << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors + << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors + << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset + << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset + << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers + << ":NV_draw_buffers:" << compileResources.NV_draw_buffers + << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision + << ":MaxImageUnits:" << compileResources.MaxImageUnits + << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms + << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms + << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms + << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms + << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources + << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0] + << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1] + << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2] + << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0] + << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1] + << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2] + << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents + << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits + << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters + << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers + << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters + << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters + << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters + << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings + << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers + << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers + << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers + << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize; // clang-format on builtInResourcesString = strstream.str(); @@ -687,16 +601,16 @@ bool TCompiler::initCallDag(TIntermNode *root) switch (mCallDag.init(root, &infoSink.info)) { - case CallDAG::INITDAG_SUCCESS: - return true; - case CallDAG::INITDAG_RECURSION: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function recursion detected"; - return false; - case CallDAG::INITDAG_UNDEFINED: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Unimplemented function detected"; - return false; + case CallDAG::INITDAG_SUCCESS: + return true; + case CallDAG::INITDAG_RECURSION: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; + return false; + case CallDAG::INITDAG_UNDEFINED: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Unimplemented function detected"; + return false; } UNREACHABLE(); @@ -790,38 +704,30 @@ class TCompiler::UnusedPredicate { public: UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas) - : mCallDag(callDag), mMetadatas(metadatas) + : mCallDag(callDag), + mMetadatas(metadatas) { } bool operator ()(TIntermNode *node) { const TIntermAggregate *asAggregate = node->getAsAggregate(); - const TIntermFunctionDefinition *asFunction = node->getAsFunctionDefinition(); - - const TFunctionSymbolInfo *functionInfo = nullptr; - if (asFunction) + if (asAggregate == nullptr) { - functionInfo = asFunction->getFunctionSymbolInfo(); - } - else if (asAggregate) - { - if (asAggregate->getOp() == EOpPrototype) - { - functionInfo = asAggregate->getFunctionSymbolInfo(); - } + return false; } - if (functionInfo == nullptr) + + if (!(asAggregate->getOp() == EOpFunction || asAggregate->getOp() == EOpPrototype)) { return false; } - size_t callDagIndex = mCallDag->findIndex(functionInfo); + size_t callDagIndex = mCallDag->findIndex(asAggregate); if (callDagIndex == CallDAG::InvalidIndex) { // This happens only for unimplemented prototypes which are thus unused - ASSERT(asAggregate && asAggregate->getOp() == EOpPrototype); + ASSERT(asAggregate->getOp() == EOpPrototype); return true; } @@ -834,10 +740,13 @@ class TCompiler::UnusedPredicate const std::vector<FunctionMetadata> *mMetadatas; }; -bool TCompiler::pruneUnusedFunctions(TIntermBlock *root) +bool TCompiler::pruneUnusedFunctions(TIntermNode *root) { + TIntermAggregate *rootNode = root->getAsAggregate(); + ASSERT(rootNode != nullptr); + UnusedPredicate isUnused(&mCallDag, &functionMetadata); - TIntermSequence *sequence = root->getSequence(); + TIntermSequence *sequence = rootNode->getSequence(); if (!sequence->empty()) { @@ -854,6 +763,12 @@ bool TCompiler::validateOutputs(TIntermNode* root) return (validateOutputs.validateAndCountErrors(infoSink.info) == 0); } +void TCompiler::rewriteCSSShader(TIntermNode* root) +{ + RenameFunction renamer("main(", "css_main("); + root->traverse(&renamer); +} + bool TCompiler::validateLimitations(TIntermNode* root) { ValidateLimitations validate(shaderType, &infoSink.info); @@ -861,9 +776,39 @@ bool TCompiler::validateLimitations(TIntermNode* root) return validate.numErrors() == 0; } +bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) +{ + if (shaderSpec != SH_WEBGL_SPEC) + { + infoSink.info << "Timing restrictions must be enforced under the WebGL spec."; + return false; + } + + if (shaderType == GL_FRAGMENT_SHADER) + { + TDependencyGraph graph(root); + + // Output any errors first. + bool success = enforceFragmentShaderTimingRestrictions(graph); + + // Then, output the dependency graph. + if (outputGraph) + { + TDependencyGraphOutput output(infoSink.info); + output.outputAllSpanningTrees(graph); + } + + return success; + } + else + { + return enforceVertexShaderTimingRestrictions(root); + } +} + bool TCompiler::limitExpressionComplexity(TIntermNode* root) { - TMaxDepthTraverser traverser(maxExpressionComplexity + 1); + TMaxDepthTraverser traverser(maxExpressionComplexity+1); root->traverse(&traverser); if (traverser.getMaxDepth() > maxExpressionComplexity) @@ -881,13 +826,26 @@ bool TCompiler::limitExpressionComplexity(TIntermNode* root) return true; } +bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph) +{ + RestrictFragmentShaderTiming restrictor(infoSink.info); + restrictor.enforceRestrictions(graph); + return restrictor.numErrors() == 0; +} + +bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) +{ + RestrictVertexShaderTiming restrictor(infoSink.info); + restrictor.enforceRestrictions(root); + return restrictor.numErrors() == 0; +} + void TCompiler::collectVariables(TIntermNode* root) { if (!variablesCollected) { sh::CollectVariables collect(&attributes, &outputVariables, &uniforms, &varyings, - &interfaceBlocks, hashFunction, symbolTable, - extensionBehavior); + &interfaceBlocks, hashFunction, symbolTable, extensionBehavior); root->traverse(&collect); // This is for enforcePackingRestriction(). @@ -896,16 +854,6 @@ void TCompiler::collectVariables(TIntermNode* root) } } -bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions) -{ - return (compileOptions & SH_VARIABLES) != 0; -} - -bool TCompiler::wereVariablesCollected() const -{ - return variablesCollected; -} - bool TCompiler::enforcePackingRestrictions() { VariablePacker packer; @@ -918,23 +866,7 @@ void TCompiler::initializeGLPosition(TIntermNode* root) sh::ShaderVariable var(GL_FLOAT_VEC4, 0); var.name = "gl_Position"; list.push_back(var); - InitializeVariables(root, list, symbolTable); -} - -void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermNode *root) -{ - sh::InterfaceBlockList list; - - for (auto block : interfaceBlocks) - { - if (!block.staticUse && - (block.layout == sh::BLOCKLAYOUT_STANDARD || block.layout == sh::BLOCKLAYOUT_SHARED)) - { - list.push_back(block); - } - } - - sh::UseInterfaceBlockFields(root, list, symbolTable); + InitializeVariables(root, list); } void TCompiler::initializeOutputVariables(TIntermNode *root) @@ -955,7 +887,7 @@ void TCompiler::initializeOutputVariables(TIntermNode *root) list.push_back(var); } } - InitializeVariables(root, list, symbolTable); + InitializeVariables(root, list); } const TExtensionBehavior& TCompiler::getExtensionBehavior() const @@ -988,7 +920,7 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const return builtInFunctionEmulator; } -void TCompiler::writePragma(ShCompileOptions compileOptions) +void TCompiler::writePragma(int compileOptions) { if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL)) { @@ -1011,5 +943,3 @@ bool TCompiler::isVaryingDefined(const char *varyingName) return false; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Compiler.h b/gfx/angle/src/compiler/translator/Compiler.h index 42b4f8f06..6b682374b 100755 --- a/gfx/angle/src/compiler/translator/Compiler.h +++ b/gfx/angle/src/compiler/translator/Compiler.h @@ -24,16 +24,15 @@ #include "compiler/translator/VariableInfo.h" #include "third_party/compiler/ArrayBoundsClamper.h" -namespace sh -{ - class TCompiler; +class TDependencyGraph; #ifdef ANGLE_ENABLE_HLSL class TranslatorHLSL; #endif // ANGLE_ENABLE_HLSL // -// Helper function to identify specs that are based on the WebGL spec. +// Helper function to identify specs that are based on the WebGL spec, +// like the CSS Shaders spec. // bool IsWebGLBasedSpec(ShShaderSpec spec); @@ -41,16 +40,6 @@ bool IsWebGLBasedSpec(ShShaderSpec spec); // Helper function to check if the shader type is GLSL. // bool IsGLSL130OrNewer(ShShaderOutput output); -bool IsGLSL420OrNewer(ShShaderOutput output); -bool IsGLSL410OrOlder(ShShaderOutput output); - -// -// Helper function to check if the invariant qualifier can be removed. -// -bool RemoveInvariant(sh::GLenum shaderType, - int shaderVersion, - ShShaderOutput outputType, - ShCompileOptions compileOptions); // // The base class used to back handles returned to the driver. @@ -85,14 +74,12 @@ class TCompiler : public TShHandleBase // compileTreeForTesting should be used only when tests require access to // the AST. Users of this function need to manually manage the global pool - // allocator. Returns nullptr whenever there are compilation errors. - TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions); + // allocator. Returns NULL whenever there are compilation errors. + TIntermNode *compileTreeForTesting(const char* const shaderStrings[], + size_t numStrings, int compileOptions); - bool compile(const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions); + bool compile(const char* const shaderStrings[], + size_t numStrings, int compileOptions); // Get results of the last compilation. int getShaderVersion() const { return shaderVersion; } @@ -117,7 +104,7 @@ class TCompiler : public TShHandleBase ShShaderOutput getOutputType() const { return outputType; } const std::string &getBuiltInResourcesString() const { return builtInResourcesString; } - bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const; + bool shouldRunLoopAndIndexingValidation(int compileOptions) const; // Get the resources set by InitBuiltInSymbolTable const ShBuiltInResources& getResources() const; @@ -132,21 +119,20 @@ class TCompiler : public TShHandleBase bool checkCallDepth(); // Returns true if a program has no conflicting or missing fragment outputs bool validateOutputs(TIntermNode* root); + // Rewrites a shader's intermediate tree according to the CSS Shaders spec. + void rewriteCSSShader(TIntermNode* root); // Returns true if the given shader does not exceed the minimum // functionality mandated in GLSL 1.0 spec Appendix A. bool validateLimitations(TIntermNode* root); + // Collect info for all attribs, uniforms, varyings. + void collectVariables(TIntermNode* root); // Add emulated functions to the built-in function emulator. - virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions){}; + virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {}; // Translate to object code. - virtual void translate(TIntermNode *root, ShCompileOptions compileOptions) = 0; + virtual void translate(TIntermNode *root, int compileOptions) = 0; // Returns true if, after applying the packing rules in the GLSL 1.017 spec // Appendix A, section 7, the shader does not use too many uniforms. bool enforcePackingRestrictions(); - // Insert statements to reference all members in unused uniform blocks with standard and shared - // layout. This is to work around a Mac driver that treats unused standard/shared - // uniform blocks as inactive. - void useAllMembersInUnusedStandardAndSharedBlocks(TIntermNode *root); // Insert statements to initialize output variables in the beginning of main(). // This is to avoid undefined behaviors. void initializeOutputVariables(TIntermNode *root); @@ -155,13 +141,20 @@ class TCompiler : public TShHandleBase // while spec says it is allowed. // This function should only be applied to vertex shaders. void initializeGLPosition(TIntermNode* root); + // Returns true if the shader passes the restrictions that aim to prevent timing attacks. + bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); + // Returns true if the shader does not use samplers. + bool enforceVertexShaderTimingRestrictions(TIntermNode* root); + // Returns true if the shader does not use sampler dependent values to affect control + // flow or in operations whose time can depend on the input values. + bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); // Return true if the maximum expression complexity is below the limit. bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; const char *getSourcePath() const; const TPragma& getPragma() const { return mPragma; } - void writePragma(ShCompileOptions compileOptions); + void writePragma(int compileOptions); unsigned int *getTemporaryIndex() { return &mTemporaryIndex; } // Relies on collectVariables having been called. bool isVaryingDefined(const char *varyingName); @@ -170,16 +163,20 @@ class TCompiler : public TShHandleBase ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; + virtual bool shouldCollectVariables(int compileOptions) + { + return (compileOptions & SH_VARIABLES) != 0; + } + virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; - virtual bool shouldCollectVariables(ShCompileOptions compileOptions); - bool wereVariablesCollected() const; std::vector<sh::Attribute> attributes; std::vector<sh::OutputVariable> outputVariables; std::vector<sh::Uniform> uniforms; std::vector<sh::ShaderVariable> expandedUniforms; std::vector<sh::Varying> varyings; std::vector<sh::InterfaceBlock> interfaceBlocks; + bool variablesCollected; private: // Creates the function call DAG for further analysis, returning false if there is a recursion @@ -190,18 +187,13 @@ class TCompiler : public TShHandleBase void initSamplerDefaultPrecision(TBasicType samplerType); - // Collect info for all attribs, uniforms, varyings. - void collectVariables(TIntermNode *root); - - bool variablesCollected; - // Removes unused function declarations and prototypes from the AST class UnusedPredicate; - bool pruneUnusedFunctions(TIntermBlock *root); + bool pruneUnusedFunctions(TIntermNode *root); - TIntermBlock *compileTreeImpl(const char *const shaderStrings[], - size_t numStrings, - const ShCompileOptions compileOptions); + TIntermNode *compileTreeImpl(const char *const shaderStrings[], + size_t numStrings, + const int compileOptions); sh::GLenum shaderType; ShShaderSpec shaderSpec; @@ -269,6 +261,4 @@ TCompiler* ConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); void DeleteCompiler(TCompiler*); -} // namespace sh - #endif // COMPILER_TRANSLATOR_COMPILER_H_ diff --git a/gfx/angle/src/compiler/translator/ConstantUnion.cpp b/gfx/angle/src/compiler/translator/ConstantUnion.cpp deleted file mode 100644 index 66f444b0b..000000000 --- a/gfx/angle/src/compiler/translator/ConstantUnion.cpp +++ /dev/null @@ -1,642 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// ConstantUnion: Constant folding helper class. - -#include "compiler/translator/ConstantUnion.h" - -#include "base/numerics/safe_math.h" -#include "common/mathutil.h" -#include "compiler/translator/Diagnostics.h" - -namespace sh -{ - -namespace -{ - -template <typename T> -T CheckedSum(base::CheckedNumeric<T> lhs, - base::CheckedNumeric<T> rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - ASSERT(lhs.IsValid() && rhs.IsValid()); - auto result = lhs + rhs; - if (!result.IsValid()) - { - diag->error(line, "Addition out of range", "*", ""); - return 0; - } - return result.ValueOrDefault(0); -} - -template <typename T> -T CheckedDiff(base::CheckedNumeric<T> lhs, - base::CheckedNumeric<T> rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - ASSERT(lhs.IsValid() && rhs.IsValid()); - auto result = lhs - rhs; - if (!result.IsValid()) - { - diag->error(line, "Difference out of range", "*", ""); - return 0; - } - return result.ValueOrDefault(0); -} - -template <typename T> -T CheckedMul(base::CheckedNumeric<T> lhs, - base::CheckedNumeric<T> rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - ASSERT(lhs.IsValid() && rhs.IsValid()); - auto result = lhs * rhs; - if (!result.IsValid()) - { - diag->error(line, "Multiplication out of range", "*", ""); - return 0; - } - return result.ValueOrDefault(0); -} - -} // anonymous namespace - -TConstantUnion::TConstantUnion() -{ - iConst = 0; - type = EbtVoid; -} - -bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant) -{ - switch (newType) - { - case EbtFloat: - switch (constant.type) - { - case EbtInt: - setFConst(static_cast<float>(constant.getIConst())); - break; - case EbtUInt: - setFConst(static_cast<float>(constant.getUConst())); - break; - case EbtBool: - setFConst(static_cast<float>(constant.getBConst())); - break; - case EbtFloat: - setFConst(static_cast<float>(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtInt: - switch (constant.type) - { - case EbtInt: - setIConst(static_cast<int>(constant.getIConst())); - break; - case EbtUInt: - setIConst(static_cast<int>(constant.getUConst())); - break; - case EbtBool: - setIConst(static_cast<int>(constant.getBConst())); - break; - case EbtFloat: - setIConst(static_cast<int>(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtUInt: - switch (constant.type) - { - case EbtInt: - setUConst(static_cast<unsigned int>(constant.getIConst())); - break; - case EbtUInt: - setUConst(static_cast<unsigned int>(constant.getUConst())); - break; - case EbtBool: - setUConst(static_cast<unsigned int>(constant.getBConst())); - break; - case EbtFloat: - setUConst(static_cast<unsigned int>(constant.getFConst())); - break; - default: - return false; - } - break; - case EbtBool: - switch (constant.type) - { - case EbtInt: - setBConst(constant.getIConst() != 0); - break; - case EbtUInt: - setBConst(constant.getUConst() != 0); - break; - case EbtBool: - setBConst(constant.getBConst()); - break; - case EbtFloat: - setBConst(constant.getFConst() != 0.0f); - break; - default: - return false; - } - break; - case EbtStruct: // Struct fields don't get cast - switch (constant.type) - { - case EbtInt: - setIConst(constant.getIConst()); - break; - case EbtUInt: - setUConst(constant.getUConst()); - break; - case EbtBool: - setBConst(constant.getBConst()); - break; - case EbtFloat: - setFConst(constant.getFConst()); - break; - default: - return false; - } - break; - default: - return false; - } - - return true; -} - -bool TConstantUnion::operator==(const int i) const -{ - return i == iConst; -} - -bool TConstantUnion::operator==(const unsigned int u) const -{ - return u == uConst; -} - -bool TConstantUnion::operator==(const float f) const -{ - return f == fConst; -} - -bool TConstantUnion::operator==(const bool b) const -{ - return b == bConst; -} - -bool TConstantUnion::operator==(const TConstantUnion &constant) const -{ - if (constant.type != type) - return false; - - switch (type) - { - case EbtInt: - return constant.iConst == iConst; - case EbtUInt: - return constant.uConst == uConst; - case EbtFloat: - return constant.fConst == fConst; - case EbtBool: - return constant.bConst == bConst; - default: - return false; - } -} - -bool TConstantUnion::operator!=(const int i) const -{ - return !operator==(i); -} - -bool TConstantUnion::operator!=(const unsigned int u) const -{ - return !operator==(u); -} - -bool TConstantUnion::operator!=(const float f) const -{ - return !operator==(f); -} - -bool TConstantUnion::operator!=(const bool b) const -{ - return !operator==(b); -} - -bool TConstantUnion::operator!=(const TConstantUnion &constant) const -{ - return !operator==(constant); -} - -bool TConstantUnion::operator>(const TConstantUnion &constant) const -{ - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - return iConst > constant.iConst; - case EbtUInt: - return uConst > constant.uConst; - case EbtFloat: - return fConst > constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } -} - -bool TConstantUnion::operator<(const TConstantUnion &constant) const -{ - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - return iConst < constant.iConst; - case EbtUInt: - return uConst < constant.uConst; - case EbtFloat: - return fConst < constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } -} - -// static -TConstantUnion TConstantUnion::add(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst)); - break; - case EbtFloat: - returnValue.setFConst(CheckedSum<float>(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst)); - break; - case EbtFloat: - returnValue.setFConst(CheckedDiff<float>(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == rhs.type); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst)); - break; - case EbtUInt: - // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that - // to implement wrapping multiplication. - returnValue.setUConst(lhs.uConst * rhs.uConst); - break; - case EbtFloat: - returnValue.setFConst(CheckedMul<float>(lhs.fConst, rhs.fConst, diag, line)); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst % constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst % constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -// static -TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); - ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); - if ((rhs.type == EbtInt && (rhs.iConst < 0 || rhs.iConst > 31)) || - (rhs.type == EbtUInt && rhs.uConst > 31u)) - { - diag->error(line, "Undefined shift (operand out of range)", ">>", ""); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(0); - break; - case EbtUInt: - returnValue.setUConst(0u); - break; - default: - UNREACHABLE(); - } - return returnValue; - } - - switch (lhs.type) - { - case EbtInt: - { - unsigned int shiftOffset = 0; - switch (rhs.type) - { - case EbtInt: - shiftOffset = static_cast<unsigned int>(rhs.iConst); - break; - case EbtUInt: - shiftOffset = rhs.uConst; - break; - default: - UNREACHABLE(); - } - if (shiftOffset > 0) - { - // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend - // the sign bit." In C++ shifting negative integers is undefined, so we implement - // extending the sign bit manually. - int lhsSafe = lhs.iConst; - if (lhsSafe == std::numeric_limits<int>::min()) - { - // The min integer needs special treatment because only bit it has set is the - // sign bit, which we clear later to implement safe right shift of negative - // numbers. - lhsSafe = -0x40000000; - --shiftOffset; - } - if (shiftOffset > 0) - { - bool extendSignBit = false; - if (lhsSafe < 0) - { - extendSignBit = true; - // Clear the sign bit so that bitshift right is defined in C++. - lhsSafe &= 0x7fffffff; - ASSERT(lhsSafe > 0); - } - returnValue.setIConst(lhsSafe >> shiftOffset); - - // Manually fill in the extended sign bit if necessary. - if (extendSignBit) - { - int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset)); - returnValue.setIConst(returnValue.getIConst() | extendedSignBit); - } - } - else - { - returnValue.setIConst(lhsSafe); - } - } - else - { - returnValue.setIConst(lhs.iConst); - } - break; - } - case EbtUInt: - switch (rhs.type) - { - case EbtInt: - returnValue.setUConst(lhs.uConst >> rhs.iConst); - break; - case EbtUInt: - returnValue.setUConst(lhs.uConst >> rhs.uConst); - break; - default: - UNREACHABLE(); - } - break; - - default: - UNREACHABLE(); - } - return returnValue; -} - -// static -TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line) -{ - TConstantUnion returnValue; - ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt); - ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt); - if ((rhs.type == EbtInt && (rhs.iConst < 0 || rhs.iConst > 31)) || - (rhs.type == EbtUInt && rhs.uConst > 31u)) - { - diag->error(line, "Undefined shift (operand out of range)", "<<", ""); - switch (lhs.type) - { - case EbtInt: - returnValue.setIConst(0); - break; - case EbtUInt: - returnValue.setUConst(0u); - break; - default: - UNREACHABLE(); - } - return returnValue; - } - - switch (lhs.type) - { - case EbtInt: - switch (rhs.type) - { - // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that - // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed - // integer overflow or undefined shift of a negative integer. - case EbtInt: - returnValue.setIConst( - static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst)); - break; - case EbtUInt: - returnValue.setIConst( - static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst)); - break; - default: - UNREACHABLE(); - } - break; - - case EbtUInt: - switch (rhs.type) - { - case EbtInt: - returnValue.setUConst(lhs.uConst << rhs.iConst); - break; - case EbtUInt: - returnValue.setUConst(lhs.uConst << rhs.uConst); - break; - default: - UNREACHABLE(); - } - break; - - default: - UNREACHABLE(); - } - return returnValue; -} - -TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(constant.type == EbtInt || constant.type == EbtUInt); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst & constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst & constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst | constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst | constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtInt: - returnValue.setIConst(iConst ^ constant.iConst); - break; - case EbtUInt: - returnValue.setUConst(uConst ^ constant.uConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtBool: - returnValue.setBConst(bConst && constant.bConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const -{ - TConstantUnion returnValue; - ASSERT(type == constant.type); - switch (type) - { - case EbtBool: - returnValue.setBConst(bConst || constant.bConst); - break; - default: - UNREACHABLE(); - } - - return returnValue; -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ConstantUnion.h b/gfx/angle/src/compiler/translator/ConstantUnion.h index f6222ce5a..a86d27f3f 100755 --- a/gfx/angle/src/compiler/translator/ConstantUnion.h +++ b/gfx/angle/src/compiler/translator/ConstantUnion.h @@ -9,21 +9,77 @@ #include <assert.h> -#include "compiler/translator/Common.h" #include "compiler/translator/BaseTypes.h" -namespace sh -{ - -class TDiagnostics; - -class TConstantUnion -{ - public: +class TConstantUnion { +public: POOL_ALLOCATOR_NEW_DELETE(); - TConstantUnion(); + TConstantUnion() + { + iConst = 0; + type = EbtVoid; + } + + bool cast(TBasicType newType, const TConstantUnion &constant) + { + switch (newType) + { + case EbtFloat: + switch (constant.type) + { + case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break; + case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break; + case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break; + case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break; + default: return false; + } + break; + case EbtInt: + switch (constant.type) + { + case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break; + case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break; + case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break; + case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break; + default: return false; + } + break; + case EbtUInt: + switch (constant.type) + { + case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break; + case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break; + case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break; + case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break; + default: return false; + } + break; + case EbtBool: + switch (constant.type) + { + case EbtInt: setBConst(constant.getIConst() != 0); break; + case EbtUInt: setBConst(constant.getUConst() != 0); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; + default: return false; + } + break; + case EbtStruct: // Struct fields don't get cast + switch (constant.type) + { + case EbtInt: setIConst(constant.getIConst()); break; + case EbtUInt: setUConst(constant.getUConst()); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setFConst(constant.getFConst()); break; + default: return false; + } + break; + default: + return false; + } - bool cast(TBasicType newType, const TConstantUnion &constant); + return true; + } void setIConst(int i) {iConst = i; type = EbtInt; } void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } @@ -35,57 +91,258 @@ class TConstantUnion float getFConst() const { return fConst; } bool getBConst() const { return bConst; } - bool operator==(const int i) const; - bool operator==(const unsigned int u) const; - bool operator==(const float f) const; - bool operator==(const bool b) const; - bool operator==(const TConstantUnion &constant) const; - bool operator!=(const int i) const; - bool operator!=(const unsigned int u) const; - bool operator!=(const float f) const; - bool operator!=(const bool b) const; - bool operator!=(const TConstantUnion &constant) const; - bool operator>(const TConstantUnion &constant) const; - bool operator<(const TConstantUnion &constant) const; - static TConstantUnion add(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion sub(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion mul(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - TConstantUnion operator%(const TConstantUnion &constant) const; - static TConstantUnion rshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - static TConstantUnion lshift(const TConstantUnion &lhs, - const TConstantUnion &rhs, - TDiagnostics *diag, - const TSourceLoc &line); - TConstantUnion operator&(const TConstantUnion &constant) const; - TConstantUnion operator|(const TConstantUnion &constant) const; - TConstantUnion operator^(const TConstantUnion &constant) const; - TConstantUnion operator&&(const TConstantUnion &constant) const; - TConstantUnion operator||(const TConstantUnion &constant) const; + bool operator==(const int i) const + { + return i == iConst; + } + + bool operator==(const unsigned int u) const + { + return u == uConst; + } + + bool operator==(const float f) const + { + return f == fConst; + } + + bool operator==(const bool b) const + { + return b == bConst; + } + + bool operator==(const TConstantUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + return constant.iConst == iConst; + case EbtUInt: + return constant.uConst == uConst; + case EbtFloat: + return constant.fConst == fConst; + case EbtBool: + return constant.bConst == bConst; + default: + return false; + } + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const TConstantUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const TConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst > constant.iConst; + case EbtUInt: + return uConst > constant.uConst; + case EbtFloat: + return fConst > constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + } + + bool operator<(const TConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst < constant.iConst; + case EbtUInt: + return uConst < constant.uConst; + case EbtFloat: + return fConst < constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } + } + + TConstantUnion operator+(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; + case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator-(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; + case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator*(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; + case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator%(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator>>(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator<<(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + // The signedness of the second parameter might be different, but we + // don't care, since the result is undefined if the second parameter is + // negative, and aliasing should not be a problem with unions. + assert(constant.type == EbtInt || constant.type == EbtUInt); + switch (type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator&(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(constant.type == EbtInt || constant.type == EbtUInt); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator|(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator^(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator&&(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstantUnion operator||(const TConstantUnion& constant) const + { + TConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } TBasicType getType() const { return type; } - private: - union { - int iConst; // used for ivec, scalar ints - unsigned int uConst; // used for uvec, scalar uints - bool bConst; // used for bvec, scalar bools - float fConst; // used for vec, mat, scalar floats - }; +private: + + union { + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + bool bConst; // used for bvec, scalar bools + float fConst; // used for vec, mat, scalar floats + } ; TBasicType type; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_ diff --git a/gfx/angle/src/compiler/translator/DeferGlobalInitializers.cpp b/gfx/angle/src/compiler/translator/DeferGlobalInitializers.cpp index 1c58562fc..76addf293 100755 --- a/gfx/angle/src/compiler/translator/DeferGlobalInitializers.cpp +++ b/gfx/angle/src/compiler/translator/DeferGlobalInitializers.cpp @@ -15,43 +15,42 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - namespace { -void SetInternalFunctionName(TFunctionSymbolInfo *functionInfo, const char *name) +void SetInternalFunctionName(TIntermAggregate *functionNode, const char *name) { TString nameStr(name); nameStr = TFunction::mangleName(nameStr); TName nameObj(nameStr); nameObj.setInternal(true); - functionInfo->setNameObj(nameObj); + functionNode->setNameObj(nameObj); } TIntermAggregate *CreateFunctionPrototypeNode(const char *name, const int functionId) { TIntermAggregate *functionNode = new TIntermAggregate(EOpPrototype); - SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name); + SetInternalFunctionName(functionNode, name); TType returnType(EbtVoid); functionNode->setType(returnType); - functionNode->getFunctionSymbolInfo()->setId(functionId); + functionNode->setFunctionId(functionId); return functionNode; } -TIntermFunctionDefinition *CreateFunctionDefinitionNode(const char *name, - TIntermBlock *functionBody, - const int functionId) +TIntermAggregate *CreateFunctionDefinitionNode(const char *name, + TIntermAggregate *functionBody, + const int functionId) { - TType returnType(EbtVoid); + TIntermAggregate *functionNode = new TIntermAggregate(EOpFunction); TIntermAggregate *paramsNode = new TIntermAggregate(EOpParameters); - TIntermFunctionDefinition *functionNode = - new TIntermFunctionDefinition(returnType, paramsNode, functionBody); + functionNode->getSequence()->push_back(paramsNode); + functionNode->getSequence()->push_back(functionBody); - SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name); - functionNode->getFunctionSymbolInfo()->setId(functionId); + SetInternalFunctionName(functionNode, name); + TType returnType(EbtVoid); + functionNode->setType(returnType); + functionNode->setFunctionId(functionId); return functionNode; } @@ -60,10 +59,10 @@ TIntermAggregate *CreateFunctionCallNode(const char *name, const int functionId) TIntermAggregate *functionNode = new TIntermAggregate(EOpFunctionCall); functionNode->setUserDefined(); - SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name); + SetInternalFunctionName(functionNode, name); TType returnType(EbtVoid); functionNode->setType(returnType); - functionNode->getFunctionSymbolInfo()->setId(functionId); + functionNode->setFunctionId(functionId); return functionNode; } @@ -74,7 +73,7 @@ class DeferGlobalInitializersTraverser : public TIntermTraverser bool visitBinary(Visit visit, TIntermBinary *node) override; - void insertInitFunction(TIntermBlock *root); + void insertInitFunction(TIntermNode *root); private: TIntermSequence mDeferredInitializers; @@ -102,8 +101,10 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n // Deferral is done also in any cases where the variable has not been constant folded, // since otherwise there's a chance that HLSL output will generate extra statements // from the initializer expression. - TIntermBinary *deferredInit = - new TIntermBinary(EOpAssign, symbolNode->deepCopy(), node->getRight()); + TIntermBinary *deferredInit = new TIntermBinary(EOpAssign); + deferredInit->setLeft(symbolNode->deepCopy()); + deferredInit->setRight(node->getRight()); + deferredInit->setType(node->getType()); mDeferredInitializers.push_back(deferredInit); // Change const global to a regular global if its initialization is deferred. @@ -114,7 +115,7 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n if (symbolNode->getQualifier() == EvqConst) { // All of the siblings in the same declaration need to have consistent qualifiers. - auto *siblings = getParentNode()->getAsDeclarationNode()->getSequence(); + auto *siblings = getParentNode()->getAsAggregate()->getSequence(); for (TIntermNode *siblingNode : *siblings) { TIntermBinary *siblingBinary = siblingNode->getAsBinaryNode(); @@ -135,51 +136,56 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n return false; } -void DeferGlobalInitializersTraverser::insertInitFunction(TIntermBlock *root) +void DeferGlobalInitializersTraverser::insertInitFunction(TIntermNode *root) { if (mDeferredInitializers.empty()) { return; } const int initFunctionId = TSymbolTable::nextUniqueId(); + TIntermAggregate *rootAgg = root->getAsAggregate(); + ASSERT(rootAgg != nullptr && rootAgg->getOp() == EOpSequence); const char *functionName = "initializeDeferredGlobals"; // Add function prototype to the beginning of the shader TIntermAggregate *functionPrototypeNode = CreateFunctionPrototypeNode(functionName, initFunctionId); - root->getSequence()->insert(root->getSequence()->begin(), functionPrototypeNode); + rootAgg->getSequence()->insert(rootAgg->getSequence()->begin(), functionPrototypeNode); // Add function definition to the end of the shader - TIntermBlock *functionBodyNode = new TIntermBlock(); + TIntermAggregate *functionBodyNode = new TIntermAggregate(EOpSequence); TIntermSequence *functionBody = functionBodyNode->getSequence(); for (const auto &deferredInit : mDeferredInitializers) { functionBody->push_back(deferredInit); } - TIntermFunctionDefinition *functionDefinition = + TIntermAggregate *functionDefinition = CreateFunctionDefinitionNode(functionName, functionBodyNode, initFunctionId); - root->getSequence()->push_back(functionDefinition); + rootAgg->getSequence()->push_back(functionDefinition); // Insert call into main function - for (TIntermNode *node : *root->getSequence()) + for (TIntermNode *node : *rootAgg->getSequence()) { - TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition(); - if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain()) + TIntermAggregate *nodeAgg = node->getAsAggregate(); + if (nodeAgg != nullptr && nodeAgg->getOp() == EOpFunction && + TFunction::unmangleName(nodeAgg->getName()) == "main") { TIntermAggregate *functionCallNode = CreateFunctionCallNode(functionName, initFunctionId); - TIntermBlock *mainBody = nodeFunction->getBody(); - ASSERT(mainBody != nullptr); - mainBody->getSequence()->insert(mainBody->getSequence()->begin(), functionCallNode); + TIntermNode *mainBody = nodeAgg->getSequence()->back(); + TIntermAggregate *mainBodyAgg = mainBody->getAsAggregate(); + ASSERT(mainBodyAgg != nullptr && mainBodyAgg->getOp() == EOpSequence); + mainBodyAgg->getSequence()->insert(mainBodyAgg->getSequence()->begin(), + functionCallNode); } } } } // namespace -void DeferGlobalInitializers(TIntermBlock *root) +void DeferGlobalInitializers(TIntermNode *root) { DeferGlobalInitializersTraverser traverser; root->traverse(&traverser); @@ -190,5 +196,3 @@ void DeferGlobalInitializers(TIntermBlock *root) // Add the function with initialization and the call to that. traverser.insertInitFunction(root); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/DeferGlobalInitializers.h b/gfx/angle/src/compiler/translator/DeferGlobalInitializers.h index 261ec9001..14f25539c 100755 --- a/gfx/angle/src/compiler/translator/DeferGlobalInitializers.h +++ b/gfx/angle/src/compiler/translator/DeferGlobalInitializers.h @@ -13,11 +13,8 @@ #ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ #define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ -class TIntermBlock; +class TIntermNode; -namespace sh -{ -void DeferGlobalInitializers(TIntermBlock *root); -} // namespace sh +void DeferGlobalInitializers(TIntermNode *root); #endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ diff --git a/gfx/angle/src/compiler/translator/Diagnostics.cpp b/gfx/angle/src/compiler/translator/Diagnostics.cpp index 3b4168617..6ba4679c4 100755 --- a/gfx/angle/src/compiler/translator/Diagnostics.cpp +++ b/gfx/angle/src/compiler/translator/Diagnostics.cpp @@ -11,9 +11,6 @@ #include "compiler/translator/Common.h" #include "compiler/translator/InfoSink.h" -namespace sh -{ - TDiagnostics::TDiagnostics(TInfoSink& infoSink) : mInfoSink(infoSink), mNumErrors(0), @@ -82,5 +79,3 @@ void TDiagnostics::print(ID id, { writeInfo(severity(id), loc, message(id), text, ""); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Diagnostics.h b/gfx/angle/src/compiler/translator/Diagnostics.h index 25a8a3a57..bb521da1a 100755 --- a/gfx/angle/src/compiler/translator/Diagnostics.h +++ b/gfx/angle/src/compiler/translator/Diagnostics.h @@ -10,9 +10,6 @@ #include "common/angleutils.h" #include "compiler/preprocessor/DiagnosticsBase.h" -namespace sh -{ - class TInfoSink; struct TSourceLoc; @@ -48,6 +45,4 @@ class TDiagnostics : public pp::Diagnostics, angle::NonCopyable int mNumWarnings; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_ diff --git a/gfx/angle/src/compiler/translator/DirectiveHandler.cpp b/gfx/angle/src/compiler/translator/DirectiveHandler.cpp index 073994d3c..f8081ecd6 100755 --- a/gfx/angle/src/compiler/translator/DirectiveHandler.cpp +++ b/gfx/angle/src/compiler/translator/DirectiveHandler.cpp @@ -12,9 +12,6 @@ #include "common/debug.h" #include "compiler/translator/Diagnostics.h" -namespace sh -{ - static TBehavior getBehavior(const std::string& str) { const char kRequire[] = "require"; @@ -198,5 +195,3 @@ void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, "version number", str, "not supported"); } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/DirectiveHandler.h b/gfx/angle/src/compiler/translator/DirectiveHandler.h index a50b08219..00eb49114 100755 --- a/gfx/angle/src/compiler/translator/DirectiveHandler.h +++ b/gfx/angle/src/compiler/translator/DirectiveHandler.h @@ -13,8 +13,6 @@ #include "compiler/preprocessor/DirectiveHandlerBase.h" #include "GLSLANG/ShaderLang.h" -namespace sh -{ class TDiagnostics; class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable @@ -52,6 +50,4 @@ class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable bool mDebugShaderPrecisionSupported; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ diff --git a/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp index a4eeb9b7e..a664d9e2f 100755 --- a/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp +++ b/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp @@ -14,60 +14,59 @@ #include "compiler/translator/EmulateGLFragColorBroadcast.h" #include "compiler/translator/IntermNode.h" -namespace sh +namespace { -namespace +TIntermConstantUnion *constructIndexNode(int index) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + +TIntermBinary *constructGLFragDataNode(int index) { + TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); + TIntermSymbol *symbol = new TIntermSymbol(0, "gl_FragData", TType(EbtFloat, 4)); + indexDirect->setLeft(symbol); + TIntermConstantUnion *indexNode = constructIndexNode(index); + indexDirect->setRight(indexNode); + return indexDirect; +} + +TIntermBinary *constructGLFragDataAssignNode(int index) +{ + TIntermBinary *assign = new TIntermBinary(EOpAssign); + assign->setLeft(constructGLFragDataNode(index)); + assign->setRight(constructGLFragDataNode(0)); + assign->setType(TType(EbtFloat, 4)); + return assign; +} class GLFragColorBroadcastTraverser : public TIntermTraverser { public: - GLFragColorBroadcastTraverser(int maxDrawBuffers) - : TIntermTraverser(true, false, false), - mMainSequence(nullptr), - mGLFragColorUsed(false), - mMaxDrawBuffers(maxDrawBuffers) + GLFragColorBroadcastTraverser() + : TIntermTraverser(true, false, false), mMainSequence(nullptr), mGLFragColorUsed(false) { } - void broadcastGLFragColor(); + void broadcastGLFragColor(int maxDrawBuffers); bool isGLFragColorUsed() const { return mGLFragColorUsed; } protected: void visitSymbol(TIntermSymbol *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - - TIntermBinary *constructGLFragDataNode(int index) const; - TIntermBinary *constructGLFragDataAssignNode(int index) const; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; private: TIntermSequence *mMainSequence; bool mGLFragColorUsed; - int mMaxDrawBuffers; }; -TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const -{ - TType gl_FragDataType = TType(EbtFloat, EbpMedium, EvqFragData, 4); - gl_FragDataType.setArraySize(mMaxDrawBuffers); - - TIntermSymbol *symbol = new TIntermSymbol(0, "gl_FragData", gl_FragDataType); - TIntermTyped *indexNode = TIntermTyped::CreateIndexNode(index); - - TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode); - return binary; -} - -TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const -{ - TIntermTyped *fragDataIndex = constructGLFragDataNode(index); - TIntermTyped *fragDataZero = constructGLFragDataNode(0); - - return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero); -} - void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node) { if (node->getSymbol() == "gl_FragColor") @@ -77,22 +76,34 @@ void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node) } } -bool GLFragColorBroadcastTraverser::visitFunctionDefinition(Visit visit, - TIntermFunctionDefinition *node) +bool GLFragColorBroadcastTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { - ASSERT(visit == PreVisit); - if (node->getFunctionSymbolInfo()->isMain()) + switch (node->getOp()) { - TIntermBlock *body = node->getBody(); - ASSERT(body); - mMainSequence = body->getSequence(); + case EOpFunction: + // Function definition. + ASSERT(visit == PreVisit); + if (node->getName() == "main(") + { + TIntermSequence *sequence = node->getSequence(); + ASSERT((sequence->size() == 1) || (sequence->size() == 2)); + if (sequence->size() == 2) + { + TIntermAggregate *body = (*sequence)[1]->getAsAggregate(); + ASSERT(body); + mMainSequence = body->getSequence(); + } + } + break; + default: + break; } return true; } -void GLFragColorBroadcastTraverser::broadcastGLFragColor() +void GLFragColorBroadcastTraverser::broadcastGLFragColor(int maxDrawBuffers) { - ASSERT(mMaxDrawBuffers > 1); + ASSERT(maxDrawBuffers > 1); if (!mGLFragColorUsed) { return; @@ -102,7 +113,7 @@ void GLFragColorBroadcastTraverser::broadcastGLFragColor() // gl_FragData[1] = gl_FragData[0]; // ... // gl_FragData[maxDrawBuffers - 1] = gl_FragData[0]; - for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex) + for (int colorIndex = 1; colorIndex < maxDrawBuffers; ++colorIndex) { mMainSequence->insert(mMainSequence->end(), constructGLFragDataAssignNode(colorIndex)); } @@ -115,12 +126,12 @@ void EmulateGLFragColorBroadcast(TIntermNode *root, std::vector<sh::OutputVariable> *outputVariables) { ASSERT(maxDrawBuffers > 1); - GLFragColorBroadcastTraverser traverser(maxDrawBuffers); + GLFragColorBroadcastTraverser traverser; root->traverse(&traverser); if (traverser.isGLFragColorUsed()) { traverser.updateTree(); - traverser.broadcastGLFragColor(); + traverser.broadcastGLFragColor(maxDrawBuffers); for (auto &var : *outputVariables) { if (var.name == "gl_FragColor") @@ -133,5 +144,3 @@ void EmulateGLFragColorBroadcast(TIntermNode *root, } } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h b/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h index 09e8dae6d..627c4c67f 100755 --- a/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h +++ b/gfx/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h @@ -15,6 +15,8 @@ namespace sh { struct OutputVariable; +} + class TIntermNode; // Replace all gl_FragColor with gl_FragData[0], and in the end of main() function, @@ -22,7 +24,6 @@ class TIntermNode; // If gl_FragColor is in outputVariables, it is replaced by gl_FragData. void EmulateGLFragColorBroadcast(TIntermNode *root, int maxDrawBuffers, - std::vector<OutputVariable> *outputVariables); -} + std::vector<sh::OutputVariable> *outputVariables); #endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ diff --git a/gfx/angle/src/compiler/translator/EmulatePrecision.cpp b/gfx/angle/src/compiler/translator/EmulatePrecision.cpp index c3c49021c..5f1454b57 100755 --- a/gfx/angle/src/compiler/translator/EmulatePrecision.cpp +++ b/gfx/angle/src/compiler/translator/EmulatePrecision.cpp @@ -8,9 +8,6 @@ #include <memory> -namespace sh -{ - namespace { @@ -94,7 +91,6 @@ class RoundingHelperWriterHLSL : public RoundingHelperWriter RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage) { - ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage)); switch (outputLanguage) { case SH_HLSL_4_1_OUTPUT: @@ -102,6 +98,9 @@ RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOut case SH_ESSL_OUTPUT: return new RoundingHelperWriterESSL(outputLanguage); default: + // Other languages not yet supported + ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || + IsGLSL130OrNewer(outputLanguage)); return new RoundingHelperWriterGLSL(outputLanguage); } } @@ -433,7 +432,7 @@ TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *chil callNode->setOp(EOpFunctionCall); TName nameObj(TFunction::mangleName(name)); nameObj.setInternal(true); - callNode->getFunctionSymbolInfo()->setNameObj(nameObj); + callNode->setNameObj(nameObj); callNode->getSequence()->push_back(child); return callNode; } @@ -470,16 +469,15 @@ bool parentUsesResult(TIntermNode* parent, TIntermNode* node) return false; } - TIntermBlock *blockParent = parent->getAsBlock(); - // If the parent is a block, the result is not assigned anywhere, + TIntermAggregate *aggParent = parent->getAsAggregate(); + // If the parent's op is EOpSequence, the result is not assigned anywhere, // so rounding it is not needed. In particular, this can avoid a lot of // unnecessary rounding of unused return values of assignment. - if (blockParent) + if (aggParent && aggParent->getOp() == EOpSequence) { return false; } - TIntermBinary *binaryParent = parent->getAsBinaryNode(); - if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node)) + if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node)) { return false; } @@ -513,7 +511,7 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) if (op == EOpInitialize && visit == InVisit) mDeclaringVariables = false; - if ((op == EOpIndexDirectStruct) && visit == InVisit) + if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit) visitChildren = false; if (visit != PreVisit) @@ -601,30 +599,14 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) return visitChildren; } -bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - // Variable or interface block declaration. - if (visit == PreVisit) - { - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - return true; -} - bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; switch (node->getOp()) { + case EOpSequence: case EOpConstructStruct: + case EOpFunction: break; case EOpPrototype: visitChildren = false; @@ -635,6 +617,21 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) case EOpInvariantDeclaration: visitChildren = false; break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; case EOpFunctionCall: { // Function call. @@ -708,19 +705,3 @@ void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink, roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul"); } -// static -bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage) -{ - switch (outputLanguage) - { - case SH_HLSL_4_1_OUTPUT: - case SH_ESSL_OUTPUT: - return true; - default: - // Other languages not yet supported - return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || - sh::IsGLSL130OrNewer(outputLanguage)); - } -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/EmulatePrecision.h b/gfx/angle/src/compiler/translator/EmulatePrecision.h index deb49cd2c..c2b9857bb 100755 --- a/gfx/angle/src/compiler/translator/EmulatePrecision.h +++ b/gfx/angle/src/compiler/translator/EmulatePrecision.h @@ -18,9 +18,6 @@ // need to write a huge number of variations of the emulated compound assignment // to every translated shader with emulation enabled. -namespace sh -{ - class EmulatePrecision : public TLValueTrackingTraverser { public: @@ -30,14 +27,11 @@ class EmulatePrecision : public TLValueTrackingTraverser bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitUnary(Visit visit, TIntermUnary *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; void writeEmulationHelpers(TInfoSinkBase &sink, const int shaderVersion, const ShShaderOutput outputLanguage); - static bool SupportedInLanguage(const ShShaderOutput outputLanguage); - private: struct TypePair { @@ -67,6 +61,4 @@ class EmulatePrecision : public TLValueTrackingTraverser bool mDeclaringVariables; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ diff --git a/gfx/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/gfx/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp index c5ff7b36b..b78c2059e 100755 --- a/gfx/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp +++ b/gfx/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp @@ -116,7 +116,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) TIntermTyped *lhs = sequence->at(0)->getAsTyped(); ASSERT(lhs); - TIntermDeclaration *init = createTempInitDeclaration(lhs); + TIntermAggregate *init = createTempInitDeclaration(lhs); TIntermTyped *current = createTempSymbol(lhs->getType()); insertStatementInParentBlock(init); @@ -124,7 +124,10 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) // Create a chain of n-1 multiples. for (int i = 1; i < n; ++i) { - TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType())); + TIntermBinary *mul = new TIntermBinary(EOpMul); + mul->setLeft(current); + mul->setRight(createTempSymbol(lhs->getType())); + mul->setType(node->getType()); mul->setLine(node->getLine()); current = mul; } @@ -135,7 +138,9 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) TConstantUnion *oneVal = new TConstantUnion(); oneVal->setFConst(1.0f); TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType()); - TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current); + TIntermBinary *div = new TIntermBinary(EOpDiv); + div->setLeft(oneNode); + div->setRight(current); current = div; } diff --git a/gfx/angle/src/compiler/translator/ExtensionGLSL.cpp b/gfx/angle/src/compiler/translator/ExtensionGLSL.cpp index 5b5dc580e..d7f45f7ee 100755 --- a/gfx/angle/src/compiler/translator/ExtensionGLSL.cpp +++ b/gfx/angle/src/compiler/translator/ExtensionGLSL.cpp @@ -10,9 +10,6 @@ #include "compiler/translator/VersionGLSL.h" -namespace sh -{ - TExtensionGLSL::TExtensionGLSL(ShShaderOutput output) : TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output)) { @@ -101,5 +98,3 @@ void TExtensionGLSL::checkOperator(TIntermOperator *node) break; } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ExtensionGLSL.h b/gfx/angle/src/compiler/translator/ExtensionGLSL.h index 3c2dbe074..6bb84d612 100755 --- a/gfx/angle/src/compiler/translator/ExtensionGLSL.h +++ b/gfx/angle/src/compiler/translator/ExtensionGLSL.h @@ -14,9 +14,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - // Traverses the intermediate tree to determine which GLSL extensions are required // to support the shader. class TExtensionGLSL : public TIntermTraverser @@ -39,6 +36,4 @@ class TExtensionGLSL : public TIntermTraverser std::set<std::string> mRequiredExtensions; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_ diff --git a/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp b/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp index 58cce845f..4cc1c26a1 100755 --- a/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp +++ b/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp @@ -9,9 +9,6 @@ #include "compiler/translator/ValidateLimitations.h" #include "angle_gl.h" -namespace sh -{ - bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node) { if (mUnrollCondition != kSamplerArrayIndex) @@ -54,7 +51,7 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node) // Check if loop index type is integer. // This is called after ValidateLimitations pass, so the loop has the limited form specified // in ESSL 1.00 appendix A. - TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence(); + TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); if (symbol->getBasicType() == EbtInt) node->setUnrollFlag(true); @@ -98,5 +95,3 @@ void ForLoopUnrollMarker::visitSymbol(TIntermSymbol* symbol) } } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ForLoopUnroll.h b/gfx/angle/src/compiler/translator/ForLoopUnroll.h index cda89b29f..9c49ecad3 100755 --- a/gfx/angle/src/compiler/translator/ForLoopUnroll.h +++ b/gfx/angle/src/compiler/translator/ForLoopUnroll.h @@ -9,9 +9,6 @@ #include "compiler/translator/LoopInfo.h" -namespace sh -{ - // This class detects for-loops that needs to be unrolled. // Currently we support two unroll conditions: // 1) kForLoopWithIntegerIndex: unroll if the index type is integer. @@ -53,6 +50,4 @@ class ForLoopUnrollMarker : public TIntermTraverser bool mHasRunLoopValidation; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ diff --git a/gfx/angle/src/compiler/translator/InfoSink.cpp b/gfx/angle/src/compiler/translator/InfoSink.cpp index e71fe51d3..cd59658ff 100755 --- a/gfx/angle/src/compiler/translator/InfoSink.cpp +++ b/gfx/angle/src/compiler/translator/InfoSink.cpp @@ -6,9 +6,6 @@ #include "compiler/translator/InfoSink.h" -namespace sh -{ - void TInfoSinkBase::prefix(TPrefixType p) { switch(p) { case EPrefixNone: @@ -55,5 +52,3 @@ void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) sink.append(m); sink.append("\n"); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/InfoSink.h b/gfx/angle/src/compiler/translator/InfoSink.h index b18e5861b..f47fafa8e 100755 --- a/gfx/angle/src/compiler/translator/InfoSink.h +++ b/gfx/angle/src/compiler/translator/InfoSink.h @@ -11,9 +11,6 @@ #include <stdlib.h> #include "compiler/translator/Common.h" -namespace sh -{ - // Returns the fractional part of the given floating-point number. inline float fractionalPart(float f) { float intPart = 0.0f; @@ -116,6 +113,4 @@ public: TInfoSinkBase obj; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_INFOSINK_H_ diff --git a/gfx/angle/src/compiler/translator/Initialize.cpp b/gfx/angle/src/compiler/translator/Initialize.cpp index a0b35f636..0bf6ac45b 100755 --- a/gfx/angle/src/compiler/translator/Initialize.cpp +++ b/gfx/angle/src/compiler/translator/Initialize.cpp @@ -16,12 +16,8 @@ #include "compiler/translator/IntermNode.h" #include "angle_gl.h" -namespace sh -{ - void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { - const TType *voidType = TCache::getType(EbtVoid); const TType *float1 = TCache::getType(EbtFloat); const TType *float2 = TCache::getType(EbtFloat, 2); const TType *float3 = TCache::getType(EbtFloat, 3); @@ -473,26 +469,6 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, float3, float3, int3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, float4, float2, float2, int2); - const TType *gimage2D = TCache::getType(EbtGImage2D); - const TType *gimage3D = TCache::getType(EbtGImage3D); - const TType *gimage2DArray = TCache::getType(EbtGImage2DArray); - const TType *gimageCube = TCache::getType(EbtGImageCube); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3); - - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray); - symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimageCube); - // // Depth range in window coordinates // @@ -535,13 +511,16 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors, EbpMedium); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers, - EbpMedium); - if (resources.EXT_blend_func_extended) + if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended", - "gl_MaxDualSourceDrawBuffersEXT", - resources.MaxDualSourceDrawBuffers); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers, + EbpMedium); + if (resources.EXT_blend_func_extended) + { + symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended", + "gl_MaxDualSourceDrawBuffersEXT", + resources.MaxDualSourceDrawBuffers); + } } symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", @@ -611,73 +590,85 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, switch (type) { case GL_FRAGMENT_SHADER: - { - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), - TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), - TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), - TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); - - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), - TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); - fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); - - if (resources.EXT_blend_func_extended) - { - symbolTable.insert( - ESSL1_BUILTINS, "GL_EXT_blend_func_extended", - new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"), - TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4))); - TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true); - secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers); - symbolTable.insert( - ESSL1_BUILTINS, "GL_EXT_blend_func_extended", - new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData)); - } - - if (resources.EXT_frag_depth) - { - symbolTable.insert( - ESSL1_BUILTINS, "GL_EXT_frag_depth", - new TVariable( - NewPoolTString("gl_FragDepthEXT"), - TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, - EvqFragDepthEXT, 1))); - } - - symbolTable.insert(ESSL3_BUILTINS, - new TVariable(NewPoolTString("gl_FragDepth"), - TType(EbtFloat, EbpHigh, EvqFragDepth, 1))); - - if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) - { - TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true); - lastFragData.setArraySize(resources.MaxDrawBuffers); - - if (resources.EXT_shader_framebuffer_fetch) - { - symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch", - new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); - } - else if (resources.NV_shader_framebuffer_fetch) - { - symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", - new TVariable(NewPoolTString("gl_LastFragColor"), - TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); - symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", - new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); - } - } - else if (resources.ARM_shader_framebuffer_fetch) - { - symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch", - new TVariable(NewPoolTString("gl_LastFragColorARM"), - TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); - } - } + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), + TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), + TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), + TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + + // + // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. + // Instead, css_MixColor and css_ColorMatrix are available. + // + if (spec != SH_CSS_SHADERS_SPEC) + { + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), + TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); + fragData.setArraySize(resources.MaxDrawBuffers); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); + + if (resources.EXT_blend_func_extended) + { + symbolTable.insert( + ESSL1_BUILTINS, "GL_EXT_blend_func_extended", + new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"), + TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4))); + TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true); + secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers); + symbolTable.insert( + ESSL1_BUILTINS, "GL_EXT_blend_func_extended", + new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData)); + } + + if (resources.EXT_frag_depth) + { + symbolTable.insert( + ESSL1_BUILTINS, "GL_EXT_frag_depth", + new TVariable( + NewPoolTString("gl_FragDepthEXT"), + TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, + EvqFragDepthEXT, 1))); + } + + symbolTable.insert(ESSL3_BUILTINS, + new TVariable(NewPoolTString("gl_FragDepth"), + TType(EbtFloat, EbpHigh, EvqFragDepth, 1))); + + if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) + { + TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true); + lastFragData.setArraySize(resources.MaxDrawBuffers); + + if (resources.EXT_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); + } + else if (resources.NV_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragColor"), + TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); + symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); + } + } + else if (resources.ARM_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragColorARM"), + TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); + } + } + else + { + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), + TType(EbtFloat, EbpMedium, EvqGlobal, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), + TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); + } break; @@ -758,5 +749,3 @@ void ResetExtensionBehavior(TExtensionBehavior &extBehavior) ext_iter->second = EBhUndefined; } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Initialize.h b/gfx/angle/src/compiler/translator/Initialize.h index 0f1b60ba3..c43ce3417 100755 --- a/gfx/angle/src/compiler/translator/Initialize.h +++ b/gfx/angle/src/compiler/translator/Initialize.h @@ -11,9 +11,6 @@ #include "compiler/translator/Compiler.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, @@ -29,6 +26,4 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, // extensions will remain unsupported. void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior); -} // namespace sh - #endif // COMPILER_TRANSLATOR_INITIALIZE_H_ diff --git a/gfx/angle/src/compiler/translator/InitializeDll.cpp b/gfx/angle/src/compiler/translator/InitializeDll.cpp index 89901935c..713965389 100755 --- a/gfx/angle/src/compiler/translator/InitializeDll.cpp +++ b/gfx/angle/src/compiler/translator/InitializeDll.cpp @@ -13,9 +13,6 @@ #include <assert.h> -namespace sh -{ - bool InitProcess() { if (!InitializePoolIndex()) { @@ -39,5 +36,3 @@ void DetachProcess() FreePoolIndex(); TCache::destroy(); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/InitializeDll.h b/gfx/angle/src/compiler/translator/InitializeDll.h index b2c787a8c..4c400760f 100755 --- a/gfx/angle/src/compiler/translator/InitializeDll.h +++ b/gfx/angle/src/compiler/translator/InitializeDll.h @@ -6,11 +6,8 @@ #ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ #define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ -namespace sh -{ bool InitProcess(); void DetachProcess(); -} // namespace sh #endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/gfx/angle/src/compiler/translator/InitializeParseContext.cpp b/gfx/angle/src/compiler/translator/InitializeParseContext.cpp index 67a248b60..c35cedb34 100755 --- a/gfx/angle/src/compiler/translator/InitializeParseContext.cpp +++ b/gfx/angle/src/compiler/translator/InitializeParseContext.cpp @@ -10,9 +10,6 @@ #include <assert.h> -namespace sh -{ - TLSIndex GlobalParseContextIndex = TLS_INVALID_INDEX; bool InitializeParseContextIndex() @@ -43,4 +40,3 @@ TParseContext* GetGlobalParseContext() return static_cast<TParseContext*>(GetTLSValue(GlobalParseContextIndex)); } -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/InitializeParseContext.h b/gfx/angle/src/compiler/translator/InitializeParseContext.h index 9c315be3f..70dac702e 100755 --- a/gfx/angle/src/compiler/translator/InitializeParseContext.h +++ b/gfx/angle/src/compiler/translator/InitializeParseContext.h @@ -7,15 +7,11 @@ #ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ #define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ -namespace sh -{ - bool InitializeParseContextIndex(); void FreeParseContextIndex(); class TParseContext; extern void SetGlobalParseContext(TParseContext* context); extern TParseContext* GetGlobalParseContext(); -} // namespace sh #endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ diff --git a/gfx/angle/src/compiler/translator/InitializeVariables.cpp b/gfx/angle/src/compiler/translator/InitializeVariables.cpp index dafea1bd6..21f00936e 100755 --- a/gfx/angle/src/compiler/translator/InitializeVariables.cpp +++ b/gfx/angle/src/compiler/translator/InitializeVariables.cpp @@ -9,122 +9,191 @@ #include "angle_gl.h" #include "common/debug.h" #include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" #include "compiler/translator/util.h" -namespace sh +namespace { -namespace +TIntermConstantUnion *constructConstUnionNode(const TType &type) +{ + TType myType = type; + myType.clearArrayness(); + myType.setQualifier(EvqConst); + size_t size = myType.getObjectSize(); + TConstantUnion *u = new TConstantUnion[size]; + for (size_t ii = 0; ii < size; ++ii) + { + switch (type.getBasicType()) + { + case EbtFloat: + u[ii].setFConst(0.0f); + break; + case EbtInt: + u[ii].setIConst(0); + break; + case EbtUInt: + u[ii].setUConst(0u); + break; + default: + UNREACHABLE(); + return nullptr; + } + } + + TIntermConstantUnion *node = new TIntermConstantUnion(u, myType); + return node; +} + +TIntermConstantUnion *constructIndexNode(int index) { + TConstantUnion *u = new TConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} class VariableInitializer : public TIntermTraverser { public: - VariableInitializer(const InitVariableList &vars, const TSymbolTable &symbolTable) - : TIntermTraverser(true, false, false), - mVariables(vars), - mSymbolTable(symbolTable), - mCodeInserted(false) + VariableInitializer(const InitVariableList &vars) + : TIntermTraverser(true, false, false), mVariables(vars), mCodeInserted(false) { - ASSERT(mSymbolTable.atGlobalLevel()); } protected: bool visitBinary(Visit, TIntermBinary *node) override { return false; } bool visitUnary(Visit, TIntermUnary *node) override { return false; } - bool visitIfElse(Visit, TIntermIfElse *node) override { return false; } + bool visitSelection(Visit, TIntermSelection *node) override { return false; } bool visitLoop(Visit, TIntermLoop *node) override { return false; } bool visitBranch(Visit, TIntermBranch *node) override { return false; } - bool visitAggregate(Visit, TIntermAggregate *node) override { return false; } - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; private: void insertInitCode(TIntermSequence *sequence); const InitVariableList &mVariables; - const TSymbolTable &mSymbolTable; bool mCodeInserted; }; // VariableInitializer implementation. -bool VariableInitializer::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +bool VariableInitializer::visitAggregate(Visit visit, TIntermAggregate *node) { - // Function definition. - ASSERT(visit == PreVisit); - if (node->getFunctionSymbolInfo()->isMain()) + bool visitChildren = !mCodeInserted; + switch (node->getOp()) { - TIntermBlock *body = node->getBody(); - insertInitCode(body->getSequence()); - mCodeInserted = true; + case EOpSequence: + break; + case EOpFunction: + { + // Function definition. + ASSERT(visit == PreVisit); + if (node->getName() == "main(") + { + TIntermSequence *sequence = node->getSequence(); + ASSERT((sequence->size() == 1) || (sequence->size() == 2)); + TIntermAggregate *body = NULL; + if (sequence->size() == 1) + { + body = new TIntermAggregate(EOpSequence); + sequence->push_back(body); + } + else + { + body = (*sequence)[1]->getAsAggregate(); + } + ASSERT(body); + insertInitCode(body->getSequence()); + mCodeInserted = true; + } + break; + } + default: + visitChildren = false; + break; } - return false; + return visitChildren; } void VariableInitializer::insertInitCode(TIntermSequence *sequence) { - for (const auto &var : mVariables) + for (size_t ii = 0; ii < mVariables.size(); ++ii) { + const sh::ShaderVariable &var = mVariables[ii]; TString name = TString(var.name.c_str()); - if (var.isArray()) { - // Assign the array elements one by one to keep the AST compatible with ESSL 1.00 which - // doesn't have array assignment. + TType type = sh::ConvertShaderVariableTypeToTType(var.type); size_t pos = name.find_last_of('['); if (pos != TString::npos) - { name = name.substr(0, pos); - } - TType elementType = sh::GetShaderVariableBasicType(var); - TType arrayType = elementType; - arrayType.setArraySize(var.elementCount()); - - for (unsigned int i = 0; i < var.arraySize; ++i) + for (int index = static_cast<int>(var.arraySize) - 1; index >= 0; --index) { - TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, arrayType); - TIntermBinary *element = new TIntermBinary(EOpIndexDirect, arraySymbol, - TIntermTyped::CreateIndexNode(i)); + TIntermBinary *assign = new TIntermBinary(EOpAssign); + sequence->insert(sequence->begin(), assign); + + TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); + TIntermSymbol *symbol = new TIntermSymbol(0, name, type); + indexDirect->setLeft(symbol); + TIntermConstantUnion *indexNode = constructIndexNode(index); + indexDirect->setRight(indexNode); - TIntermTyped *zero = TIntermTyped::CreateZero(elementType); - TIntermBinary *assignment = new TIntermBinary(EOpAssign, element, zero); + assign->setLeft(indexDirect); - sequence->insert(sequence->begin(), assignment); + TIntermConstantUnion *zeroConst = constructConstUnionNode(type); + assign->setRight(zeroConst); } } else if (var.isStruct()) { - TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); - ASSERT(structInfo); - - TIntermSymbol *symbol = new TIntermSymbol(0, name, structInfo->getType()); - TIntermTyped *zero = TIntermTyped::CreateZero(structInfo->getType()); - - TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero); - sequence->insert(sequence->begin(), assign); + TFieldList *fields = new TFieldList; + TSourceLoc loc; + for (auto field : var.fields) + { + fields->push_back(new TField(nullptr, new TString(field.name.c_str()), loc)); + } + TStructure *structure = new TStructure(new TString(var.structName.c_str()), fields); + TType type; + type.setStruct(structure); + for (int fieldIndex = 0; fieldIndex < static_cast<int>(var.fields.size()); ++fieldIndex) + { + TIntermBinary *assign = new TIntermBinary(EOpAssign); + sequence->insert(sequence->begin(), assign); + + TIntermBinary *indexDirectStruct = new TIntermBinary(EOpIndexDirectStruct); + TIntermSymbol *symbol = new TIntermSymbol(0, name, type); + indexDirectStruct->setLeft(symbol); + TIntermConstantUnion *indexNode = constructIndexNode(fieldIndex); + indexDirectStruct->setRight(indexNode); + assign->setLeft(indexDirectStruct); + + const sh::ShaderVariable &field = var.fields[fieldIndex]; + TType fieldType = sh::ConvertShaderVariableTypeToTType(field.type); + TIntermConstantUnion *zeroConst = constructConstUnionNode(fieldType); + assign->setRight(zeroConst); + } } else { - TType type = sh::GetShaderVariableBasicType(var); - TIntermSymbol *symbol = new TIntermSymbol(0, name, type); - TIntermTyped *zero = TIntermTyped::CreateZero(type); - - TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero); + TType type = sh::ConvertShaderVariableTypeToTType(var.type); + TIntermBinary *assign = new TIntermBinary(EOpAssign); sequence->insert(sequence->begin(), assign); + TIntermSymbol *symbol = new TIntermSymbol(0, name, type); + assign->setLeft(symbol); + TIntermConstantUnion *zeroConst = constructConstUnionNode(type); + assign->setRight(zeroConst); } + } } } // namespace anonymous -void InitializeVariables(TIntermNode *root, - const InitVariableList &vars, - const TSymbolTable &symbolTable) +void InitializeVariables(TIntermNode *root, const InitVariableList &vars) { - VariableInitializer initializer(vars, symbolTable); + VariableInitializer initializer(vars); root->traverse(&initializer); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/InitializeVariables.h b/gfx/angle/src/compiler/translator/InitializeVariables.h index 9a34245a5..f826032d3 100755 --- a/gfx/angle/src/compiler/translator/InitializeVariables.h +++ b/gfx/angle/src/compiler/translator/InitializeVariables.h @@ -9,23 +9,10 @@ #include <GLSLANG/ShaderLang.h> -namespace sh -{ class TIntermNode; -class TSymbolTable; typedef std::vector<sh::ShaderVariable> InitVariableList; -// Currently this function is only capable of initializing variables of basic types, -// array of basic types, or struct of basic types. -// For now it is used for the following two scenarios: -// 1. initializing gl_Position; -// 2. initializing ESSL 3.00 shaders' output variables (which might be structs). -// Specifically, it's not feasible to make it work for local variables because if their -// types are structs, we can't look into TSymbolTable to find the TType data. -void InitializeVariables(TIntermNode *root, - const InitVariableList &vars, - const TSymbolTable &symbolTable); -} // namespace sh +void InitializeVariables(TIntermNode *root, const InitVariableList &vars); #endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ diff --git a/gfx/angle/src/compiler/translator/IntermNode.cpp b/gfx/angle/src/compiler/translator/IntermNode.cpp index b91b43ecf..dcf47879a 100755 --- a/gfx/angle/src/compiler/translator/IntermNode.cpp +++ b/gfx/angle/src/compiler/translator/IntermNode.cpp @@ -21,10 +21,6 @@ #include "compiler/translator/HashNames.h" #include "compiler/translator/IntermNode.h" #include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ namespace { @@ -47,14 +43,13 @@ TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size) return constUnion; } -void UndefinedConstantFoldingError(const TSourceLoc &loc, - TOperator op, - TBasicType basicType, - TDiagnostics *diagnostics, - TConstantUnion *result) +void UndefinedConstantFoldingError(const TSourceLoc &loc, TOperator op, TBasicType basicType, + TInfoSink &infoSink, TConstantUnion *result) { - diagnostics->warning(loc, "operation result is undefined for the values passed in", - GetOperatorString(op), ""); + std::stringstream constantFoldingErrorStream; + constantFoldingErrorStream << "'" << GetOperatorString(op) + << "' operation result is undefined for the values passed in"; + infoSink.info.message(EPrefixWarning, loc, constantFoldingErrorStream.str().c_str()); switch (basicType) { @@ -96,7 +91,7 @@ float VectorDotProduct(const TConstantUnion *paramArray1, return result; } -TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray, +TIntermTyped *CreateFoldedNode(TConstantUnion *constArray, const TIntermTyped *originalNode, TQualifier qualifier) { @@ -173,7 +168,7 @@ bool TIntermLoop::replaceChildNode( REPLACE_IF_IS(mInit, TIntermNode, original, replacement); REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); - REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); + REPLACE_IF_IS(mBody, TIntermAggregate, original, replacement); return false; } @@ -184,13 +179,6 @@ bool TIntermBranch::replaceChildNode( return false; } -bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - bool TIntermBinary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -202,67 +190,42 @@ bool TIntermBinary::replaceChildNode( bool TIntermUnary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { - ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType()); REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); return false; } -bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mParameters, TIntermAggregate, original, replacement); - REPLACE_IF_IS(mBody, TIntermBlock, original, replacement); - return false; -} - bool TIntermAggregate::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - return replaceChildNodeInternal(original, replacement); -} - -bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < getSequence()->size(); ++ii) + for (size_t ii = 0; ii < mSequence.size(); ++ii) { - REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement); + REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); } return false; } -bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original, - const TIntermSequence &replacements) +bool TIntermAggregate::replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements) { - for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it) + for (auto it = mSequence.begin(); it < mSequence.end(); ++it) { if (*it == original) { - it = getSequence()->erase(it); - getSequence()->insert(it, replacements.begin(), replacements.end()); + it = mSequence.erase(it); + mSequence.insert(it, replacements.begin(), replacements.end()); return true; } } return false; } -bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position, - const TIntermSequence &insertions) +bool TIntermAggregate::insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions) { - if (position > getSequence()->size()) + if (position > mSequence.size()) { return false; } - auto it = getSequence()->begin() + position; - getSequence()->insert(it, insertions.begin(), insertions.end()); + auto it = mSequence.begin() + position; + mSequence.insert(it, insertions.begin(), insertions.end()); return true; } @@ -320,47 +283,18 @@ void TIntermAggregate::setBuiltInFunctionPrecision() } // ESSL 3.0 spec section 8: textureSize always gets highp precision. // All other functions that take a sampler are assumed to be texture functions. - if (mFunctionInfo.getName().find("textureSize") == 0) + if (mName.getString().find("textureSize") == 0) mType.setPrecision(EbpHigh); else mType.setPrecision(precision); } -void TIntermBlock::appendStatement(TIntermNode *statement) -{ - // Declaration nodes with no children can appear if all the declarators just added constants to - // the symbol table instead of generating code. They're no-ops so they aren't added to blocks. - if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr || - !statement->getAsDeclarationNode()->getSequence()->empty())) - { - mStatements.push_back(statement); - } -} - -void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) -{ - ASSERT(declarator != nullptr); - ASSERT(declarator->getAsSymbolNode() != nullptr || - (declarator->getAsBinaryNode() != nullptr && - declarator->getAsBinaryNode()->getOp() == EOpInitialize)); - ASSERT(mDeclarators.empty() || - declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType())); - mDeclarators.push_back(declarator); -} - -bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement); - REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement); - return false; -} - -bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement) +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) { REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement); - REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement); + REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); return false; } @@ -368,7 +302,7 @@ bool TIntermSwitch::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); - REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement); + REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement); return false; } @@ -402,100 +336,18 @@ bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters() return true; } -// static -TIntermTyped *TIntermTyped::CreateIndexNode(int index) -{ - TConstantUnion *u = new TConstantUnion[1]; - u[0].setIConst(index); - - TType type(EbtInt, EbpUndefined, EvqConst, 1); - TIntermConstantUnion *node = new TIntermConstantUnion(u, type); - return node; -} - -// static -TIntermTyped *TIntermTyped::CreateZero(const TType &type) -{ - TType constType(type); - constType.setQualifier(EvqConst); - - if (!type.isArray() && type.getBasicType() != EbtStruct) - { - ASSERT(type.isScalar() || type.isVector() || type.isMatrix()); - - size_t size = constType.getObjectSize(); - TConstantUnion *u = new TConstantUnion[size]; - for (size_t i = 0; i < size; ++i) - { - switch (type.getBasicType()) - { - case EbtFloat: - u[i].setFConst(0.0f); - break; - case EbtInt: - u[i].setIConst(0); - break; - case EbtUInt: - u[i].setUConst(0u); - break; - case EbtBool: - u[i].setBConst(false); - break; - default: - UNREACHABLE(); - return nullptr; - } - } - - TIntermConstantUnion *node = new TIntermConstantUnion(u, constType); - return node; - } - - TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type)); - constructor->setType(constType); - - if (type.isArray()) - { - TType elementType(type); - elementType.clearArrayness(); - - size_t arraySize = type.getArraySize(); - for (size_t i = 0; i < arraySize; ++i) - { - constructor->getSequence()->push_back(CreateZero(elementType)); - } - } - else - { - ASSERT(type.getBasicType() == EbtStruct); - - TStructure *structure = type.getStruct(); - for (const auto &field : structure->fields()) - { - constructor->getSequence()->push_back(CreateZero(*field->type())); - } - } - - return constructor; -} - TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node) { mUnionArrayPointer = node.mUnionArrayPointer; } -void TFunctionSymbolInfo::setFromFunction(const TFunction &function) -{ - setName(function.getMangledName()); - setId(function.getUniqueId()); -} - TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) : TIntermOperator(node), + mName(node.mName), mUserDefined(node.mUserDefined), + mFunctionId(node.mFunctionId), mUseEmulatedFunction(node.mUseEmulatedFunction), - mGotPrecisionFromChildren(node.mGotPrecisionFromChildren), - mFunctionInfo(node.mFunctionInfo) + mGotPrecisionFromChildren(node.mGotPrecisionFromChildren) { for (TIntermNode *child : node.mSequence) { @@ -506,13 +358,6 @@ TIntermAggregate::TIntermAggregate(const TIntermAggregate &node) } } -TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node) -{ - TIntermTyped *operandCopy = node.mOperand->deepCopy(); - ASSERT(operandCopy != nullptr); - mOperand = operandCopy; -} - TIntermBinary::TIntermBinary(const TIntermBinary &node) : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp) { @@ -531,15 +376,20 @@ TIntermUnary::TIntermUnary(const TIntermUnary &node) mOperand = operandCopy; } -TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node) +TIntermSelection::TIntermSelection(const TIntermSelection &node) : TIntermTyped(node) { + // Only supported for ternary nodes, not if statements. + TIntermTyped *trueTyped = node.mTrueBlock->getAsTyped(); + TIntermTyped *falseTyped = node.mFalseBlock->getAsTyped(); + ASSERT(trueTyped != nullptr); + ASSERT(falseTyped != nullptr); TIntermTyped *conditionCopy = node.mCondition->deepCopy(); - TIntermTyped *trueCopy = node.mTrueExpression->deepCopy(); - TIntermTyped *falseCopy = node.mFalseExpression->deepCopy(); + TIntermTyped *trueCopy = trueTyped->deepCopy(); + TIntermTyped *falseCopy = falseTyped->deepCopy(); ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr); - mCondition = conditionCopy; - mTrueExpression = trueCopy; - mFalseExpression = falseCopy; + mCondition = conditionCopy; + mTrueBlock = trueCopy; + mFalseBlock = falseCopy; } bool TIntermOperator::isAssignment() const @@ -694,187 +544,77 @@ TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const // Make sure the type of a unary operator is appropriate for its // combination of operation and operand type. // -void TIntermUnary::promote() +void TIntermUnary::promote(const TType *funcReturnType) { - TQualifier resultQualifier = EvqTemporary; - if (mOperand->getQualifier() == EvqConst) - resultQualifier = EvqConst; - - unsigned char operandPrimarySize = - static_cast<unsigned char>(mOperand->getType().getNominalSize()); switch (mOp) { - case EOpFloatBitsToInt: - setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpFloatBitsToUint: - setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize)); - break; - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - setType(TType(EbtUInt, EbpHigh, resultQualifier)); - break; - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - setType(TType(EbtFloat, EbpHigh, resultQualifier, 2)); - break; - case EOpUnpackHalf2x16: - setType(TType(EbtFloat, EbpMedium, resultQualifier, 2)); - break; - case EOpAny: - case EOpAll: - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; - case EOpLength: - case EOpDeterminant: - setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier)); - break; - case EOpTranspose: - setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier, - static_cast<unsigned char>(mOperand->getType().getRows()), - static_cast<unsigned char>(mOperand->getType().getCols()))); - break; - case EOpIsInf: - case EOpIsNan: - setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize)); - break; - default: - setType(mOperand->getType()); - mType.setQualifier(resultQualifier); - break; - } -} - -TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets) - : TIntermTyped(TType(EbtFloat, EbpUndefined)), - mOperand(operand), - mSwizzleOffsets(swizzleOffsets) -{ - ASSERT(mSwizzleOffsets.size() <= 4); - promote(); -} - -TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand) - : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false) -{ - promote(); -} - -TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right) - : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false) -{ - promote(); -} - -TIntermTernary::TIntermTernary(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression) - : TIntermTyped(trueExpression->getType()), - mCondition(cond), - mTrueExpression(trueExpression), - mFalseExpression(falseExpression) -{ - getTypePointer()->setQualifier( - TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression)); -} - -// static -TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression) -{ - if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst && - falseExpression->getQualifier() == EvqConst) - { - return EvqConst; + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + mType.setPrecision(EbpHigh); + break; + case EOpUnpackHalf2x16: + mType.setPrecision(EbpMedium); + break; + default: + setType(mOperand->getType()); } - return EvqTemporary; -} -void TIntermSwizzle::promote() -{ - TQualifier resultQualifier = EvqTemporary; - if (mOperand->getQualifier() == EvqConst) - resultQualifier = EvqConst; - - auto numFields = mSwizzleOffsets.size(); - setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier, - static_cast<unsigned char>(numFields))); -} - -bool TIntermSwizzle::hasDuplicateOffsets() const -{ - int offsetCount[4] = {0u, 0u, 0u, 0u}; - for (const auto offset : mSwizzleOffsets) + if (funcReturnType != nullptr) { - offsetCount[offset]++; - if (offsetCount[offset] > 1) + if (funcReturnType->getBasicType() == EbtBool) { - return true; + // Bool types should not have precision. + setType(*funcReturnType); } - } - return false; -} - -void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const -{ - for (const int offset : mSwizzleOffsets) - { - switch (offset) + else { - case 0: - *out << "x"; - break; - case 1: - *out << "y"; - break; - case 2: - *out << "z"; - break; - case 3: - *out << "w"; - break; - default: - UNREACHABLE(); + // Precision of the node has been set based on the operand. + setTypePreservePrecision(*funcReturnType); } } + + if (mOperand->getQualifier() == EvqConst) + mType.setQualifier(EvqConst); + else + mType.setQualifier(EvqTemporary); } -TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion, - const TIntermTyped *left, - const TIntermTyped *right) +TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right) + : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false) { - // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. - if (shaderVersion >= 300 || left->getQualifier() != EvqConst || - right->getQualifier() != EvqConst) - { - return EvqTemporary; - } - return EvqConst; + promote(); } -// Establishes the type of the result of the binary operation. +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// For lots of operations it should already be established that the operand +// combination is valid, but returns false if operator can't work on operands. +// void TIntermBinary::promote() { + ASSERT(mLeft->isArray() == mRight->isArray()); + ASSERT(!isMultiplication() || mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType())); - // Comma is handled as a special case. - if (mOp == EOpComma) - { - setType(mRight->getType()); - return; - } - // Base assumption: just make the type the same as the left // operand. Then only deviations from this need be coded. setType(mLeft->getType()); + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision( + mLeft->getPrecision(), mRight->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + TQualifier resultQualifier = EvqConst; // Binary operations results in temporary variables unless both // operands are const. @@ -884,55 +624,6 @@ void TIntermBinary::promote() getTypePointer()->setQualifier(EvqTemporary); } - // Handle indexing ops. - switch (mOp) - { - case EOpIndexDirect: - case EOpIndexIndirect: - if (mLeft->isArray()) - { - mType.clearArrayness(); - } - else if (mLeft->isMatrix()) - { - setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier, - static_cast<unsigned char>(mLeft->getRows()))); - } - else if (mLeft->isVector()) - { - setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier)); - } - else - { - UNREACHABLE(); - } - return; - case EOpIndexDirectStruct: - { - const TFieldList &fields = mLeft->getType().getStruct()->fields(); - const int i = mRight->getAsConstantUnion()->getIConst(0); - setType(*fields[i]->type()); - getTypePointer()->setQualifier(resultQualifier); - return; - } - case EOpIndexDirectInterfaceBlock: - { - const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields(); - const int i = mRight->getAsConstantUnion()->getIConst(0); - setType(*fields[i]->type()); - getTypePointer()->setQualifier(resultQualifier); - return; - } - default: - break; - } - - ASSERT(mLeft->isArray() == mRight->isArray()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize()); @@ -952,8 +643,8 @@ void TIntermBinary::promote() case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined, resultQualifier)); - break; + setType(TType(EbtBool, EbpUndefined)); + break; // // And and Or operate on conditionals @@ -962,7 +653,7 @@ void TIntermBinary::promote() case EOpLogicalXor: case EOpLogicalOr: ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); - setType(TType(EbtBool, EbpUndefined, resultQualifier)); + setType(TType(EbtBool, EbpUndefined)); break; default: @@ -1058,7 +749,8 @@ void TIntermBinary::promote() case EOpIndexIndirect: case EOpIndexDirectInterfaceBlock: case EOpIndexDirectStruct: - // These ops should be already fully handled. + // TODO (oetuaho): These ops could be handled here as well (should be done closer to the + // top of the function). UNREACHABLE(); break; default: @@ -1067,105 +759,26 @@ void TIntermBinary::promote() } } -const TConstantUnion *TIntermConstantUnion::foldIndexing(int index) -{ - if (isArray()) - { - ASSERT(index < static_cast<int>(getType().getArraySize())); - TType arrayElementType = getType(); - arrayElementType.clearArrayness(); - size_t arrayElementSize = arrayElementType.getObjectSize(); - return &mUnionArrayPointer[arrayElementSize * index]; - } - else if (isMatrix()) - { - ASSERT(index < getType().getCols()); - int size = getType().getRows(); - return &mUnionArrayPointer[size * index]; - } - else if (isVector()) - { - ASSERT(index < getType().getNominalSize()); - return &mUnionArrayPointer[index]; - } - else - { - UNREACHABLE(); - return nullptr; - } -} - -TIntermTyped *TIntermSwizzle::fold() +TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) { - TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); - if (operandConstant == nullptr) + TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion(); + TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion(); + if (leftConstant == nullptr || rightConstant == nullptr) { return nullptr; } + TConstantUnion *constArray = leftConstant->foldBinary(mOp, rightConstant, diagnostics); - TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()]; - for (size_t i = 0; i < mSwizzleOffsets.size(); ++i) - { - constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i)); - } - return CreateFoldedNode(constArray, this, mType.getQualifier()); -} - -TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) -{ - TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion(); - TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion(); - switch (mOp) + // Nodes may be constant folded without being qualified as constant. + TQualifier resultQualifier = EvqConst; + if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) { - case EOpIndexDirect: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return nullptr; - } - int index = rightConstant->getIConst(0); - - const TConstantUnion *constArray = leftConstant->foldIndexing(index); - return CreateFoldedNode(constArray, this, mType.getQualifier()); - } - case EOpIndexDirectStruct: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return nullptr; - } - const TFieldList &fields = mLeft->getType().getStruct()->fields(); - size_t index = static_cast<size_t>(rightConstant->getIConst(0)); - - size_t previousFieldsSize = 0; - for (size_t i = 0; i < index; ++i) - { - previousFieldsSize += fields[i]->type()->getObjectSize(); - } - - const TConstantUnion *constArray = leftConstant->getUnionArrayPointer(); - return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier()); - } - case EOpIndexIndirect: - case EOpIndexDirectInterfaceBlock: - // Can never be constant folded. - return nullptr; - default: - { - if (leftConstant == nullptr || rightConstant == nullptr) - { - return nullptr; - } - TConstantUnion *constArray = - leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine()); - - // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, mType.getQualifier()); - } + resultQualifier = EvqTemporary; } + return CreateFoldedNode(constArray, this, resultQualifier); } -TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) +TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink) { TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); if (operandConstant == nullptr) @@ -1188,18 +801,19 @@ TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) case EOpUnpackUnorm2x16: case EOpPackHalf2x16: case EOpUnpackHalf2x16: - constArray = operandConstant->foldUnaryNonComponentWise(mOp); - break; + constArray = operandConstant->foldUnaryWithDifferentReturnType(mOp, infoSink); + break; default: - constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics); - break; + constArray = operandConstant->foldUnaryWithSameReturnType(mOp, infoSink); + break; } // Nodes may be constant folded without being qualified as constant. - return CreateFoldedNode(constArray, this, mType.getQualifier()); + TQualifier resultQualifier = mOperand->getQualifier() == EvqConst ? EvqConst : EvqTemporary; + return CreateFoldedNode(constArray, this, resultQualifier); } -TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) +TIntermTyped *TIntermAggregate::fold(TInfoSink &infoSink) { // Make sure that all params are constant before actual constant folding. for (auto *param : *getSequence()) @@ -1211,9 +825,9 @@ TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) } TConstantUnion *constArray = nullptr; if (isConstructor()) - constArray = TIntermConstantUnion::FoldAggregateConstructor(this); + constArray = TIntermConstantUnion::FoldAggregateConstructor(this, infoSink); else - constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics); + constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, infoSink); // Nodes may be constant folded without being qualified as constant. TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary; @@ -1228,13 +842,15 @@ TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics) // TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUnion *rightNode, - TDiagnostics *diagnostics, - const TSourceLoc &line) + TDiagnostics *diagnostics) { const TConstantUnion *leftArray = getUnionArrayPointer(); const TConstantUnion *rightArray = rightNode->getUnionArrayPointer(); - ASSERT(leftArray && rightArray); + if (!leftArray) + return nullptr; + if (!rightArray) + return nullptr; size_t objectSize = getType().getObjectSize(); @@ -1257,12 +873,12 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, case EOpAdd: resultArray = new TConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) - resultArray[i] = TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line); + resultArray[i] = leftArray[i] + rightArray[i]; break; case EOpSub: resultArray = new TConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) - resultArray[i] = TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line); + resultArray[i] = leftArray[i] - rightArray[i]; break; case EOpMul: @@ -1270,12 +886,11 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, case EOpMatrixTimesScalar: resultArray = new TConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) - resultArray[i] = TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line); + resultArray[i] = leftArray[i] * rightArray[i]; break; case EOpMatrixTimesMatrix: { - // TODO(jmadll): This code should check for overflows. ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat); const int leftCols = getCols(); @@ -1334,42 +949,14 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, } else { - int lhs = leftArray[i].getIConst(); - int divisor = rightArray[i].getIConst(); if (op == EOpDiv) { - // Check for the special case where the minimum representable number is - // divided by -1. If left alone this leads to integer overflow in C++. - // ESSL 3.00.6 section 4.1.3 Integers: - // "However, for the case where the minimum representable value is - // divided by -1, it is allowed to return either the minimum - // representable value or the maximum representable value." - if (lhs == -0x7fffffff - 1 && divisor == -1) - { - resultArray[i].setIConst(0x7fffffff); - } - else - { - resultArray[i].setIConst(lhs / divisor); - } + resultArray[i].setIConst(leftArray[i].getIConst() / rightArray[i].getIConst()); } else { ASSERT(op == EOpIMod); - if (lhs < 0 || divisor < 0) - { - // ESSL 3.00.6 section 5.9: Results of modulus are undefined when - // either one of the operands is negative. - diagnostics->warning(getLine(), - "Negative modulus operator operand " - "encountered during constant folding", - "%", ""); - resultArray[i].setIConst(0); - } - else - { - resultArray[i].setIConst(lhs % divisor); - } + resultArray[i].setIConst(leftArray[i].getIConst() % rightArray[i].getIConst()); } } break; @@ -1405,7 +992,6 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, case EOpMatrixTimesVector: { - // TODO(jmadll): This code should check for overflows. ASSERT(rightNode->getBasicType() == EbtFloat); const int matrixCols = getCols(); @@ -1428,7 +1014,6 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, case EOpVectorTimesMatrix: { - // TODO(jmadll): This code should check for overflows. ASSERT(getType().getBasicType() == EbtFloat); const int matrixCols = rightNode->getType().getCols(); @@ -1498,12 +1083,12 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, case EOpBitShiftLeft: resultArray = new TConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) - resultArray[i] = TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line); + resultArray[i] = leftArray[i] << rightArray[i]; break; case EOpBitShiftRight: resultArray = new TConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) - resultArray[i] = TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line); + resultArray[i] = leftArray[i] >> rightArray[i]; break; case EOpLessThan: @@ -1561,22 +1146,29 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, return resultArray; } -// The fold functions do operations on a constant at GLSL compile time, without generating run-time -// code. Returns the constant value to keep using. Nullptr should not be returned. -TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the constant value to keep using or nullptr. +// +TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink) { - // Do operations where the return type may have a different number of components compared to the - // operand type. + // + // Do operations where the return type has a different number of components compared to the operand type. + // const TConstantUnion *operandArray = getUnionArrayPointer(); - ASSERT(operandArray); + if (!operandArray) + return nullptr; size_t objectSize = getType().getObjectSize(); TConstantUnion *resultArray = nullptr; switch (op) { - case EOpAny: - ASSERT(getType().getBasicType() == EbtBool); + case EOpAny: + if (getType().getBasicType() == EbtBool) + { resultArray = new TConstantUnion(); resultArray->setBConst(false); for (size_t i = 0; i < objectSize; i++) @@ -1588,9 +1180,16 @@ TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) } } break; + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpAll: - ASSERT(getType().getBasicType() == EbtBool); + case EOpAll: + if (getType().getBasicType() == EbtBool) + { resultArray = new TConstantUnion(); resultArray->setBConst(true); for (size_t i = 0; i < objectSize; i++) @@ -1602,55 +1201,89 @@ TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) } } break; + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpLength: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpLength: + if (getType().getBasicType() == EbtFloat) + { resultArray = new TConstantUnion(); resultArray->setFConst(VectorLength(operandArray, objectSize)); break; + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpTranspose: + case EOpTranspose: + if (getType().getBasicType() == EbtFloat) { - ASSERT(getType().getBasicType() == EbtFloat); resultArray = new TConstantUnion[objectSize]; angle::Matrix<float> result = GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose(); SetUnionArrayFromMatrix(result, resultArray); break; } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpDeterminant: + case EOpDeterminant: + if (getType().getBasicType() == EbtFloat) { - ASSERT(getType().getBasicType() == EbtFloat); unsigned int size = getType().getNominalSize(); ASSERT(size >= 2 && size <= 4); resultArray = new TConstantUnion(); resultArray->setFConst(GetMatrix(operandArray, size).determinant()); break; } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpInverse: + case EOpInverse: + if (getType().getBasicType() == EbtFloat) { - ASSERT(getType().getBasicType() == EbtFloat); unsigned int size = getType().getNominalSize(); ASSERT(size >= 2 && size <= 4); - resultArray = new TConstantUnion[objectSize]; + resultArray = new TConstantUnion[objectSize]; angle::Matrix<float> result = GetMatrix(operandArray, size).inverse(); SetUnionArrayFromMatrix(result, resultArray); break; } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpPackSnorm2x16: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpPackSnorm2x16: + if (getType().getBasicType() == EbtFloat) + { ASSERT(getType().getNominalSize() == 2); resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); + resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); break; + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpUnpackSnorm2x16: + case EOpUnpackSnorm2x16: + if (getType().getBasicType() == EbtUInt) { - ASSERT(getType().getBasicType() == EbtUInt); resultArray = new TConstantUnion[2]; float f1, f2; gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2); @@ -1658,18 +1291,29 @@ TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) resultArray[1].setFConst(f2); break; } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpPackUnorm2x16: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpPackUnorm2x16: + if (getType().getBasicType() == EbtFloat) + { ASSERT(getType().getNominalSize() == 2); resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); + resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); break; + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpUnpackUnorm2x16: + case EOpUnpackUnorm2x16: + if (getType().getBasicType() == EbtUInt) { - ASSERT(getType().getBasicType() == EbtUInt); resultArray = new TConstantUnion[2]; float f1, f2; gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2); @@ -1677,18 +1321,29 @@ TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) resultArray[1].setFConst(f2); break; } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpPackHalf2x16: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpPackHalf2x16: + if (getType().getBasicType() == EbtFloat) + { ASSERT(getType().getNominalSize() == 2); resultArray = new TConstantUnion(); - resultArray->setUConst( - gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); + resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); break; + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } - case EOpUnpackHalf2x16: + case EOpUnpackHalf2x16: + if (getType().getBasicType() == EbtUInt) { - ASSERT(getType().getBasicType() == EbtUInt); resultArray = new TConstantUnion[2]; float f1, f2; gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2); @@ -1696,24 +1351,29 @@ TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op) resultArray[1].setFConst(f2); break; } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; + } + break; - default: - UNREACHABLE(); - break; + default: + break; } return resultArray; } -TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, - TDiagnostics *diagnostics) +TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink) { - // Do unary operations where each component of the result is computed based on the corresponding - // component of the operand. Also folds normalize, though the divisor in that case takes all - // components into account. + // + // Do unary operations where the return type is the same as operand type. + // const TConstantUnion *operandArray = getUnionArrayPointer(); - ASSERT(operandArray); + if (!operandArray) + return nullptr; size_t objectSize = getType().getObjectSize(); @@ -1722,232 +1382,243 @@ TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, { switch(op) { - case EOpNegative: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(-operandArray[i].getFConst()); - break; - case EbtInt: - if (operandArray[i] == std::numeric_limits<int>::min()) - { - // The minimum representable integer doesn't have a positive - // counterpart, rather the negation overflows and in ESSL is supposed to - // wrap back to the minimum representable integer. Make sure that we - // don't actually let the negation overflow, which has undefined - // behavior in C++. - resultArray[i].setIConst(std::numeric_limits<int>::min()); - } - else - { - resultArray[i].setIConst(-operandArray[i].getIConst()); - } - break; - case EbtUInt: - if (operandArray[i] == 0x80000000u) - { - resultArray[i].setUConst(0x80000000u); - } - else - { - resultArray[i].setUConst(static_cast<unsigned int>( - -static_cast<int>(operandArray[i].getUConst()))); - } - break; - default: - UNREACHABLE(); - return nullptr; - } + case EOpNegative: + switch (getType().getBasicType()) + { + case EbtFloat: + resultArray[i].setFConst(-operandArray[i].getFConst()); + break; + case EbtInt: + resultArray[i].setIConst(-operandArray[i].getIConst()); break; + case EbtUInt: + resultArray[i].setUConst(static_cast<unsigned int>( + -static_cast<int>(operandArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; + } + break; - case EOpPositive: - switch (getType().getBasicType()) - { - case EbtFloat: - resultArray[i].setFConst(operandArray[i].getFConst()); - break; - case EbtInt: - resultArray[i].setIConst(operandArray[i].getIConst()); - break; - case EbtUInt: - resultArray[i].setUConst(static_cast<unsigned int>( - static_cast<int>(operandArray[i].getUConst()))); - break; - default: - UNREACHABLE(); - return nullptr; - } + case EOpPositive: + switch (getType().getBasicType()) + { + case EbtFloat: + resultArray[i].setFConst(operandArray[i].getFConst()); break; + case EbtInt: + resultArray[i].setIConst(operandArray[i].getIConst()); + break; + case EbtUInt: + resultArray[i].setUConst(static_cast<unsigned int>( + static_cast<int>(operandArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; + } + break; - case EOpLogicalNot: - switch (getType().getBasicType()) - { - case EbtBool: - resultArray[i].setBConst(!operandArray[i].getBConst()); - break; - default: - UNREACHABLE(); - return nullptr; - } + case EOpLogicalNot: + // this code is written for possible future use, + // will not get executed currently + switch (getType().getBasicType()) + { + case EbtBool: + resultArray[i].setBConst(!operandArray[i].getBConst()); break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; + } + break; - case EOpBitwiseNot: - switch (getType().getBasicType()) - { - case EbtInt: - resultArray[i].setIConst(~operandArray[i].getIConst()); - break; - case EbtUInt: - resultArray[i].setUConst(~operandArray[i].getUConst()); - break; - default: - UNREACHABLE(); - return nullptr; - } + case EOpBitwiseNot: + switch (getType().getBasicType()) + { + case EbtInt: + resultArray[i].setIConst(~operandArray[i].getIConst()); + break; + case EbtUInt: + resultArray[i].setUConst(~operandArray[i].getUConst()); break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; + } + break; - case EOpRadians: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpRadians: + if (getType().getBasicType() == EbtFloat) + { resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst()); break; + } + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; - case EOpDegrees: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpDegrees: + if (getType().getBasicType() == EbtFloat) + { resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst()); break; + } + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; - case EOpSin: - foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]); - break; + case EOpSin: + if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpCos: - foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]); - break; + case EOpCos: + if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpTan: - foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]); - break; + case EOpTan: + if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpAsin: - // For asin(x), results are undefined if |x| > 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) > 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]); - break; + case EOpAsin: + // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpAcos: - // For acos(x), results are undefined if |x| > 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) > 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]); - break; + case EOpAcos: + // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpAtan: - foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]); - break; + case EOpAtan: + if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpSinh: - foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]); - break; + case EOpSinh: + if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpCosh: - foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]); - break; + case EOpCosh: + if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpTanh: - foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]); - break; + case EOpTanh: + if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpAsinh: - foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]); - break; + case EOpAsinh: + if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpAcosh: - // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. - if (operandArray[i].getFConst() < 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]); - break; + case EOpAcosh: + // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpAtanh: - // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to - // 0. - if (fabsf(operandArray[i].getFConst()) >= 1.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]); + case EOpAtanh: + // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i])) + return nullptr; + break; + + case EOpAbs: + switch (getType().getBasicType()) + { + case EbtFloat: + resultArray[i].setFConst(fabsf(operandArray[i].getFConst())); + break; + case EbtInt: + resultArray[i].setIConst(abs(operandArray[i].getIConst())); break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; + } + break; - case EOpAbs: - switch (getType().getBasicType()) + case EOpSign: + switch (getType().getBasicType()) + { + case EbtFloat: { - case EbtFloat: - resultArray[i].setFConst(fabsf(operandArray[i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst(abs(operandArray[i].getIConst())); - break; - default: - UNREACHABLE(); - return nullptr; + float fConst = operandArray[i].getFConst(); + float fResult = 0.0f; + if (fConst > 0.0f) + fResult = 1.0f; + else if (fConst < 0.0f) + fResult = -1.0f; + resultArray[i].setFConst(fResult); } break; - - case EOpSign: - switch (getType().getBasicType()) + case EbtInt: { - case EbtFloat: - { - float fConst = operandArray[i].getFConst(); - float fResult = 0.0f; - if (fConst > 0.0f) - fResult = 1.0f; - else if (fConst < 0.0f) - fResult = -1.0f; - resultArray[i].setFConst(fResult); - break; - } - case EbtInt: - { - int iConst = operandArray[i].getIConst(); - int iResult = 0; - if (iConst > 0) - iResult = 1; - else if (iConst < 0) - iResult = -1; - resultArray[i].setIConst(iResult); - break; - } - default: - UNREACHABLE(); - return nullptr; + int iConst = operandArray[i].getIConst(); + int iResult = 0; + if (iConst > 0) + iResult = 1; + else if (iConst < 0) + iResult = -1; + resultArray[i].setIConst(iResult); } break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; + } + break; - case EOpFloor: - foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]); - break; + case EOpFloor: + if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpTrunc: - foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]); - break; + case EOpTrunc: + if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpRound: - foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]); - break; + case EOpRound: + if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpRoundEven: + case EOpRoundEven: + if (getType().getBasicType() == EbtFloat) { - ASSERT(getType().getBasicType() == EbtFloat); float x = operandArray[i].getFConst(); float result; float fractPart = modff(x, &result); @@ -1958,151 +1629,197 @@ TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op, resultArray[i].setFConst(result); break; } + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; - case EOpCeil: - foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]); - break; + case EOpCeil: + if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpFract: + case EOpFract: + if (getType().getBasicType() == EbtFloat) { - ASSERT(getType().getBasicType() == EbtFloat); float x = operandArray[i].getFConst(); resultArray[i].setFConst(x - floorf(x)); break; } + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; - case EOpIsNan: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpIsNan: + if (getType().getBasicType() == EbtFloat) + { resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst())); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpIsInf: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpIsInf: + if (getType().getBasicType() == EbtFloat) + { resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst())); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpFloatBitsToInt: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpFloatBitsToInt: + if (getType().getBasicType() == EbtFloat) + { resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst())); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpFloatBitsToUint: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpFloatBitsToUint: + if (getType().getBasicType() == EbtFloat) + { resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst())); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpIntBitsToFloat: - ASSERT(getType().getBasicType() == EbtInt); + case EOpIntBitsToFloat: + if (getType().getBasicType() == EbtInt) + { resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst())); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpUintBitsToFloat: - ASSERT(getType().getBasicType() == EbtUInt); + case EOpUintBitsToFloat: + if (getType().getBasicType() == EbtUInt) + { resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst())); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpExp: - foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]); - break; + case EOpExp: + if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpLog: - // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); - break; + case EOpLog: + // For log(x), results are undefined if x <= 0, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpExp2: - foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]); - break; + case EOpExp2: + if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpLog2: - // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. - // And log2f is not available on some plarforms like old android, so just using - // log(x)/log(2) here. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - { - foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]); - resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); - } - break; + case EOpLog2: + // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. + // And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here. + if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i])) + return nullptr; + else + resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); + break; - case EOpSqrt: - // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. - if (operandArray[i].getFConst() < 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); - break; + case EOpSqrt: + // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i])) + return nullptr; + break; - case EOpInverseSqrt: - // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), - // so getting the square root first using builtin function sqrt() and then taking - // its inverse. - // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set - // result to 0. - if (operandArray[i].getFConst() <= 0.0f) - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); - else - { - foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]); - resultArray[i].setFConst(1.0f / resultArray[i].getFConst()); - } - break; + case EOpInverseSqrt: + // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), + // so getting the square root first using builtin function sqrt() and then taking its inverse. + // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set result to 0. + if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f) + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); + else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i])) + return nullptr; + else + resultArray[i].setFConst(1.0f / resultArray[i].getFConst()); + break; - case EOpVectorLogicalNot: - ASSERT(getType().getBasicType() == EbtBool); + case EOpVectorLogicalNot: + if (getType().getBasicType() == EbtBool) + { resultArray[i].setBConst(!operandArray[i].getBConst()); break; + } + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return nullptr; - case EOpNormalize: + case EOpNormalize: + if (getType().getBasicType() == EbtFloat) { - ASSERT(getType().getBasicType() == EbtFloat); - float x = operandArray[i].getFConst(); + float x = operandArray[i].getFConst(); float length = VectorLength(operandArray, objectSize); if (length) resultArray[i].setFConst(x / length); else - UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), - diagnostics, &resultArray[i]); + UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, + &resultArray[i]); break; } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - case EOpDFdx: - case EOpDFdy: - case EOpFwidth: - ASSERT(getType().getBasicType() == EbtFloat); + case EOpDFdx: + case EOpDFdy: + case EOpFwidth: + if (getType().getBasicType() == EbtFloat) + { // Derivatives of constant arguments should be 0. resultArray[i].setFConst(0.0f); break; + } + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); + return nullptr; - default: - return nullptr; + default: + return nullptr; } } return resultArray; } -void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, - FloatTypeUnaryFunc builtinFunc, - TConstantUnion *result) const +bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, FloatTypeUnaryFunc builtinFunc, + TInfoSink &infoSink, TConstantUnion *result) const { ASSERT(builtinFunc); - ASSERT(getType().getBasicType() == EbtFloat); - result->setFConst(builtinFunc(parameter.getFConst())); + if (getType().getBasicType() == EbtFloat) + { + result->setFConst(builtinFunc(parameter.getFConst())); + return true; + } + + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return false; } // static -TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate) +TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate, + TInfoSink &infoSink) { ASSERT(aggregate->getSequence()->size() > 0u); size_t resultSize = aggregate->getType().getObjectSize(); @@ -2201,8 +1918,7 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate } // static -TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics) +TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink) { TOperator op = aggregate->getOp(); TIntermSequence *sequence = aggregate->getSequence(); @@ -2243,298 +1959,284 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg // switch (op) { - case EOpAtan: + case EOpAtan: { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) + if (basicType == EbtFloat) { - float y = unionArrays[0][i].getFConst(); - float x = unionArrays[1][i].getFConst(); - // Results are undefined if x and y are both 0. - if (x == 0.0f && y == 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setFConst(atan2f(y, x)); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float y = unionArrays[0][i].getFConst(); + float x = unionArrays[1][i].getFConst(); + // Results are undefined if x and y are both 0. + if (x == 0.0f && y == 0.0f) + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); + else + resultArray[i].setFConst(atan2f(y, x)); + } } - break; + else + UNREACHABLE(); } + break; - case EOpPow: + case EOpPow: { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) + if (basicType == EbtFloat) { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - // Results are undefined if x < 0. - // Results are undefined if x = 0 and y <= 0. - if (x < 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else if (x == 0.0f && y <= 0.0f) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - else - resultArray[i].setFConst(powf(x, y)); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + // Results are undefined if x < 0. + // Results are undefined if x = 0 and y <= 0. + if (x < 0.0f) + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); + else if (x == 0.0f && y <= 0.0f) + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); + else + resultArray[i].setFConst(powf(x, y)); + } } - break; + else + UNREACHABLE(); } + break; - case EOpMod: + case EOpMod: { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) + if (basicType == EbtFloat) { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - resultArray[i].setFConst(x - y * floorf(x / y)); + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + { + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + resultArray[i].setFConst(x - y * floorf(x / y)); + } } - break; + else + UNREACHABLE(); } + break; - case EOpMin: + case EOpMin: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(), - unionArrays[1][i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(), - unionArrays[1][i].getIConst())); - break; - case EbtUInt: - resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(), - unionArrays[1][i].getUConst())); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); + break; + case EbtInt: + resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); + break; + case EbtUInt: + resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpMax: + case EOpMax: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(), - unionArrays[1][i].getFConst())); - break; - case EbtInt: - resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(), - unionArrays[1][i].getIConst())); - break; - case EbtUInt: - resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(), - unionArrays[1][i].getUConst())); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst())); + break; + case EbtInt: + resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst())); + break; + case EbtUInt: + resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst())); + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpStep: + case EOpStep: { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) - resultArray[i].setFConst( - unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f - : 1.0f); - break; + if (basicType == EbtFloat) + { + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) + resultArray[i].setFConst(unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f); + } + else + UNREACHABLE(); } + break; - case EOpLessThan: + case EOpLessThan: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() < - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() < - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() < - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() < unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() < unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() < unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpLessThanEqual: + case EOpLessThanEqual: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() <= - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() <= - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() <= - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() <= unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() <= unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() <= unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpGreaterThan: + case EOpGreaterThan: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() > - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() > - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() > - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() > unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() > unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() > unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; } } - break; } - case EOpGreaterThanEqual: + break; + + case EOpGreaterThanEqual: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() >= - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() >= - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() >= - unionArrays[1][i].getUConst()); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() >= unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() >= unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() >= unionArrays[1][i].getUConst()); + break; + default: + UNREACHABLE(); + break; } } } break; - case EOpVectorEqual: + case EOpVectorEqual: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() == - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() == - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() == - unionArrays[1][i].getUConst()); - break; - case EbtBool: - resultArray[i].setBConst(unionArrays[0][i].getBConst() == - unionArrays[1][i].getBConst()); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() == unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() == unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() == unionArrays[1][i].getUConst()); + break; + case EbtBool: + resultArray[i].setBConst(unionArrays[0][i].getBConst() == unionArrays[1][i].getBConst()); + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpVectorNotEqual: + case EOpVectorNotEqual: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: - resultArray[i].setBConst(unionArrays[0][i].getFConst() != - unionArrays[1][i].getFConst()); - break; - case EbtInt: - resultArray[i].setBConst(unionArrays[0][i].getIConst() != - unionArrays[1][i].getIConst()); - break; - case EbtUInt: - resultArray[i].setBConst(unionArrays[0][i].getUConst() != - unionArrays[1][i].getUConst()); - break; - case EbtBool: - resultArray[i].setBConst(unionArrays[0][i].getBConst() != - unionArrays[1][i].getBConst()); - break; - default: - UNREACHABLE(); - break; + case EbtFloat: + resultArray[i].setBConst(unionArrays[0][i].getFConst() != unionArrays[1][i].getFConst()); + break; + case EbtInt: + resultArray[i].setBConst(unionArrays[0][i].getIConst() != unionArrays[1][i].getIConst()); + break; + case EbtUInt: + resultArray[i].setBConst(unionArrays[0][i].getUConst() != unionArrays[1][i].getUConst()); + break; + case EbtBool: + resultArray[i].setBConst(unionArrays[0][i].getBConst() != unionArrays[1][i].getBConst()); + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpDistance: + case EOpDistance: + if (basicType == EbtFloat) { - ASSERT(basicType == EbtFloat); TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize]; - resultArray = new TConstantUnion(); + resultArray = new TConstantUnion(); for (size_t i = 0; i < maxObjectSize; i++) { float x = unionArrays[0][i].getFConst(); @@ -2542,40 +2244,47 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg distanceArray[i].setFConst(x - y); } resultArray->setFConst(VectorLength(distanceArray, maxObjectSize)); - break; } + else + UNREACHABLE(); + break; + + case EOpDot: - case EOpDot: - ASSERT(basicType == EbtFloat); + if (basicType == EbtFloat) + { resultArray = new TConstantUnion(); - resultArray->setFConst( - VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); - break; + resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); + } + else + UNREACHABLE(); + break; - case EOpCross: + case EOpCross: + if (basicType == EbtFloat && maxObjectSize == 3) { - ASSERT(basicType == EbtFloat && maxObjectSize == 3); resultArray = new TConstantUnion[maxObjectSize]; - float x0 = unionArrays[0][0].getFConst(); - float x1 = unionArrays[0][1].getFConst(); - float x2 = unionArrays[0][2].getFConst(); - float y0 = unionArrays[1][0].getFConst(); - float y1 = unionArrays[1][1].getFConst(); - float y2 = unionArrays[1][2].getFConst(); + float x0 = unionArrays[0][0].getFConst(); + float x1 = unionArrays[0][1].getFConst(); + float x2 = unionArrays[0][2].getFConst(); + float y0 = unionArrays[1][0].getFConst(); + float y1 = unionArrays[1][1].getFConst(); + float y2 = unionArrays[1][2].getFConst(); resultArray[0].setFConst(x1 * y2 - y1 * x2); resultArray[1].setFConst(x2 * y0 - y2 * x0); resultArray[2].setFConst(x0 * y1 - y0 * x1); - break; } + else + UNREACHABLE(); + break; - case EOpReflect: + case EOpReflect: + if (basicType == EbtFloat) { - ASSERT(basicType == EbtFloat); // genType reflect (genType I, genType N) : - // For the incident vector I and surface orientation N, returns the reflection - // direction: + // For the incident vector I and surface orientation N, returns the reflection direction: // I - 2 * dot(N, I) * N. - resultArray = new TConstantUnion[maxObjectSize]; + resultArray = new TConstantUnion[maxObjectSize]; float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); for (size_t i = 0; i < maxObjectSize; i++) { @@ -2583,40 +2292,45 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg 2.0f * dotProduct * unionArrays[1][i].getFConst(); resultArray[i].setFConst(result); } - break; } + else + UNREACHABLE(); + break; - case EOpMul: + case EOpMul: + if (basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() && + (*sequence)[1]->getAsTyped()->isMatrix()) { - ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() && - (*sequence)[1]->getAsTyped()->isMatrix()); // Perform component-wise matrix multiplication. resultArray = new TConstantUnion[maxObjectSize]; - int size = (*sequence)[0]->getAsTyped()->getNominalSize(); + int size = (*sequence)[0]->getAsTyped()->getNominalSize(); angle::Matrix<float> result = GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size)); SetUnionArrayFromMatrix(result, resultArray); - break; } + else + UNREACHABLE(); + break; - case EOpOuterProduct: + case EOpOuterProduct: + if (basicType == EbtFloat) { - ASSERT(basicType == EbtFloat); size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize(); size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize(); - resultArray = new TConstantUnion[numRows * numCols]; + resultArray = new TConstantUnion[numRows * numCols]; angle::Matrix<float> result = GetMatrix(unionArrays[0], static_cast<int>(numRows), 1) .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols))); SetUnionArrayFromMatrix(result, resultArray); - break; } - - default: + else UNREACHABLE(); - // TODO: Add constant folding support for other built-in operations that take 2 - // parameters and not handled above. - return nullptr; + break; + + default: + UNREACHABLE(); + // TODO: Add constant folding support for other built-in operations that take 2 parameters and not handled above. + return nullptr; } } else if (paramsCount == 3) @@ -2626,123 +2340,124 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg // switch (op) { - case EOpClamp: + case EOpClamp: { resultArray = new TConstantUnion[maxObjectSize]; for (size_t i = 0; i < maxObjectSize; i++) { switch (basicType) { - case EbtFloat: + case EbtFloat: { - float x = unionArrays[0][i].getFConst(); + float x = unionArrays[0][i].getFConst(); float min = unionArrays[1][i].getFConst(); float max = unionArrays[2][i].getFConst(); // Results are undefined if min > max. if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); else resultArray[i].setFConst(gl::clamp(x, min, max)); - break; } - - case EbtInt: + break; + case EbtInt: { - int x = unionArrays[0][i].getIConst(); + int x = unionArrays[0][i].getIConst(); int min = unionArrays[1][i].getIConst(); int max = unionArrays[2][i].getIConst(); // Results are undefined if min > max. if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); else resultArray[i].setIConst(gl::clamp(x, min, max)); - break; } - case EbtUInt: + break; + case EbtUInt: { - unsigned int x = unionArrays[0][i].getUConst(); + unsigned int x = unionArrays[0][i].getUConst(); unsigned int min = unionArrays[1][i].getUConst(); unsigned int max = unionArrays[2][i].getUConst(); // Results are undefined if min > max. if (min > max) - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); else resultArray[i].setUConst(gl::clamp(x, min, max)); - break; } - default: - UNREACHABLE(); - break; + break; + default: + UNREACHABLE(); + break; } } - break; } + break; - case EOpMix: + case EOpMix: { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) + if (basicType == EbtFloat) { - float x = unionArrays[0][i].getFConst(); - float y = unionArrays[1][i].getFConst(); - TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType(); - if (type == EbtFloat) + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) { - // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. - float a = unionArrays[2][i].getFConst(); - resultArray[i].setFConst(x * (1.0f - a) + y * a); - } - else // 3rd parameter is EbtBool - { - ASSERT(type == EbtBool); - // Selects which vector each returned component comes from. - // For a component of a that is false, the corresponding component of x is - // returned. - // For a component of a that is true, the corresponding component of y is - // returned. - bool a = unionArrays[2][i].getBConst(); - resultArray[i].setFConst(a ? y : x); + float x = unionArrays[0][i].getFConst(); + float y = unionArrays[1][i].getFConst(); + TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType(); + if (type == EbtFloat) + { + // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a. + float a = unionArrays[2][i].getFConst(); + resultArray[i].setFConst(x * (1.0f - a) + y * a); + } + else // 3rd parameter is EbtBool + { + ASSERT(type == EbtBool); + // Selects which vector each returned component comes from. + // For a component of a that is false, the corresponding component of x is returned. + // For a component of a that is true, the corresponding component of y is returned. + bool a = unionArrays[2][i].getBConst(); + resultArray[i].setFConst(a ? y : x); + } } } - break; + else + UNREACHABLE(); } + break; - case EOpSmoothStep: + case EOpSmoothStep: { - ASSERT(basicType == EbtFloat); - resultArray = new TConstantUnion[maxObjectSize]; - for (size_t i = 0; i < maxObjectSize; i++) + if (basicType == EbtFloat) { - float edge0 = unionArrays[0][i].getFConst(); - float edge1 = unionArrays[1][i].getFConst(); - float x = unionArrays[2][i].getFConst(); - // Results are undefined if edge0 >= edge1. - if (edge0 >= edge1) + resultArray = new TConstantUnion[maxObjectSize]; + for (size_t i = 0; i < maxObjectSize; i++) { - UndefinedConstantFoldingError(loc, op, basicType, diagnostics, - &resultArray[i]); - } - else - { - // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth - // Hermite interpolation between 0 and 1 when edge0 < x < edge1. - float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); - resultArray[i].setFConst(t * t * (3.0f - 2.0f * t)); + float edge0 = unionArrays[0][i].getFConst(); + float edge1 = unionArrays[1][i].getFConst(); + float x = unionArrays[2][i].getFConst(); + // Results are undefined if edge0 >= edge1. + if (edge0 >= edge1) + { + UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]); + } + else + { + // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth + // Hermite interpolation between 0 and 1 when edge0 < x < edge1. + float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); + resultArray[i].setFConst(t * t * (3.0f - 2.0f * t)); + } } } - break; + else + UNREACHABLE(); } + break; - case EOpFaceForward: + case EOpFaceForward: + if (basicType == EbtFloat) { - ASSERT(basicType == EbtFloat); // genType faceforward(genType N, genType I, genType Nref) : // If dot(Nref, I) < 0 return N, otherwise return -N. - resultArray = new TConstantUnion[maxObjectSize]; + resultArray = new TConstantUnion[maxObjectSize]; float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize); for (size_t i = 0; i < maxObjectSize; i++) { @@ -2751,42 +2466,43 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg else resultArray[i].setFConst(-unionArrays[0][i].getFConst()); } - break; } + else + UNREACHABLE(); + break; - case EOpRefract: + case EOpRefract: + if (basicType == EbtFloat) { - ASSERT(basicType == EbtFloat); // genType refract(genType I, genType N, float eta) : - // For the incident vector I and surface normal N, and the ratio of indices of - // refraction eta, + // For the incident vector I and surface normal N, and the ratio of indices of refraction eta, // return the refraction vector. The result is computed by // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) // if (k < 0.0) // return genType(0.0) // else // return eta * I - (eta * dot(N, I) + sqrt(k)) * N - resultArray = new TConstantUnion[maxObjectSize]; + resultArray = new TConstantUnion[maxObjectSize]; float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize); for (size_t i = 0; i < maxObjectSize; i++) { float eta = unionArrays[2][i].getFConst(); - float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct); + float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct); if (k < 0.0f) resultArray[i].setFConst(0.0f); else resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() - - (eta * dotProduct + sqrtf(k)) * - unionArrays[1][i].getFConst()); + (eta * dotProduct + sqrtf(k)) * unionArrays[1][i].getFConst()); } - break; } - - default: + else UNREACHABLE(); - // TODO: Add constant folding support for other built-in operations that take 3 - // parameters and not handled above. - return nullptr; + break; + + default: + UNREACHABLE(); + // TODO: Add constant folding support for other built-in operations that take 3 parameters and not handled above. + return nullptr; } } return resultArray; @@ -2815,12 +2531,14 @@ void TIntermTraverser::updateTree() bool inserted = insertion.parent->insertChildNodes(insertion.position + 1, insertion.insertionsAfter); ASSERT(inserted); + UNUSED_ASSERTION_VARIABLE(inserted); } if (!insertion.insertionsBefore.empty()) { bool inserted = insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore); ASSERT(inserted); + UNUSED_ASSERTION_VARIABLE(inserted); } } for (size_t ii = 0; ii < mReplacements.size(); ++ii) @@ -2830,6 +2548,7 @@ void TIntermTraverser::updateTree() bool replaced = replacement.parent->replaceChildNode( replacement.original, replacement.replacement); ASSERT(replaced); + UNUSED_ASSERTION_VARIABLE(replaced); if (!replacement.originalBecomesChildOfReplacement) { @@ -2852,6 +2571,7 @@ void TIntermTraverser::updateTree() bool replaced = replacement.parent->replaceChildNodeWithMultiple( replacement.original, replacement.replacements); ASSERT(replaced); + UNUSED_ASSERTION_VARIABLE(replaced); } clearReplacementQueue(); @@ -2879,5 +2599,3 @@ void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent, bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD); mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild)); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/IntermNode.h b/gfx/angle/src/compiler/translator/IntermNode.h index 94811bd1c..7068685ee 100755 --- a/gfx/angle/src/compiler/translator/IntermNode.h +++ b/gfx/angle/src/compiler/translator/IntermNode.h @@ -27,22 +27,14 @@ #include "compiler/translator/Operator.h" #include "compiler/translator/Types.h" -namespace sh -{ - class TDiagnostics; class TIntermTraverser; class TIntermAggregate; -class TIntermBlock; -class TIntermDeclaration; -class TIntermFunctionDefinition; -class TIntermSwizzle; class TIntermBinary; class TIntermUnary; class TIntermConstantUnion; -class TIntermTernary; -class TIntermIfElse; +class TIntermSelection; class TIntermSwitch; class TIntermCase; class TIntermTyped; @@ -54,7 +46,6 @@ class TIntermRaw; class TIntermBranch; class TSymbolTable; -class TFunction; // Encapsulate an identifier string and track whether it is coming from the original shader code // (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed. @@ -99,15 +90,10 @@ class TIntermNode : angle::NonCopyable virtual void traverse(TIntermTraverser *) = 0; virtual TIntermTyped *getAsTyped() { return 0; } virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } - virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; } virtual TIntermAggregate *getAsAggregate() { return 0; } - virtual TIntermBlock *getAsBlock() { return nullptr; } - virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; } - virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; } virtual TIntermBinary *getAsBinaryNode() { return 0; } virtual TIntermUnary *getAsUnaryNode() { return 0; } - virtual TIntermTernary *getAsTernaryNode() { return nullptr; } - virtual TIntermIfElse *getAsIfElseNode() { return nullptr; } + virtual TIntermSelection *getAsSelectionNode() { return 0; } virtual TIntermSwitch *getAsSwitchNode() { return 0; } virtual TIntermCase *getAsCaseNode() { return 0; } virtual TIntermSymbol *getAsSymbolNode() { return 0; } @@ -155,7 +141,6 @@ class TIntermTyped : public TIntermNode TBasicType getBasicType() const { return mType.getBasicType(); } TQualifier getQualifier() const { return mType.getQualifier(); } TPrecision getPrecision() const { return mType.getPrecision(); } - TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); } int getCols() const { return mType.getCols(); } int getRows() const { return mType.getRows(); } int getNominalSize() const { return mType.getNominalSize(); } @@ -174,9 +159,6 @@ class TIntermTyped : public TIntermNode bool isConstructorWithOnlyConstantUnionParameters(); - static TIntermTyped *CreateIndexNode(int index); - static TIntermTyped *CreateZero(const TType &type); - protected: TType mType; @@ -200,7 +182,7 @@ class TIntermLoop : public TIntermNode TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, - TIntermBlock *body) + TIntermAggregate *body) : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body), mUnrollFlag(false) { } @@ -213,11 +195,11 @@ class TIntermLoop : public TIntermNode TIntermNode *getInit() { return mInit; } TIntermTyped *getCondition() { return mCond; } TIntermTyped *getExpression() { return mExpr; } - TIntermBlock *getBody() { return mBody; } + TIntermAggregate *getBody() { return mBody; } void setCondition(TIntermTyped *condition) { mCond = condition; } void setExpression(TIntermTyped *expression) { mExpr = expression; } - void setBody(TIntermBlock *body) { mBody = body; } + void setBody(TIntermAggregate *body) { mBody = body; } void setUnrollFlag(bool flag) { mUnrollFlag = flag; } bool getUnrollFlag() const { return mUnrollFlag; } @@ -227,7 +209,7 @@ class TIntermLoop : public TIntermNode TIntermNode *mInit; // for-loop initialization TIntermTyped *mCond; // loop exit condition TIntermTyped *mExpr; // for-loop expression - TIntermBlock *mBody; // loop body + TIntermAggregate *mBody; // loop body bool mUnrollFlag; // Whether the loop should be unrolled or not. }; @@ -334,7 +316,6 @@ class TIntermConstantUnion : public TIntermTyped TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type) : TIntermTyped(type), mUnionArrayPointer(unionPointer) { - ASSERT(unionPointer); } TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); } @@ -362,7 +343,6 @@ class TIntermConstantUnion : public TIntermTyped void replaceConstantUnion(const TConstantUnion *safeConstantUnion) { - ASSERT(safeConstantUnion); // Previous union pointer freed on pool deallocation. mUnionArrayPointer = safeConstantUnion; } @@ -373,15 +353,13 @@ class TIntermConstantUnion : public TIntermTyped TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, - TDiagnostics *diagnostics, - const TSourceLoc &line); - const TConstantUnion *foldIndexing(int index); - TConstantUnion *foldUnaryNonComponentWise(TOperator op); - TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics); + TDiagnostics *diagnostics); + TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink); + TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink); - static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate); - static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics); + static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate, + TInfoSink &infoSink); + static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink); protected: // Same data may be shared between multiple constant unions, so it can't be modified. @@ -389,9 +367,7 @@ class TIntermConstantUnion : public TIntermTyped private: typedef float(*FloatTypeUnaryFunc) (float); - void foldFloatTypeUnary(const TConstantUnion ¶meter, - FloatTypeUnaryFunc builtinFunc, - TConstantUnion *result) const; + bool foldFloatTypeUnary(const TConstantUnion ¶meter, FloatTypeUnaryFunc builtinFunc, TInfoSink &infoSink, TConstantUnion *result) const; TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private! }; @@ -403,6 +379,7 @@ class TIntermOperator : public TIntermTyped { public: TOperator getOp() const { return mOp; } + void setOp(TOperator op) { mOp = op; } bool isAssignment() const; bool isMultiplication() const; @@ -423,54 +400,24 @@ class TIntermOperator : public TIntermTyped TOperator mOp; }; -// Node for vector swizzles. -class TIntermSwizzle : public TIntermTyped -{ - public: - // This constructor determines the type of the node based on the operand. - TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets); - - TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); } - - TIntermSwizzle *getAsSwizzleNode() override { return this; }; - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - bool hasSideEffects() const override { return mOperand->hasSideEffects(); } - - TIntermTyped *getOperand() { return mOperand; } - void writeOffsetsAsXYZW(TInfoSinkBase *out) const; - - bool hasDuplicateOffsets() const; - - TIntermTyped *fold(); - - protected: - TIntermTyped *mOperand; - TVector<int> mSwizzleOffsets; - - private: - void promote(); - - TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private! -}; - // // Nodes for all the basic binary math operators. // class TIntermBinary : public TIntermOperator { public: + TIntermBinary(TOperator op) + : TIntermOperator(op), + mAddIndexClamp(false) {} + // This constructor determines the type of the binary node based on the operands and op. + // This is only supported for math/logical ops, not indexing. TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right); TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); } static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right); static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right); - static TQualifier GetCommaQualifier(int shaderVersion, - const TIntermTyped *left, - const TIntermTyped *right); TIntermBinary *getAsBinaryNode() override { return this; }; void traverse(TIntermTraverser *it) override; @@ -481,6 +428,8 @@ class TIntermBinary : public TIntermOperator return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); } + void setLeft(TIntermTyped *node) { mLeft = node; } + void setRight(TIntermTyped *node) { mRight = node; } TIntermTyped *getLeft() const { return mLeft; } TIntermTyped *getRight() const { return mRight; } TIntermTyped *fold(TDiagnostics *diagnostics); @@ -507,7 +456,14 @@ class TIntermBinary : public TIntermOperator class TIntermUnary : public TIntermOperator { public: - TIntermUnary(TOperator op, TIntermTyped *operand); + TIntermUnary(TOperator op, const TType &type) + : TIntermOperator(op, type), + mOperand(NULL), + mUseEmulatedFunction(false) {} + TIntermUnary(TOperator op) + : TIntermOperator(op), + mOperand(NULL), + mUseEmulatedFunction(false) {} TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); } @@ -517,8 +473,10 @@ class TIntermUnary : public TIntermOperator bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); } + void setOperand(TIntermTyped *operand) { mOperand = operand; } TIntermTyped *getOperand() { return mOperand; } - TIntermTyped *fold(TDiagnostics *diagnostics); + void promote(const TType *funcReturnType); + TIntermTyped *fold(TInfoSink &infoSink); void setUseEmulatedFunction() { mUseEmulatedFunction = true; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; } @@ -531,107 +489,22 @@ class TIntermUnary : public TIntermOperator bool mUseEmulatedFunction; private: - void promote(); - TIntermUnary(const TIntermUnary &node); // note: not deleted, just private! }; -class TFunctionSymbolInfo -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TFunctionSymbolInfo() : mId(0) {} - - TFunctionSymbolInfo(const TFunctionSymbolInfo &) = default; - TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &) = default; - - void setFromFunction(const TFunction &function); - - void setNameObj(const TName &name) { mName = name; } - const TName &getNameObj() const { return mName; } - - const TString &getName() const { return mName.getString(); } - void setName(const TString &name) { mName.setString(name); } - bool isMain() const { return mName.getString() == "main("; } - - void setId(int functionId) { mId = functionId; } - int getId() const { return mId; } - private: - TName mName; - int mId; -}; - -// Node for function definitions. -class TIntermFunctionDefinition : public TIntermTyped -{ - public: - // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor - // parameters. - TIntermFunctionDefinition(const TType &type, TIntermAggregate *parameters, TIntermBlock *body) - : TIntermTyped(type), mParameters(parameters), mBody(body) - { - ASSERT(parameters != nullptr); - ASSERT(body != nullptr); - } - - TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - TIntermTyped *deepCopy() const override - { - UNREACHABLE(); - return nullptr; - } - bool hasSideEffects() const override - { - UNREACHABLE(); - return true; - } - - TIntermAggregate *getFunctionParameters() const { return mParameters; } - TIntermBlock *getBody() const { return mBody; } - - TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } - const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } - - private: - TIntermAggregate *mParameters; - TIntermBlock *mBody; - - TFunctionSymbolInfo mFunctionInfo; -}; - typedef TVector<TIntermNode *> TIntermSequence; typedef TVector<int> TQualifierList; -// Interface for node classes that have an arbitrarily sized set of children. -class TIntermAggregateBase -{ - public: - virtual ~TIntermAggregateBase() {} - - virtual TIntermSequence *getSequence() = 0; - virtual const TIntermSequence *getSequence() const = 0; - - bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements); - bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions); - - protected: - TIntermAggregateBase() {} - - bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement); -}; - // // Nodes that operate on an arbitrary sized set of children. // -class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase +class TIntermAggregate : public TIntermOperator { public: TIntermAggregate() : TIntermOperator(EOpNull), mUserDefined(false), + mFunctionId(0), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false) { @@ -639,6 +512,7 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase TIntermAggregate(TOperator op) : TIntermOperator(op), mUserDefined(false), + mFunctionId(0), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false) { @@ -648,22 +522,29 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase // Note: only supported for nodes that can be a part of an expression. TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); } - void setOp(TOperator op) { mOp = op; } - TIntermAggregate *getAsAggregate() override { return this; } void traverse(TIntermTraverser *it) override; bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - + bool replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements); + bool insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions); // Conservatively assume function calls and other aggregate operators have side-effects bool hasSideEffects() const override { return true; } - TIntermTyped *fold(TDiagnostics *diagnostics); + TIntermTyped *fold(TInfoSink &infoSink); - TIntermSequence *getSequence() override { return &mSequence; } - const TIntermSequence *getSequence() const override { return &mSequence; } + TIntermSequence *getSequence() { return &mSequence; } + + void setNameObj(const TName &name) { mName = name; } + const TName &getNameObj() const { return mName; } + + void setName(const TString &name) { mName.setString(name); } + const TString &getName() const { return mName.getString(); } void setUserDefined() { mUserDefined = true; } bool isUserDefined() const { return mUserDefined; } + void setFunctionId(int functionId) { mFunctionId = functionId; } + int getFunctionId() const { return mFunctionId; } + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; } @@ -674,12 +555,11 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase // Returns true if changing parameter precision may affect the return value. bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; } - TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; } - const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; } - protected: TIntermSequence mSequence; + TName mName; bool mUserDefined; // used for user defined function names + int mFunctionId; // If set to true, replace the built-in function call with an emulated one // to work around driver bugs. @@ -687,110 +567,50 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase bool mGotPrecisionFromChildren; - TFunctionSymbolInfo mFunctionInfo; - private: TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! }; -// A list of statements. Either the root node which contains declarations and function definitions, -// or a block that can be marked with curly braces {}. -class TIntermBlock : public TIntermNode, public TIntermAggregateBase -{ - public: - TIntermBlock() : TIntermNode() {} - ~TIntermBlock() {} - - TIntermBlock *getAsBlock() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - // Only intended for initially building the block. - void appendStatement(TIntermNode *statement); - - TIntermSequence *getSequence() override { return &mStatements; } - const TIntermSequence *getSequence() const override { return &mStatements; } - - protected: - TIntermSequence mStatements; -}; - -// Struct, interface block or variable declaration. Can contain multiple variable declarators. -class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase +// +// For if tests. +// +class TIntermSelection : public TIntermTyped { public: - TIntermDeclaration() : TIntermNode() {} - ~TIntermDeclaration() {} - - TIntermDeclaration *getAsDeclarationNode() override { return this; } - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - - // Only intended for initially building the declaration. - // The declarator node should be either TIntermSymbol or TIntermBinary with op set to - // EOpInitialize. - void appendDeclarator(TIntermTyped *declarator); - - TIntermSequence *getSequence() override { return &mDeclarators; } - const TIntermSequence *getSequence() const override { return &mDeclarators; } - protected: - TIntermSequence mDeclarators; -}; + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) + : TIntermTyped(TType(EbtVoid, EbpUndefined)), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, + const TType &type) + : TIntermTyped(type), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} -// For ternary operators like a ? b : c. -class TIntermTernary : public TIntermTyped -{ - public: - TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression); + // Note: only supported for ternary operator nodes. + TIntermTyped *deepCopy() const override { return new TIntermSelection(*this); } void traverse(TIntermTraverser *it) override; bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; - TIntermTyped *getCondition() const { return mCondition; } - TIntermTyped *getTrueExpression() const { return mTrueExpression; } - TIntermTyped *getFalseExpression() const { return mFalseExpression; } - TIntermTernary *getAsTernaryNode() override { return this; } - - TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); } - - bool hasSideEffects() const override - { - return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() || - mFalseExpression->hasSideEffects(); - } - - static TQualifier DetermineQualifier(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression); - - private: - TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private! - - TIntermTyped *mCondition; - TIntermTyped *mTrueExpression; - TIntermTyped *mFalseExpression; -}; - -class TIntermIfElse : public TIntermNode -{ - public: - TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB) - : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB) - { - } - - void traverse(TIntermTraverser *it) override; - bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; + // Conservatively assume selections have side-effects + bool hasSideEffects() const override { return true; } - TIntermTyped *getCondition() const { return mCondition; } - TIntermBlock *getTrueBlock() const { return mTrueBlock; } - TIntermBlock *getFalseBlock() const { return mFalseBlock; } - TIntermIfElse *getAsIfElseNode() override { return this; } + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermNode *getCondition() const { return mCondition; } + TIntermNode *getTrueBlock() const { return mTrueBlock; } + TIntermNode *getFalseBlock() const { return mFalseBlock; } + TIntermSelection *getAsSelectionNode() override { return this; } protected: TIntermTyped *mCondition; - TIntermBlock *mTrueBlock; - TIntermBlock *mFalseBlock; + TIntermNode *mTrueBlock; + TIntermNode *mFalseBlock; + + private: + TIntermSelection(const TIntermSelection &node); // Note: not deleted, just private! }; // @@ -799,8 +619,10 @@ class TIntermIfElse : public TIntermNode class TIntermSwitch : public TIntermNode { public: - TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList) - : TIntermNode(), mInit(init), mStatementList(statementList) + TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList) + : TIntermNode(), + mInit(init), + mStatementList(statementList) { } @@ -811,12 +633,12 @@ class TIntermSwitch : public TIntermNode TIntermSwitch *getAsSwitchNode() override { return this; } TIntermTyped *getInit() { return mInit; } - TIntermBlock *getStatementList() { return mStatementList; } - void setStatementList(TIntermBlock *statementList) { mStatementList = statementList; } + TIntermAggregate *getStatementList() { return mStatementList; } + void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; } protected: TIntermTyped *mInit; - TIntermBlock *mStatementList; + TIntermAggregate *mStatementList; }; // @@ -872,20 +694,12 @@ class TIntermTraverser : angle::NonCopyable virtual void visitSymbol(TIntermSymbol *node) {} virtual void visitRaw(TIntermRaw *node) {} virtual void visitConstantUnion(TIntermConstantUnion *node) {} - virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; } virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; } virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; } - virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; } - virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; } + virtual bool visitSelection(Visit visit, TIntermSelection *node) { return true; } virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; } virtual bool visitCase(Visit visit, TIntermCase *node) { return true; } - virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) - { - return true; - } virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; } - virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; } - virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; } virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; } virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; } @@ -895,17 +709,12 @@ class TIntermTraverser : angle::NonCopyable virtual void traverseSymbol(TIntermSymbol *node); virtual void traverseRaw(TIntermRaw *node); virtual void traverseConstantUnion(TIntermConstantUnion *node); - virtual void traverseSwizzle(TIntermSwizzle *node); virtual void traverseBinary(TIntermBinary *node); virtual void traverseUnary(TIntermUnary *node); - virtual void traverseTernary(TIntermTernary *node); - virtual void traverseIfElse(TIntermIfElse *node); + virtual void traverseSelection(TIntermSelection *node); virtual void traverseSwitch(TIntermSwitch *node); virtual void traverseCase(TIntermCase *node); - virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node); virtual void traverseAggregate(TIntermAggregate *node); - virtual void traverseBlock(TIntermBlock *node); - virtual void traverseDeclaration(TIntermDeclaration *node); virtual void traverseLoop(TIntermLoop *node); virtual void traverseBranch(TIntermBranch *node); @@ -952,7 +761,7 @@ class TIntermTraverser : angle::NonCopyable return nullptr; } - void pushParentBlock(TIntermBlock *node); + void pushParentBlock(TIntermAggregate *node); void incrementParentBlockPos(); void popParentBlock(); @@ -964,14 +773,14 @@ class TIntermTraverser : angle::NonCopyable // To replace a single node with multiple nodes on the parent aggregate node struct NodeReplaceWithMultipleEntry { - NodeReplaceWithMultipleEntry(TIntermAggregateBase *_parent, - TIntermNode *_original, - TIntermSequence _replacements) - : parent(_parent), original(_original), replacements(_replacements) + NodeReplaceWithMultipleEntry(TIntermAggregate *_parent, TIntermNode *_original, TIntermSequence _replacements) + : parent(_parent), + original(_original), + replacements(_replacements) { } - TIntermAggregateBase *parent; + TIntermAggregate *parent; TIntermNode *original; TIntermSequence replacements; }; @@ -979,7 +788,7 @@ class TIntermTraverser : angle::NonCopyable // To insert multiple nodes on the parent aggregate node struct NodeInsertMultipleEntry { - NodeInsertMultipleEntry(TIntermBlock *_parent, + NodeInsertMultipleEntry(TIntermAggregate *_parent, TIntermSequence::size_type _position, TIntermSequence _insertionsBefore, TIntermSequence _insertionsAfter) @@ -990,7 +799,7 @@ class TIntermTraverser : angle::NonCopyable { } - TIntermBlock *parent; + TIntermAggregate *parent; TIntermSequence::size_type position; TIntermSequence insertionsBefore; TIntermSequence insertionsAfter; @@ -1016,11 +825,11 @@ class TIntermTraverser : angle::NonCopyable // Helper to create a temporary symbol node. TIntermSymbol *createTempSymbol(const TType &type); // Create a node that declares but doesn't initialize a temporary symbol. - TIntermDeclaration *createTempDeclaration(const TType &type); + TIntermAggregate *createTempDeclaration(const TType &type); // Create a node that initializes the current temporary symbol with initializer having the given qualifier. - TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier); + TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier); // Create a node that initializes the current temporary symbol with initializer. - TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer); + TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer); // Create a node that assigns rightNode to the current temporary symbol. TIntermBinary *createTempAssignment(TIntermTyped *rightNode); // Increment temporary symbol index. @@ -1082,12 +891,13 @@ class TIntermTraverser : angle::NonCopyable struct ParentBlock { - ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn) - : node(nodeIn), pos(posIn) + ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn) + : node(nodeIn), + pos(posIn) { } - TIntermBlock *node; + TIntermAggregate *node; TIntermSequence::size_type pos; }; @@ -1120,7 +930,6 @@ class TLValueTrackingTraverser : public TIntermTraverser void traverseBinary(TIntermBinary *node) final; void traverseUnary(TIntermUnary *node) final; - void traverseFunctionDefinition(TIntermFunctionDefinition *node) final; void traverseAggregate(TIntermAggregate *node) final; protected: @@ -1189,10 +998,8 @@ class TMaxDepthTraverser : public TIntermTraverser bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); } bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); } - bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); } - bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); } + bool visitSelection(Visit, TIntermSelection *) override { return depthCheck(); } bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); } - bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); } bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); } bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); } @@ -1202,6 +1009,4 @@ class TMaxDepthTraverser : public TIntermTraverser int mDepthLimit; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_INTERMNODE_H_ diff --git a/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.cpp b/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.cpp index dd2054f68..b614d8365 100755 --- a/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.cpp +++ b/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.cpp @@ -12,9 +12,17 @@ #include "compiler/translator/IntermNode.h" -namespace sh +namespace { +bool IsNodeBlock(TIntermNode *node) +{ + ASSERT(node != nullptr); + return (node->getAsAggregate() && node->getAsAggregate()->getOp() == EOpSequence); +} + +} // anonymous namespace + IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask) { } @@ -31,7 +39,7 @@ bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *p if ((mMask & kExpressionReturningArray) != 0) { if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr && - !parentNode->getAsBlock()) + !IsNodeBlock(parentNode)) { return true; } @@ -88,7 +96,7 @@ bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parent if (node->getType().isArray() && !parentIsAssignment && (node->isConstructor() || node->getOp() == EOpFunctionCall) && - !parentNode->getAsBlock()) + !IsNodeBlock(parentNode)) { return true; } @@ -97,13 +105,14 @@ bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parent return false; } -bool IntermNodePatternMatcher::match(TIntermTernary *node) +bool IntermNodePatternMatcher::match(TIntermSelection *node) { if ((mMask & kUnfoldedShortCircuitExpression) != 0) { - return true; + if (node->usesTernaryOperator()) + { + return true; + } } return false; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.h b/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.h index 10f9657ed..be6fc61f7 100755 --- a/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.h +++ b/gfx/angle/src/compiler/translator/IntermNodePatternMatcher.h @@ -11,13 +11,10 @@ #ifndef COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_ #define COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_ -namespace sh -{ - class TIntermAggregate; class TIntermBinary; class TIntermNode; -class TIntermTernary; +class TIntermSelection; class IntermNodePatternMatcher { @@ -45,7 +42,7 @@ class IntermNodePatternMatcher bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere); bool match(TIntermAggregate *node, TIntermNode *parentNode); - bool match(TIntermTernary *node); + bool match(TIntermSelection *node); private: const unsigned int mMask; @@ -53,6 +50,4 @@ class IntermNodePatternMatcher bool matchInternal(TIntermBinary *node, TIntermNode *parentNode); }; -} // namespace sh - #endif diff --git a/gfx/angle/src/compiler/translator/IntermTraverse.cpp b/gfx/angle/src/compiler/translator/IntermTraverse.cpp index 7f91595d4..2f66ba7cd 100755 --- a/gfx/angle/src/compiler/translator/IntermTraverse.cpp +++ b/gfx/angle/src/compiler/translator/IntermTraverse.cpp @@ -8,9 +8,6 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - void TIntermSymbol::traverse(TIntermTraverser *it) { it->traverseSymbol(this); @@ -26,11 +23,6 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it) it->traverseConstantUnion(this); } -void TIntermSwizzle::traverse(TIntermTraverser *it) -{ - it->traverseSwizzle(this); -} - void TIntermBinary::traverse(TIntermTraverser *it) { it->traverseBinary(this); @@ -41,14 +33,9 @@ void TIntermUnary::traverse(TIntermTraverser *it) it->traverseUnary(this); } -void TIntermTernary::traverse(TIntermTraverser *it) +void TIntermSelection::traverse(TIntermTraverser *it) { - it->traverseTernary(this); -} - -void TIntermIfElse::traverse(TIntermTraverser *it) -{ - it->traverseIfElse(this); + it->traverseSelection(this); } void TIntermSwitch::traverse(TIntermTraverser *it) @@ -61,21 +48,6 @@ void TIntermCase::traverse(TIntermTraverser *it) it->traverseCase(this); } -void TIntermFunctionDefinition::traverse(TIntermTraverser *it) -{ - it->traverseFunctionDefinition(this); -} - -void TIntermBlock::traverse(TIntermTraverser *it) -{ - it->traverseBlock(this); -} - -void TIntermDeclaration::traverse(TIntermTraverser *it) -{ - it->traverseDeclaration(this); -} - void TIntermAggregate::traverse(TIntermTraverser *it) { it->traverseAggregate(this); @@ -106,7 +78,7 @@ TIntermTraverser::~TIntermTraverser() { } -void TIntermTraverser::pushParentBlock(TIntermBlock *node) +void TIntermTraverser::pushParentBlock(TIntermAggregate *node) { mParentBlockStack.push_back(ParentBlock(node, 0)); } @@ -154,11 +126,7 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier TIntermSymbol *node = new TIntermSymbol(0, symbolName, type); node->setInternal(true); - - ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal); node->getTypePointer()->setQualifier(qualifier); - // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created - // symbol. This might need to be done in other places as well. return node; } @@ -167,25 +135,27 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type) return createTempSymbol(type, EvqTemporary); } -TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type) +TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type) { - TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); - tempDeclaration->appendDeclarator(createTempSymbol(type)); + TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration); + tempDeclaration->getSequence()->push_back(createTempSymbol(type)); return tempDeclaration; } -TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, - TQualifier qualifier) +TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier) { ASSERT(initializer != nullptr); TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier); - TIntermDeclaration *tempDeclaration = new TIntermDeclaration(); - TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer); - tempDeclaration->appendDeclarator(tempInit); + TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration); + TIntermBinary *tempInit = new TIntermBinary(EOpInitialize); + tempInit->setLeft(tempSymbol); + tempInit->setRight(initializer); + tempInit->setType(tempSymbol->getType()); + tempDeclaration->getSequence()->push_back(tempInit); return tempDeclaration; } -TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer) +TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer) { return createTempInitDeclaration(initializer, EvqTemporary); } @@ -194,7 +164,10 @@ TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode) { ASSERT(rightNode != nullptr); TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType()); - TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode); + TIntermBinary *assignment = new TIntermBinary(EOpAssign); + assignment->setLeft(tempSymbol); + assignment->setRight(rightNode); + assignment->setType(tempSymbol->getType()); return assignment; } @@ -217,14 +190,13 @@ void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequen bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const { ASSERT(callNode->getOp() == EOpFunctionCall); - return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getNameObj()) != - mFunctionMap.end()); + return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end()); } TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode) { ASSERT(isInFunctionMap(callNode)); - return mFunctionMap[callNode->getFunctionSymbolInfo()->getNameObj()]; + return mFunctionMap[callNode->getNameObj()]; } void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter) @@ -261,26 +233,6 @@ void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node) visitConstantUnion(node); } -void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node) -{ - bool visit = true; - - if (preVisit) - visit = visitSwizzle(PreVisit, node); - - if (visit) - { - incrementDepth(node); - - node->getOperand()->traverse(this); - - decrementDepth(); - } - - if (visit && postVisit) - visitSwizzle(PostVisit, node); -} - // // Traverse a binary node. // @@ -442,99 +394,9 @@ void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node) visitUnary(PostVisit, node); } -// Traverse a function definition node. -void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node) -{ - bool visit = true; - - if (preVisit) - visit = visitFunctionDefinition(PreVisit, node); - - if (visit) - { - incrementDepth(node); - mInGlobalScope = false; - - node->getFunctionParameters()->traverse(this); - if (inVisit) - visit = visitFunctionDefinition(InVisit, node); - node->getBody()->traverse(this); - - mInGlobalScope = true; - decrementDepth(); - } - - if (visit && postVisit) - visitFunctionDefinition(PostVisit, node); -} - -// Traverse a block node. -void TIntermTraverser::traverseBlock(TIntermBlock *node) -{ - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitBlock(PreVisit, node); - - if (visit) - { - incrementDepth(node); - pushParentBlock(node); - - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitBlock(InVisit, node); - } - - incrementParentBlockPos(); - } - - popParentBlock(); - decrementDepth(); - } - - if (visit && postVisit) - visitBlock(PostVisit, node); -} - -// Traverse a declaration node. -void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node) -{ - bool visit = true; - - TIntermSequence *sequence = node->getSequence(); - - if (preVisit) - visit = visitDeclaration(PreVisit, node); - - if (visit) - { - incrementDepth(node); - - for (auto *child : *sequence) - { - child->traverse(this); - if (visit && inVisit) - { - if (child != sequence->back()) - visit = visitDeclaration(InVisit, node); - } - } - - decrementDepth(); - } - - if (visit && postVisit) - visitDeclaration(PostVisit, node); -} - +// // Traverse an aggregate node. Same comments in binary node apply here. +// void TIntermTraverser::traverseAggregate(TIntermAggregate *node) { bool visit = true; @@ -548,6 +410,11 @@ void TIntermTraverser::traverseAggregate(TIntermAggregate *node) { incrementDepth(node); + if (node->getOp() == EOpSequence) + pushParentBlock(node); + else if (node->getOp() == EOpFunction) + mInGlobalScope = false; + for (auto *child : *sequence) { child->traverse(this); @@ -556,8 +423,16 @@ void TIntermTraverser::traverseAggregate(TIntermAggregate *node) if (child != sequence->back()) visit = visitAggregate(InVisit, node); } + + if (node->getOp() == EOpSequence) + incrementParentBlockPos(); } + if (node->getOp() == EOpSequence) + popParentBlock(); + else if (node->getOp() == EOpFunction) + mInGlobalScope = true; + decrementDepth(); } @@ -565,24 +440,26 @@ void TIntermTraverser::traverseAggregate(TIntermAggregate *node) visitAggregate(PostVisit, node); } -void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node) -{ - TIntermAggregate *params = node->getFunctionParameters(); - ASSERT(params != nullptr); - ASSERT(params->getOp() == EOpParameters); - addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence()); - - TIntermTraverser::traverseFunctionDefinition(node); -} - void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) { bool visit = true; TIntermSequence *sequence = node->getSequence(); - if (node->getOp() == EOpPrototype) + switch (node->getOp()) { - addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence); + case EOpFunction: + { + TIntermAggregate *params = sequence->front()->getAsAggregate(); + ASSERT(params != nullptr); + ASSERT(params->getOp() == EOpParameters); + addToFunctionMap(node->getNameObj(), params->getSequence()); + break; + } + case EOpPrototype: + addToFunctionMap(node->getNameObj(), sequence); + break; + default: + break; } if (preVisit) @@ -628,6 +505,11 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) } else { + if (node->getOp() == EOpSequence) + pushParentBlock(node); + else if (node->getOp() == EOpFunction) + mInGlobalScope = false; + // Find the built-in function corresponding to this op so that we can determine the // in/out qualifiers of its parameters. TFunction *builtInFunc = nullptr; @@ -669,10 +551,18 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) visit = visitAggregate(InVisit, node); } + if (node->getOp() == EOpSequence) + incrementParentBlockPos(); + ++paramIndex; } setInFunctionCallOutParameter(false); + + if (node->getOp() == EOpSequence) + popParentBlock(); + else if (node->getOp() == EOpFunction) + mInGlobalScope = true; } decrementDepth(); @@ -683,37 +573,14 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) } // -// Traverse a ternary node. Same comments in binary node apply here. +// Traverse a selection node. Same comments in binary node apply here. // -void TIntermTraverser::traverseTernary(TIntermTernary *node) -{ - bool visit = true; - - if (preVisit) - visit = visitTernary(PreVisit, node); - - if (visit) - { - incrementDepth(node); - node->getCondition()->traverse(this); - if (node->getTrueExpression()) - node->getTrueExpression()->traverse(this); - if (node->getFalseExpression()) - node->getFalseExpression()->traverse(this); - decrementDepth(); - } - - if (visit && postVisit) - visitTernary(PostVisit, node); -} - -// Traverse an if-else node. Same comments in binary node apply here. -void TIntermTraverser::traverseIfElse(TIntermIfElse *node) +void TIntermTraverser::traverseSelection(TIntermSelection *node) { bool visit = true; if (preVisit) - visit = visitIfElse(PreVisit, node); + visit = visitSelection(PreVisit, node); if (visit) { @@ -727,7 +594,7 @@ void TIntermTraverser::traverseIfElse(TIntermIfElse *node) } if (visit && postVisit) - visitIfElse(PostVisit, node); + visitSelection(PostVisit, node); } // @@ -766,11 +633,7 @@ void TIntermTraverser::traverseCase(TIntermCase *node) visit = visitCase(PreVisit, node); if (visit && node->getCondition()) - { - incrementDepth(node); node->getCondition()->traverse(this); - decrementDepth(); - } if (visit && postVisit) visitCase(PostVisit, node); @@ -834,5 +697,3 @@ void TIntermTraverser::traverseRaw(TIntermRaw *node) { visitRaw(node); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Intermediate.cpp b/gfx/angle/src/compiler/translator/Intermediate.cpp index 9e3e455ae..b6fefa45e 100755 --- a/gfx/angle/src/compiler/translator/Intermediate.cpp +++ b/gfx/angle/src/compiler/translator/Intermediate.cpp @@ -15,9 +15,6 @@ #include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - //////////////////////////////////////////////////////////////////////////// // // First set of functions are to help build the intermediate representation. @@ -47,30 +44,52 @@ TIntermSymbol *TIntermediate::addSymbol( // Returns the added node. // The caller should set the type of the returned node. // -TIntermTyped *TIntermediate::addIndex(TOperator op, - TIntermTyped *base, - TIntermTyped *index, - const TSourceLoc &line, - TDiagnostics *diagnostics) +TIntermTyped *TIntermediate::addIndex( + TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line) { - TIntermBinary *node = new TIntermBinary(op, base, index); + TIntermBinary *node = new TIntermBinary(op); node->setLine(line); + node->setLeft(base); + node->setRight(index); - TIntermTyped *folded = node->fold(diagnostics); - if (folded) - { - return folded; - } + // caller should set the type return node; } +// +// Add one node as the parent of another that it operates on. +// +// Returns the added node. +// +TIntermTyped *TIntermediate::addUnaryMath( + TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType) +{ + // + // Make a new node for the operator. + // + TIntermUnary *node = new TIntermUnary(op); + node->setLine(line); + node->setOperand(child); + node->promote(funcReturnType); + + TIntermTyped *foldedNode = node->fold(mInfoSink); + if (foldedNode) + return foldedNode; + + return node; +} + +// // This is the safe way to change the operator on an aggregate, as it // does lots of error checking and fixing. Especially for establishing -// a function call's operation on it's set of parameters. +// a function call's operation on it's set of parameters. Sequences +// of instructions are also aggregates, but they just direnctly set +// their operator to EOpSequence. // // Returns an aggregate node, which could be the one passed in if // it was already an aggregate but no operator was set. +// TIntermAggregate *TIntermediate::setAggregateOperator( TIntermNode *node, TOperator op, const TSourceLoc &line) { @@ -141,10 +160,11 @@ TIntermAggregate *TIntermediate::growAggregate( // // Returns an aggregate, unless NULL was passed in for the existing node. // -TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceLoc &line) +TIntermAggregate *TIntermediate::makeAggregate( + TIntermNode *node, const TSourceLoc &line) { - if (node == nullptr) - return nullptr; + if (node == NULL) + return NULL; TIntermAggregate *aggNode = new TIntermAggregate; aggNode->getSequence()->push_back(node); @@ -155,57 +175,70 @@ TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceL } // If the input node is nullptr, return nullptr. -// If the input node is a block node, return it. -// If the input node is not a block node, put it inside a block node and return that. -TIntermBlock *TIntermediate::EnsureBlock(TIntermNode *node) +// If the input node is a sequence (block) node, return it. +// If the input node is not a sequence node, put it inside a sequence node and return that. +TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node) { if (node == nullptr) return nullptr; - TIntermBlock *blockNode = node->getAsBlock(); - if (blockNode != nullptr) - return blockNode; - - blockNode = new TIntermBlock(); - blockNode->setLine(node->getLine()); - blockNode->getSequence()->push_back(node); - return blockNode; + TIntermAggregate *aggNode = node->getAsAggregate(); + if (aggNode != nullptr && aggNode->getOp() == EOpSequence) + return aggNode; + + aggNode = makeAggregate(node, node->getLine()); + aggNode->setOp(EOpSequence); + return aggNode; } +// // For "if" test nodes. There are three children; a condition, // a true path, and a false path. The two paths are in the // nodePair. // -// Returns the node created. -TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond, - TIntermNodePair nodePair, - const TSourceLoc &line) +// Returns the selection node created. +// +TIntermNode *TIntermediate::addSelection( + TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line) { - // For compile time constant conditions, prune the code now. + // + // For compile time constant selections, prune the code and + // test now. + // if (cond->getAsConstantUnion()) { if (cond->getAsConstantUnion()->getBConst(0) == true) { - return EnsureBlock(nodePair.node1); + return nodePair.node1 ? setAggregateOperator( + nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; } else { - return EnsureBlock(nodePair.node2); + return nodePair.node2 ? setAggregateOperator( + nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; } } - TIntermIfElse *node = - new TIntermIfElse(cond, EnsureBlock(nodePair.node1), EnsureBlock(nodePair.node2)); + TIntermSelection *node = new TIntermSelection( + cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2)); node->setLine(line); return node; } -TIntermTyped *TIntermediate::AddComma(TIntermTyped *left, +TIntermTyped *TIntermediate::addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line, int shaderVersion) { + TQualifier resultQualifier = EvqConst; + // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. + if (shaderVersion >= 300 || left->getQualifier() != EvqConst || + right->getQualifier() != EvqConst) + { + resultQualifier = EvqTemporary; + } + TIntermTyped *commaNode = nullptr; if (!left->hasSideEffects()) { @@ -213,53 +246,58 @@ TIntermTyped *TIntermediate::AddComma(TIntermTyped *left, } else { - commaNode = new TIntermBinary(EOpComma, left, right); - commaNode->setLine(line); + commaNode = growAggregate(left, right, line); + commaNode->getAsAggregate()->setOp(EOpComma); + commaNode->setType(right->getType()); } - TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(shaderVersion, left, right); commaNode->getTypePointer()->setQualifier(resultQualifier); return commaNode; } +// // For "?:" test nodes. There are three children; a condition, // a true path, and a false path. The two paths are specified // as separate parameters. // -// Returns the ternary node created, or one of trueExpression and falseExpression if the expression -// could be folded. -TIntermTyped *TIntermediate::AddTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &line) +// Returns the selection node created, or one of trueBlock and falseBlock if the expression could be folded. +// +TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, + const TSourceLoc &line) { + TQualifier resultQualifier = EvqTemporary; + if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst && + falseBlock->getQualifier() == EvqConst) + { + resultQualifier = EvqConst; + } // Note that the node resulting from here can be a constant union without being qualified as // constant. if (cond->getAsConstantUnion()) { - TQualifier resultQualifier = - TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression); if (cond->getAsConstantUnion()->getBConst(0)) { - trueExpression->getTypePointer()->setQualifier(resultQualifier); - return trueExpression; + trueBlock->getTypePointer()->setQualifier(resultQualifier); + return trueBlock; } else { - falseExpression->getTypePointer()->setQualifier(resultQualifier); - return falseExpression; + falseBlock->getTypePointer()->setQualifier(resultQualifier); + return falseBlock; } } - // Make a ternary node. - TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression); + // + // Make a selection node. + // + TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); + node->getTypePointer()->setQualifier(resultQualifier); node->setLine(line); return node; } -TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &line) +TIntermSwitch *TIntermediate::addSwitch( + TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line) { TIntermSwitch *node = new TIntermSwitch(init, statementList); node->setLine(line); @@ -292,22 +330,24 @@ TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *cons return node; } -TIntermTyped *TIntermediate::AddSwizzle(TIntermTyped *baseExpression, - const TVectorFields &fields, - const TSourceLoc &dotLocation) +TIntermTyped *TIntermediate::addSwizzle( + TVectorFields &fields, const TSourceLoc &line) { - TVector<int> fieldsVector; - for (int i = 0; i < fields.num; ++i) - { - fieldsVector.push_back(fields.offsets[i]); - } - TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldsVector); - node->setLine(dotLocation); - TIntermTyped *folded = node->fold(); - if (folded) + TIntermAggregate *node = new TIntermAggregate(EOpSequence); + + node->setLine(line); + TIntermConstantUnion *constIntNode; + TIntermSequence *sequenceVector = node->getSequence(); + TConstantUnion *unionArray; + + for (int i = 0; i < fields.num; i++) { - return folded; + unionArray = new TConstantUnion[1]; + unionArray->setIConst(fields.offsets[i]); + constIntNode = addConstantUnion( + unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); + sequenceVector->push_back(constIntNode); } return node; @@ -320,7 +360,7 @@ TIntermNode *TIntermediate::addLoop( TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, TIntermNode *body, const TSourceLoc &line) { - TIntermNode *node = new TIntermLoop(type, init, cond, expr, EnsureBlock(body)); + TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body)); node->setLine(line); return node; @@ -344,8 +384,34 @@ TIntermBranch* TIntermediate::addBranch( return node; } -TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate, - TDiagnostics *diagnostics) +// +// This is to be executed once the final root is put on top by the parsing +// process. +// +TIntermAggregate *TIntermediate::postProcess(TIntermNode *root) +{ + if (root == nullptr) + return nullptr; + + // + // Finish off the top level sequence, if any + // + TIntermAggregate *aggRoot = root->getAsAggregate(); + if (aggRoot != nullptr && aggRoot->getOp() == EOpNull) + { + aggRoot->setOp(EOpSequence); + } + else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence) + { + aggRoot = new TIntermAggregate(EOpSequence); + aggRoot->setLine(root->getLine()); + aggRoot->getSequence()->push_back(root); + } + + return aggRoot; +} + +TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate) { switch (aggregate->getOp()) { @@ -372,16 +438,14 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate, case EOpFaceForward: case EOpReflect: case EOpRefract: - return aggregate->fold(diagnostics); + return aggregate->fold(mInfoSink); default: // TODO: Add support for folding array constructors if (aggregate->isConstructor() && !aggregate->isArray()) { - return aggregate->fold(diagnostics); + return aggregate->fold(mInfoSink); } // Constant folding not supported for the built-in. return nullptr; } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Intermediate.h b/gfx/angle/src/compiler/translator/Intermediate.h index d712bf953..339daa3e8 100755 --- a/gfx/angle/src/compiler/translator/Intermediate.h +++ b/gfx/angle/src/compiler/translator/Intermediate.h @@ -9,9 +9,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - struct TVectorFields { int offsets[4]; @@ -19,42 +16,38 @@ struct TVectorFields }; // -// Set of helper functions to help build the tree. +// Set of helper functions to help parse and build the tree. // +class TInfoSink; class TIntermediate { public: POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate() {} + TIntermediate(TInfoSink &i) + : mInfoSink(i) { } TIntermSymbol *addSymbol( int id, const TString &, const TType &, const TSourceLoc &); - TIntermTyped *addIndex(TOperator op, - TIntermTyped *base, - TIntermTyped *index, - const TSourceLoc &line, - TDiagnostics *diagnostics); + TIntermTyped *addIndex( + TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &); TIntermTyped *addUnaryMath( TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType); TIntermAggregate *growAggregate( TIntermNode *left, TIntermNode *right, const TSourceLoc &); - static TIntermAggregate *MakeAggregate(TIntermNode *node, const TSourceLoc &line); - static TIntermBlock *EnsureBlock(TIntermNode *node); + TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &); + TIntermAggregate *ensureSequence(TIntermNode *node); TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &); - TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &line); - static TIntermTyped *AddTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &line); - TIntermSwitch *addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &line); + TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &); + TIntermTyped *addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, + const TSourceLoc &line); + TIntermSwitch *addSwitch( + TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line); TIntermCase *addCase( TIntermTyped *condition, const TSourceLoc &line); - static TIntermTyped *AddComma(TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &line, - int shaderVersion); + TIntermTyped *addComma(TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &line, + int shaderVersion); TIntermConstantUnion *addConstantUnion(const TConstantUnion *constantUnion, const TType &type, const TSourceLoc &line); @@ -62,18 +55,17 @@ class TIntermediate TIntermNode *, const TSourceLoc &); TIntermBranch *addBranch(TOperator, const TSourceLoc &); TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); - static TIntermTyped *AddSwizzle(TIntermTyped *baseExpression, - const TVectorFields &fields, - const TSourceLoc &dotLocation); + TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); + TIntermAggregate *postProcess(TIntermNode *root); static void outputTree(TIntermNode *, TInfoSinkBase &); - TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate, TDiagnostics *diagnostics); + TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate); private: void operator=(TIntermediate &); // prevent assignments -}; -} // namespace sh + TInfoSink & mInfoSink; +}; #endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/gfx/angle/src/compiler/translator/LoopInfo.cpp b/gfx/angle/src/compiler/translator/LoopInfo.cpp index 48fa24472..d931a18a2 100755 --- a/gfx/angle/src/compiler/translator/LoopInfo.cpp +++ b/gfx/angle/src/compiler/translator/LoopInfo.cpp @@ -6,9 +6,6 @@ #include "compiler/translator/LoopInfo.h" -namespace sh -{ - namespace { @@ -96,7 +93,8 @@ void TLoopIndexInfo::fillInfo(TIntermLoop *node) // Here we assume all the operations are valid, because the loop node is // already validated in ValidateLimitations. - TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence(); + TIntermSequence *declSeq = + node->getInit()->getAsAggregate()->getSequence(); TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); @@ -211,4 +209,3 @@ void TLoopStack::pop() pop_back(); } -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/LoopInfo.h b/gfx/angle/src/compiler/translator/LoopInfo.h index 393aa64f6..ec73fd0fa 100755 --- a/gfx/angle/src/compiler/translator/LoopInfo.h +++ b/gfx/angle/src/compiler/translator/LoopInfo.h @@ -9,9 +9,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - class TLoopIndexInfo { public: @@ -79,7 +76,5 @@ class TLoopStack : public TVector<TLoopInfo> void pop(); }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_LOOPINFO_H_ diff --git a/gfx/angle/src/compiler/translator/Operator.cpp b/gfx/angle/src/compiler/translator/Operator.cpp index 57878b930..2a6f1e4fc 100755 --- a/gfx/angle/src/compiler/translator/Operator.cpp +++ b/gfx/angle/src/compiler/translator/Operator.cpp @@ -62,6 +62,8 @@ const char *GetOperatorString(TOperator op) case EOpIndexDirectStruct: case EOpIndexDirectInterfaceBlock: return "."; + case EOpVectorSwizzle: return "."; + case EOpRadians: return "radians"; case EOpDegrees: return "degrees"; case EOpSin: return "sin"; diff --git a/gfx/angle/src/compiler/translator/Operator.h b/gfx/angle/src/compiler/translator/Operator.h index f7706f8ed..b3acc5f08 100755 --- a/gfx/angle/src/compiler/translator/Operator.h +++ b/gfx/angle/src/compiler/translator/Operator.h @@ -13,9 +13,12 @@ enum TOperator { EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. EOpFunctionCall, + EOpFunction, // For function definition EOpParameters, // an aggregate listing the parameters to a function + EOpDeclaration, EOpInvariantDeclaration, // Specialized declarations for attributing invariance EOpPrototype, @@ -74,6 +77,8 @@ enum TOperator EOpIndexDirectStruct, EOpIndexDirectInterfaceBlock, + EOpVectorSwizzle, + // // Built-in functions potentially mapped to operators // diff --git a/gfx/angle/src/compiler/translator/OutputESSL.cpp b/gfx/angle/src/compiler/translator/OutputESSL.cpp index e55d6c544..77e0a8fb3 100755 --- a/gfx/angle/src/compiler/translator/OutputESSL.cpp +++ b/gfx/angle/src/compiler/translator/OutputESSL.cpp @@ -6,27 +6,20 @@ #include "compiler/translator/OutputESSL.h" -namespace sh -{ - TOutputESSL::TOutputESSL(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable &symbolTable, - sh::GLenum shaderType, int shaderVersion, - bool forceHighp, - ShCompileOptions compileOptions) + bool forceHighp) : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, - shaderType, shaderVersion, - SH_ESSL_OUTPUT, - compileOptions), + SH_ESSL_OUTPUT), mForceHighp(forceHighp) { } @@ -43,5 +36,3 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision) out << getPrecisionString(precision); return true; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/OutputESSL.h b/gfx/angle/src/compiler/translator/OutputESSL.h index 5b2cb9492..c5a963499 100755 --- a/gfx/angle/src/compiler/translator/OutputESSL.h +++ b/gfx/angle/src/compiler/translator/OutputESSL.h @@ -9,29 +9,22 @@ #include "compiler/translator/OutputGLSLBase.h" -namespace sh -{ - class TOutputESSL : public TOutputGLSLBase { - public: - TOutputESSL(TInfoSinkBase &objSink, +public: + TOutputESSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable &symbolTable, - sh::GLenum shaderType, + NameMap& nameMap, + TSymbolTable& symbolTable, int shaderVersion, - bool forceHighp, - ShCompileOptions compileOptions); + bool forceHighp); - protected: - bool writeVariablePrecision(TPrecision precision) override; +protected: + bool writeVariablePrecision(TPrecision precision) override; - private: +private: bool mForceHighp; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_ diff --git a/gfx/angle/src/compiler/translator/OutputGLSL.cpp b/gfx/angle/src/compiler/translator/OutputGLSL.cpp index fc2b18471..431425020 100755 --- a/gfx/angle/src/compiler/translator/OutputGLSL.cpp +++ b/gfx/angle/src/compiler/translator/OutputGLSL.cpp @@ -6,27 +6,20 @@ #include "compiler/translator/OutputGLSL.h" -namespace sh -{ - -TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink, +TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable &symbolTable, - sh::GLenum shaderType, + NameMap& nameMap, + TSymbolTable& symbolTable, int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) + ShShaderOutput output) : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, - shaderType, shaderVersion, - output, - compileOptions) + output) { } @@ -44,11 +37,11 @@ void TOutputGLSL::visitSymbol(TIntermSymbol *node) { out << "gl_FragDepth"; } - else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput())) + else if (symbol == "gl_FragColor" && IsGLSL130OrNewer(getShaderOutput())) { out << "webgl_FragColor"; } - else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput())) + else if (symbol == "gl_FragData" && IsGLSL130OrNewer(getShaderOutput())) { out << "webgl_FragData"; } @@ -94,8 +87,8 @@ TString TOutputGLSL::translateTextureFunction(TString &name) "textureCubeGradEXT", "textureGrad", NULL, NULL }; - const char **mapping = - (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename; + const char **mapping = (IsGLSL130OrNewer(getShaderOutput())) ? + legacyToCoreRename : simpleRename; for (int i = 0; mapping[i] != NULL; i += 2) { @@ -107,5 +100,3 @@ TString TOutputGLSL::translateTextureFunction(TString &name) return name; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/OutputGLSL.h b/gfx/angle/src/compiler/translator/OutputGLSL.h index d910c0004..9b1aca4ea 100755 --- a/gfx/angle/src/compiler/translator/OutputGLSL.h +++ b/gfx/angle/src/compiler/translator/OutputGLSL.h @@ -9,21 +9,16 @@ #include "compiler/translator/OutputGLSLBase.h" -namespace sh -{ - class TOutputGLSL : public TOutputGLSLBase { public: - TOutputGLSL(TInfoSinkBase &objSink, + TOutputGLSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap &nameMap, - TSymbolTable &symbolTable, - sh::GLenum shaderType, + NameMap& nameMap, + TSymbolTable& symbolTable, int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); + ShShaderOutput output); protected: bool writeVariablePrecision(TPrecision) override; @@ -31,6 +26,4 @@ class TOutputGLSL : public TOutputGLSLBase TString translateTextureFunction(TString &name) override; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_ diff --git a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp index 2c32b2ea5..296eef7d1 100755 --- a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -10,9 +10,6 @@ #include <cfloat> -namespace sh -{ - namespace { TString arrayBrackets(const TType &type) @@ -25,17 +22,16 @@ TString arrayBrackets(const TType &type) bool isSingleStatement(TIntermNode *node) { - if (node->getAsFunctionDefinition()) - { - return false; - } - else if (node->getAsBlock()) + if (const TIntermAggregate *aggregate = node->getAsAggregate()) { - return false; + return (aggregate->getOp() != EOpFunction) && + (aggregate->getOp() != EOpSequence); } - else if (node->getAsIfElseNode()) + else if (const TIntermSelection *selection = node->getAsSelectionNode()) { - return false; + // Ternary operators are usually part of an assignment operator. + // This handles those rare cases in which they are all by themselves. + return selection->usesTernaryOperator(); } else if (node->getAsLoopNode()) { @@ -52,32 +48,6 @@ bool isSingleStatement(TIntermNode *node) return true; } -// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever -// variables with specified layout qualifiers are copied. Additional checks are needed against the -// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted. -// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove -// NeedsToWriteLayoutQualifier. -bool NeedsToWriteLayoutQualifier(const TType &type) -{ - if (type.getBasicType() == EbtInterfaceBlock) - { - return false; - } - - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - - if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) && - layoutQualifier.location >= 0) - { - return true; - } - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - return true; - } - return false; -} - } // namespace TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, @@ -85,10 +55,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable &symbolTable, - sh::GLenum shaderType, int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) + ShShaderOutput output) : TIntermTraverser(true, true, true), mObjSink(objSink), mDeclaringVariables(false), @@ -96,20 +64,9 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, mHashFunction(hashFunction), mNameMap(nameMap), mSymbolTable(symbolTable), - mShaderType(shaderType), mShaderVersion(shaderVersion), - mOutput(output), - mCompileOptions(compileOptions) -{ -} - -void TOutputGLSLBase::writeInvariantQualifier(const TType &type) + mOutput(output) { - if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions)) - { - TInfoSinkBase &out = objSink(); - out << "invariant "; - } } void TOutputGLSLBase::writeTriplet( @@ -134,121 +91,55 @@ void TOutputGLSLBase::writeBuiltInFunctionTriplet( void TOutputGLSLBase::writeLayoutQualifier(const TType &type) { - if (!NeedsToWriteLayoutQualifier(type)) - { - return; - } - - TInfoSinkBase &out = objSink(); - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - out << "layout("; - if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) { + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); if (layoutQualifier.location >= 0) { - out << "location = " << layoutQualifier.location; + TInfoSinkBase &out = objSink(); + out << "layout(location = " << layoutQualifier.location << ") "; } } - - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); - out << getImageInternalFormatString(layoutQualifier.imageInternalFormat); - } - - out << ") "; -} - -const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) -{ - if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 && - (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0) - { - switch (qualifier) - { - // The return string is consistent with sh::getQualifierString() from - // BaseTypes.h minus the "centroid" keyword. - case EvqCentroid: - return ""; - case EvqCentroidIn: - return "smooth in"; - case EvqCentroidOut: - return "smooth out"; - default: - break; - } - } - if (sh::IsGLSL130OrNewer(mOutput)) - { - switch (qualifier) - { - case EvqAttribute: - return "in"; - case EvqVaryingIn: - return "in"; - case EvqVaryingOut: - return "out"; - default: - break; - } - } - return sh::getQualifierString(qualifier); } void TOutputGLSLBase::writeVariableType(const TType &type) { - TQualifier qualifier = type.getQualifier(); TInfoSinkBase &out = objSink(); if (type.isInvariant()) { - writeInvariantQualifier(type); + out << "invariant "; } if (type.getBasicType() == EbtInterfaceBlock) { TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); declareInterfaceBlockLayout(interfaceBlock); } + TQualifier qualifier = type.getQualifier(); if (qualifier != EvqTemporary && qualifier != EvqGlobal) { - const char *qualifierString = mapQualifierToString(qualifier); - if (qualifierString && qualifierString[0] != '\0') + if (IsGLSL130OrNewer(mOutput)) { - out << qualifierString << " "; + switch (qualifier) + { + case EvqAttribute: + out << "in "; + break; + case EvqVaryingIn: + out << "in "; + break; + case EvqVaryingOut: + out << "out "; + break; + default: + out << type.getQualifierString() << " "; + break; + } + } + else + { + out << type.getQualifierString() << " "; } } - - const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); - if (memoryQualifier.readonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "readonly "; - } - - if (memoryQualifier.writeonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "writeonly "; - } - - if (memoryQualifier.coherent) - { - ASSERT(IsImage(type.getBasicType())); - out << "coherent "; - } - - if (memoryQualifier.restrictQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "restrict "; - } - - if (memoryQualifier.volatileQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "volatile "; - } - // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { @@ -286,8 +177,9 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) const TType &type = arg->getType(); writeVariableType(type); - if (!arg->getName().getString().empty()) - out << " " << hashName(arg->getName()); + const TString &name = arg->getSymbol(); + if (!name.empty()) + out << " " << hashName(name); if (type.isArray()) out << arrayBrackets(type); @@ -305,7 +197,7 @@ const TConstantUnion *TOutputGLSLBase::writeConstantUnion( if (type.getBasicType() == EbtStruct) { const TStructure *structure = type.getStruct(); - out << hashName(TName(structure->name())) << "("; + out << hashName(structure->name()) << "("; const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) @@ -379,7 +271,7 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node)) out << mLoopUnrollStack.getLoopIndexValue(node); else - out << hashVariableName(node->getName()); + out << hashVariableName(node->getSymbol()); if (mDeclaringVariables && node->getType().isArray()) out << arrayBrackets(node->getType()); @@ -390,222 +282,241 @@ void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) writeConstantUnion(node->getType(), node->getUnionArrayPointer()); } -bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = objSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) { bool visitChildren = true; TInfoSinkBase &out = objSink(); switch (node->getOp()) { - case EOpComma: - writeTriplet(visit, "(", ", ", ")"); - break; - case EOpInitialize: + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariables = false; + } + break; + case EOpAssign: + writeTriplet(visit, "(", " = ", ")"); + break; + case EOpAddAssign: + writeTriplet(visit, "(", " += ", ")"); + break; + case EOpSubAssign: + writeTriplet(visit, "(", " -= ", ")"); + break; + case EOpDivAssign: + writeTriplet(visit, "(", " /= ", ")"); + break; + case EOpIModAssign: + writeTriplet(visit, "(", " %= ", ")"); + break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + case EOpBitShiftLeftAssign: + writeTriplet(visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + writeTriplet(visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + writeTriplet(visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + writeTriplet(visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + writeTriplet(visit, "(", " |= ", ")"); + break; + + case EOpIndexDirect: + writeTriplet(visit, NULL, "[", "]"); + break; + case EOpIndexIndirect: + if (node->getAddIndexClamp()) + { if (visit == InVisit) { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariables = false; + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "[int(clamp(float("; + else + out << "[webgl_int_clamp("; } - break; - case EOpAssign: - writeTriplet(visit, "(", " = ", ")"); - break; - case EOpAddAssign: - writeTriplet(visit, "(", " += ", ")"); - break; - case EOpSubAssign: - writeTriplet(visit, "(", " -= ", ")"); - break; - case EOpDivAssign: - writeTriplet(visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - writeTriplet(visit, "(", " %= ", ")"); - break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - case EOpBitShiftLeftAssign: - writeTriplet(visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - writeTriplet(visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - writeTriplet(visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - writeTriplet(visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - writeTriplet(visit, "(", " |= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, NULL, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) + else if (visit == PostVisit) { - if (visit == InVisit) + int maxSize; + TIntermTyped *left = node->getLeft(); + TType leftType = left->getType(); + + if (left->isArray()) { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "[int(clamp(float("; - else - out << "[webgl_int_clamp("; + // The shader will fail validation if the array length is not > 0. + maxSize = static_cast<int>(leftType.getArraySize()) - 1; } - else if (visit == PostVisit) + else { - int maxSize; - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (left->isArray()) - { - // The shader will fail validation if the array length is not > 0. - maxSize = static_cast<int>(leftType.getArraySize()) - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "), 0.0, float(" << maxSize << ")))]"; - else - out << ", 0, " << maxSize << ")]"; + maxSize = leftType.getNominalSize() - 1; } + + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "), 0.0, float(" << maxSize << ")))]"; + else + out << ", 0, " << maxSize << ")]"; } - else - { - writeTriplet(visit, NULL, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) - fieldName = hashName(TName(fieldName)); - - out << fieldName; - visitChildren = false; - } - break; - case EOpIndexDirectInterfaceBlock: - if (visit == InVisit) + } + else + { + writeTriplet(visit, NULL, "[", "]"); + } + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. + out << "."; + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpIndexDirectInterfaceBlock: + if (visit == InVisit) + { + out << "."; + const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = interfaceBlock->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion)); + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + TIntermAggregate *rightChild = node->getRight()->getAsAggregate(); + TIntermSequence *sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit) { - out << "."; - const TInterfaceBlock *interfaceBlock = - node->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion)); - fieldName = hashName(TName(fieldName)); - - out << fieldName; - visitChildren = false; + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + ASSERT(element->getBasicType() == EbtInt); + ASSERT(element->getNominalSize() == 1); + const TConstantUnion& data = element->getUnionArrayPointer()[0]; + ASSERT(data.getType() == EbtInt); + switch (data.getIConst()) + { + case 0: + out << "x"; + break; + case 1: + out << "y"; + break; + case 2: + out << "z"; + break; + case 3: + out << "w"; + break; + default: + UNREACHABLE(); + } } - break; + visitChildren = false; + } + break; - case EOpAdd: - writeTriplet(visit, "(", " + ", ")"); - break; - case EOpSub: - writeTriplet(visit, "(", " - ", ")"); - break; - case EOpMul: - writeTriplet(visit, "(", " * ", ")"); - break; - case EOpDiv: - writeTriplet(visit, "(", " / ", ")"); - break; - case EOpIMod: - writeTriplet(visit, "(", " % ", ")"); - break; - case EOpBitShiftLeft: - writeTriplet(visit, "(", " << ", ")"); - break; - case EOpBitShiftRight: - writeTriplet(visit, "(", " >> ", ")"); - break; - case EOpBitwiseAnd: - writeTriplet(visit, "(", " & ", ")"); - break; - case EOpBitwiseXor: - writeTriplet(visit, "(", " ^ ", ")"); - break; - case EOpBitwiseOr: - writeTriplet(visit, "(", " | ", ")"); - break; + case EOpAdd: + writeTriplet(visit, "(", " + ", ")"); + break; + case EOpSub: + writeTriplet(visit, "(", " - ", ")"); + break; + case EOpMul: + writeTriplet(visit, "(", " * ", ")"); + break; + case EOpDiv: + writeTriplet(visit, "(", " / ", ")"); + break; + case EOpIMod: + writeTriplet(visit, "(", " % ", ")"); + break; + case EOpBitShiftLeft: + writeTriplet(visit, "(", " << ", ")"); + break; + case EOpBitShiftRight: + writeTriplet(visit, "(", " >> ", ")"); + break; + case EOpBitwiseAnd: + writeTriplet(visit, "(", " & ", ")"); + break; + case EOpBitwiseXor: + writeTriplet(visit, "(", " ^ ", ")"); + break; + case EOpBitwiseOr: + writeTriplet(visit, "(", " | ", ")"); + break; - case EOpEqual: - writeTriplet(visit, "(", " == ", ")"); - break; - case EOpNotEqual: - writeTriplet(visit, "(", " != ", ")"); - break; - case EOpLessThan: - writeTriplet(visit, "(", " < ", ")"); - break; - case EOpGreaterThan: - writeTriplet(visit, "(", " > ", ")"); - break; - case EOpLessThanEqual: - writeTriplet(visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqual: - writeTriplet(visit, "(", " >= ", ")"); - break; + case EOpEqual: + writeTriplet(visit, "(", " == ", ")"); + break; + case EOpNotEqual: + writeTriplet(visit, "(", " != ", ")"); + break; + case EOpLessThan: + writeTriplet(visit, "(", " < ", ")"); + break; + case EOpGreaterThan: + writeTriplet(visit, "(", " > ", ")"); + break; + case EOpLessThanEqual: + writeTriplet(visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqual: + writeTriplet(visit, "(", " >= ", ")"); + break; - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; - case EOpLogicalOr: - writeTriplet(visit, "(", " || ", ")"); - break; - case EOpLogicalXor: - writeTriplet(visit, "(", " ^^ ", ")"); - break; - case EOpLogicalAnd: - writeTriplet(visit, "(", " && ", ")"); - break; - default: - UNREACHABLE(); + case EOpLogicalOr: + writeTriplet(visit, "(", " || ", ")"); + break; + case EOpLogicalXor: + writeTriplet(visit, "(", " ^^ ", ")"); + break; + case EOpLogicalAnd: + writeTriplet(visit, "(", " && ", ")"); + break; + default: + UNREACHABLE(); } return visitChildren; @@ -800,40 +711,40 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) return true; } -bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node) +bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node) { TInfoSinkBase &out = objSink(); - // Notice two brackets at the beginning and end. The outer ones - // encapsulate the whole ternary expression. This preserves the - // order of precedence when ternary expressions are used in a - // compound expression, i.e., c = 2 * (a < b ? 1 : 2). - out << "(("; - node->getCondition()->traverse(this); - out << ") ? ("; - node->getTrueExpression()->traverse(this); - out << ") : ("; - node->getFalseExpression()->traverse(this); - out << "))"; - return false; -} -bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = objSink(); - - out << "if ("; - node->getCondition()->traverse(this); - out << ")\n"; + if (node->usesTernaryOperator()) + { + // Notice two brackets at the beginning and end. The outer ones + // encapsulate the whole ternary expression. This preserves the + // order of precedence when ternary expressions are used in a + // compound expression, i.e., c = 2 * (a < b ? 1 : 2). + out << "(("; + node->getCondition()->traverse(this); + out << ") ? ("; + node->getTrueBlock()->traverse(this); + out << ") : ("; + node->getFalseBlock()->traverse(this); + out << "))"; + } + else + { + out << "if ("; + node->getCondition()->traverse(this); + out << ")\n"; - incrementDepth(node); - visitCodeBlock(node->getTrueBlock()); + incrementDepth(node); + visitCodeBlock(node->getTrueBlock()); - if (node->getFalseBlock()) - { - out << "else\n"; - visitCodeBlock(node->getFalseBlock()); + if (node->getFalseBlock()) + { + out << "else\n"; + visitCodeBlock(node->getFalseBlock()); + } + decrementDepth(); } - decrementDepth(); return false; } @@ -867,65 +778,6 @@ bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) } } -bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = objSink(); - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "{\n"; - } - - incrementDepth(node); - for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); - iter != node->getSequence()->end(); ++iter) - { - TIntermNode *curNode = *iter; - ASSERT(curNode != nullptr); - curNode->traverse(this); - - if (isSingleStatement(curNode)) - out << ";\n"; - } - decrementDepth(); - - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "}\n"; - } - return false; -} - -bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TInfoSinkBase &out = objSink(); - - ASSERT(visit == PreVisit); - { - const TType &type = node->getType(); - writeVariableType(type); - if (type.isArray()) - out << arrayBrackets(type); - } - - out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - - incrementDepth(node); - - // Traverse function parameters. - TIntermAggregate *params = node->getFunctionParameters()->getAsAggregate(); - ASSERT(params->getOp() == EOpParameters); - params->traverse(this); - - // Traverse function body. - visitCodeBlock(node->getBody()); - decrementDepth(); - - // Fully processed; no need to visit children. - return false; -} - bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; @@ -933,6 +785,33 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction()); switch (node->getOp()) { + case EOpSequence: + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "{\n"; + } + + incrementDepth(node); + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *curNode = *iter; + ASSERT(curNode != NULL); + curNode->traverse(this); + + if (isSingleStatement(curNode)) + out << ";\n"; + } + decrementDepth(); + + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "}\n"; + } + visitChildren = false; + break; case EOpPrototype: // Function declaration. ASSERT(visit == PreVisit); @@ -943,7 +822,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) out << arrayBrackets(type); } - out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); + out << " " << hashFunctionNameIfNeeded(node->getNameObj()); out << "("; writeFunctionParameters(*(node->getSequence())); @@ -951,10 +830,46 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) visitChildren = false; break; + case EOpFunction: { + // Function definition. + ASSERT(visit == PreVisit); + { + const TType &type = node->getType(); + writeVariableType(type); + if (type.isArray()) + out << arrayBrackets(type); + } + + out << " " << hashFunctionNameIfNeeded(node->getNameObj()); + + incrementDepth(node); + // Function definition node contains one or two children nodes + // representing function parameters and function body. The latter + // is not present in case of empty function bodies. + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence::const_iterator seqIter = sequence.begin(); + + // Traverse function parameters. + TIntermAggregate *params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + params->traverse(this); + + // Traverse function body. + TIntermAggregate *body = ++seqIter != sequence.end() ? + (*seqIter)->getAsAggregate() : NULL; + visitCodeBlock(body); + decrementDepth(); + + // Fully processed; no need to visit children. + visitChildren = false; + break; + } case EOpFunctionCall: // Function call. if (visit == PreVisit) - out << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "("; + out << hashFunctionNameIfNeeded(node->getNameObj()) << "("; else if (visit == InVisit) out << ", "; else @@ -968,6 +883,27 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) out << ")"; visitChildren = false; break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + const TIntermTyped *variable = sequence.front()->getAsTyped(); + writeLayoutQualifier(variable->getType()); + writeVariableType(variable->getType()); + out << " "; + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + out << ", "; + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; case EOpInvariantDeclaration: // Invariant declaration. ASSERT(visit == PreVisit); @@ -976,7 +912,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ASSERT(sequence && sequence->size() == 1); const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); ASSERT(symbol); - out << "invariant " << hashVariableName(symbol->getName()); + out << "invariant " << hashVariableName(symbol->getSymbol()); } visitChildren = false; break; @@ -1031,6 +967,9 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorNotEqual: writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); break; + case EOpComma: + writeTriplet(visit, "(", ", ", ")"); + break; case EOpMod: writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); @@ -1090,32 +1029,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) return visitChildren; } -bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TInfoSinkBase &out = objSink(); - - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence &sequence = *(node->getSequence()); - const TIntermTyped *variable = sequence.front()->getAsTyped(); - writeLayoutQualifier(variable->getType()); - writeVariableType(variable->getType()); - out << " "; - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - out << ", "; - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - return true; -} - bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) { TInfoSinkBase &out = objSink(); @@ -1149,10 +1062,11 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) else { // Need to put a one-iteration loop here to handle break. - TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence(); + TIntermSequence *declSeq = + node->getInit()->getAsAggregate()->getSequence(); TIntermSymbol *indexSymbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - TString name = hashVariableName(indexSymbol->getName()); + TString name = hashVariableName(indexSymbol->getSymbol()); out << "for (int " << name << " = 0; " << name << " < 1; " << "++" << name << ")\n"; @@ -1220,7 +1134,7 @@ bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) return true; } -void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) +void TOutputGLSLBase::visitCodeBlock(TIntermNode *node) { TInfoSinkBase &out = objSink(); if (node != NULL) @@ -1240,43 +1154,27 @@ void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) TString TOutputGLSLBase::getTypeName(const TType &type) { if (type.getBasicType() == EbtStruct) - return hashName(TName(type.getStruct()->name())); + return hashName(type.getStruct()->name()); else return type.getBuiltInTypeNameString(); } -TString TOutputGLSLBase::hashName(const TName &name) +TString TOutputGLSLBase::hashName(const TString &name) { - if (name.getString().empty()) - { - ASSERT(!name.isInternal()); - return name.getString(); - } - if (name.isInternal()) - { - // TODO(oetuaho): Would be nicer to prefix non-internal names with "_" instead, like is - // done in the HLSL output, but that requires fairly complex changes elsewhere in the code - // as well. - // We need to use a prefix that is reserved in WebGL in order to guarantee that the internal - // names don't conflict with user-defined names from WebGL. - return "webgl_angle_" + name.getString(); - } - if (mHashFunction == nullptr) - { - return name.getString(); - } - NameMap::const_iterator it = mNameMap.find(name.getString().c_str()); + if (mHashFunction == NULL || name.empty()) + return name; + NameMap::const_iterator it = mNameMap.find(name.c_str()); if (it != mNameMap.end()) return it->second.c_str(); - TString hashedName = TIntermTraverser::hash(name.getString(), mHashFunction); - mNameMap[name.getString().c_str()] = hashedName.c_str(); + TString hashedName = TIntermTraverser::hash(name, mHashFunction); + mNameMap[name.c_str()] = hashedName.c_str(); return hashedName; } -TString TOutputGLSLBase::hashVariableName(const TName &name) +TString TOutputGLSLBase::hashVariableName(const TString &name) { - if (mSymbolTable.findBuiltIn(name.getString(), mShaderVersion) != NULL) - return name.getString(); + if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL) + return name; return hashName(name); } @@ -1287,16 +1185,9 @@ TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName) if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main") return translateTextureFunction(name); if (mangledName.isInternal()) - { - // Internal function names are outputted as-is - they may refer to functions manually added - // to the output shader source that are not included in the AST at all. return name; - } else - { - TName nameObj(name); - return hashName(nameObj); - } + return hashName(name); } bool TOutputGLSLBase::structDeclared(const TStructure *structure) const @@ -1314,14 +1205,14 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure) { TInfoSinkBase &out = objSink(); - out << "struct " << hashName(TName(structure->name())) << "{\n"; + out << "struct " << hashName(structure->name()) << "{\n"; const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) { const TField *field = fields[i]; if (writeVariablePrecision(field->type()->getPrecision())) out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); + out << getTypeName(*field->type()) << " " << hashName(field->name()); if (field->type()->isArray()) out << arrayBrackets(*field->type()); out << ";\n"; @@ -1382,19 +1273,17 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc { TInfoSinkBase &out = objSink(); - out << hashName(TName(interfaceBlock->name())) << "{\n"; + out << hashName(interfaceBlock->name()) << "{\n"; const TFieldList &fields = interfaceBlock->fields(); for (size_t i = 0; i < fields.size(); ++i) { const TField *field = fields[i]; if (writeVariablePrecision(field->type()->getPrecision())) out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); + out << getTypeName(*field->type()) << " " << hashName(field->name()); if (field->type()->isArray()) out << arrayBrackets(*field->type()); out << ";\n"; } out << "}"; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/OutputGLSLBase.h b/gfx/angle/src/compiler/translator/OutputGLSLBase.h index ede4c4925..29b710487 100755 --- a/gfx/angle/src/compiler/translator/OutputGLSLBase.h +++ b/gfx/angle/src/compiler/translator/OutputGLSLBase.h @@ -13,9 +13,6 @@ #include "compiler/translator/LoopInfo.h" #include "compiler/translator/ParseContext.h" -namespace sh -{ - class TOutputGLSLBase : public TIntermTraverser { public: @@ -23,11 +20,9 @@ class TOutputGLSLBase : public TIntermTraverser ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap &nameMap, - TSymbolTable &symbolTable, - sh::GLenum shaderType, + TSymbolTable& symbolTable, int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions); + ShShaderOutput output); ShShaderOutput getShaderOutput() const { @@ -38,7 +33,6 @@ class TOutputGLSLBase : public TIntermTraverser TInfoSinkBase &objSink() { return mObjSink; } void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); void writeLayoutQualifier(const TType &type); - void writeInvariantQualifier(const TType &type); void writeVariableType(const TType &type); virtual bool writeVariablePrecision(TPrecision precision) = 0; void writeFunctionParameters(const TIntermSequence &args); @@ -48,27 +42,22 @@ class TOutputGLSLBase : public TIntermTraverser void visitSymbol(TIntermSymbol *node) override; void visitConstantUnion(TIntermConstantUnion *node) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitUnary(Visit visit, TIntermUnary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; bool visitSwitch(Visit visit, TIntermSwitch *node) override; bool visitCase(Visit visit, TIntermCase *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; bool visitLoop(Visit visit, TIntermLoop *node) override; bool visitBranch(Visit visit, TIntermBranch *node) override; - void visitCodeBlock(TIntermBlock *node); + void visitCodeBlock(TIntermNode *node); // Return the original name if hash function pointer is NULL; // otherwise return the hashed name. - TString hashName(const TName &name); + TString hashName(const TString &name); // Same as hashName(), but without hashing built-in variables. - TString hashVariableName(const TName &name); + TString hashVariableName(const TString &name); // Same as hashName(), but without hashing built-in functions and with unmangling. TString hashFunctionNameIfNeeded(const TName &mangledName); // Used to translate function names for differences between ESSL and GLSL @@ -83,8 +72,6 @@ class TOutputGLSLBase : public TIntermTraverser void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction); - const char *mapQualifierToString(TQualifier qialifier); - TInfoSinkBase &mObjSink; bool mDeclaringVariables; @@ -103,15 +90,9 @@ class TOutputGLSLBase : public TIntermTraverser TSymbolTable &mSymbolTable; - sh::GLenum mShaderType; - const int mShaderVersion; ShShaderOutput mOutput; - - ShCompileOptions mCompileOptions; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ diff --git a/gfx/angle/src/compiler/translator/OutputHLSL.cpp b/gfx/angle/src/compiler/translator/OutputHLSL.cpp index 5ef2e89f9..639178281 100755 --- a/gfx/angle/src/compiler/translator/OutputHLSL.cpp +++ b/gfx/angle/src/compiler/translator/OutputHLSL.cpp @@ -28,11 +28,13 @@ #include "compiler/translator/blocklayout.h" #include "compiler/translator/util.h" -namespace sh +namespace { -namespace +bool IsSequence(TIntermNode *node) { + return node->getAsAggregate() != nullptr && node->getAsAggregate()->getOp() == EOpSequence; +} void WriteSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion) { @@ -75,14 +77,14 @@ const TConstantUnion *WriteConstantUnionArray(TInfoSinkBase &out, } // namespace -OutputHLSL::OutputHLSL(sh::GLenum shaderType, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - const char *sourcePath, - ShShaderOutput outputType, - int numRenderTargets, - const std::vector<Uniform> &uniforms, - ShCompileOptions compileOptions) +namespace sh +{ + +OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, ShShaderOutput outputType, + int numRenderTargets, const std::vector<Uniform> &uniforms, + int compileOptions) : TIntermTraverser(true, true, true), mShaderType(shaderType), mShaderVersion(shaderVersion), @@ -156,17 +158,12 @@ void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) BuiltInFunctionEmulator builtInFunctionEmulator; InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator); - if ((mCompileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) != 0) - { - InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(&builtInFunctionEmulator, - mShaderVersion); - } - builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot); // Now that we are done changing the AST, do the analyses need for HLSL generation CallDAG::InitResult success = mCallDag.init(treeRoot, &objSink); ASSERT(success == CallDAG::INITDAG_SUCCESS); + UNUSED_ASSERTION_VARIABLE(success); mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag); // Output the body and footer first to determine what has to go in the header @@ -842,17 +839,6 @@ bool OutputHLSL::ancestorEvaluatesToSamplerInStruct(Visit visit) return false; } -bool OutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = getInfoSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase &out = getInfoSink(); @@ -866,139 +852,133 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) switch (node->getOp()) { - case EOpComma: - outputTriplet(out, visit, "(", ", ", ")"); - break; - case EOpAssign: - if (node->getLeft()->isArray()) - { - TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); - if (rightAgg != nullptr && rightAgg->isConstructor()) - { - const TString &functionName = addArrayConstructIntoFunction(node->getType()); - out << functionName << "("; - node->getLeft()->traverse(this); - TIntermSequence *seq = rightAgg->getSequence(); - for (auto &arrayElement : *seq) - { - out << ", "; - arrayElement->traverse(this); - } - out << ")"; - return false; - } - // ArrayReturnValueToOutParameter should have eliminated expressions where a - // function call is assigned. - ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpFunctionCall); - - const TString &functionName = addArrayAssignmentFunction(node->getType()); - outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); - } - else + case EOpAssign: + if (node->getLeft()->isArray()) + { + TIntermAggregate *rightAgg = node->getRight()->getAsAggregate(); + if (rightAgg != nullptr && rightAgg->isConstructor()) { - outputTriplet(out, visit, "(", " = ", ")"); - } - break; - case EOpInitialize: - if (visit == PreVisit) - { - TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); - ASSERT(symbolNode); - TIntermTyped *expression = node->getRight(); - - // Global initializers must be constant at this point. - ASSERT(symbolNode->getQualifier() != EvqGlobal || - canWriteAsHLSLLiteral(expression)); - - // GLSL allows to write things like "float x = x;" where a new variable x is defined - // and the value of an existing variable x is assigned. HLSL uses C semantics (the - // new variable is created before the assignment is evaluated), so we need to - // convert - // this to "float t = x, x = t;". - if (writeSameSymbolInitializer(out, symbolNode, expression)) - { - // Skip initializing the rest of the expression - return false; - } - else if (writeConstantInitialization(out, symbolNode, expression)) + const TString &functionName = addArrayConstructIntoFunction(node->getType()); + out << functionName << "("; + node->getLeft()->traverse(this); + TIntermSequence *seq = rightAgg->getSequence(); + for (auto &arrayElement : *seq) { - return false; + out << ", "; + arrayElement->traverse(this); } + out << ")"; + return false; } - else if (visit == InVisit) - { - out << " = "; - } - break; - case EOpAddAssign: - outputTriplet(out, visit, "(", " += ", ")"); - break; - case EOpSubAssign: - outputTriplet(out, visit, "(", " -= ", ")"); - break; - case EOpMulAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpVectorTimesScalarAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpMatrixTimesScalarAssign: - outputTriplet(out, visit, "(", " *= ", ")"); - break; - case EOpVectorTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) - { - out << " = mul("; - node->getLeft()->traverse(this); - out << ", transpose("; - } - else - { - out << ")))"; - } - break; - case EOpMatrixTimesMatrixAssign: - if (visit == PreVisit) - { - out << "("; - } - else if (visit == InVisit) + // ArrayReturnValueToOutParameter should have eliminated expressions where a function call is assigned. + ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpFunctionCall); + + const TString &functionName = addArrayAssignmentFunction(node->getType()); + outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")"); + } + else + { + outputTriplet(out, visit, "(", " = ", ")"); + } + break; + case EOpInitialize: + if (visit == PreVisit) + { + TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); + ASSERT(symbolNode); + TIntermTyped *expression = node->getRight(); + + // Global initializers must be constant at this point. + ASSERT(symbolNode->getQualifier() != EvqGlobal || canWriteAsHLSLLiteral(expression)); + + // GLSL allows to write things like "float x = x;" where a new variable x is defined + // and the value of an existing variable x is assigned. HLSL uses C semantics (the + // new variable is created before the assignment is evaluated), so we need to convert + // this to "float t = x, x = t;". + if (writeSameSymbolInitializer(out, symbolNode, expression)) { - out << " = transpose(mul(transpose("; - node->getLeft()->traverse(this); - out << "), transpose("; + // Skip initializing the rest of the expression + return false; } - else + else if (writeConstantInitialization(out, symbolNode, expression)) { - out << "))))"; + return false; } - break; - case EOpDivAssign: - outputTriplet(out, visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - outputTriplet(out, visit, "(", " %= ", ")"); - break; - case EOpBitShiftLeftAssign: - outputTriplet(out, visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - outputTriplet(out, visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - outputTriplet(out, visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - outputTriplet(out, visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - outputTriplet(out, visit, "(", " |= ", ")"); - break; - case EOpIndexDirect: + } + else if (visit == InVisit) + { + out << " = "; + } + break; + case EOpAddAssign: + outputTriplet(out, visit, "(", " += ", ")"); + break; + case EOpSubAssign: + outputTriplet(out, visit, "(", " -= ", ")"); + break; + case EOpMulAssign: + outputTriplet(out, visit, "(", " *= ", ")"); + break; + case EOpVectorTimesScalarAssign: + outputTriplet(out, visit, "(", " *= ", ")"); + break; + case EOpMatrixTimesScalarAssign: + outputTriplet(out, visit, "(", " *= ", ")"); + break; + case EOpVectorTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = mul("; + node->getLeft()->traverse(this); + out << ", transpose("; + } + else + { + out << ")))"; + } + break; + case EOpMatrixTimesMatrixAssign: + if (visit == PreVisit) + { + out << "("; + } + else if (visit == InVisit) + { + out << " = transpose(mul(transpose("; + node->getLeft()->traverse(this); + out << "), transpose("; + } + else + { + out << "))))"; + } + break; + case EOpDivAssign: + outputTriplet(out, visit, "(", " /= ", ")"); + break; + case EOpIModAssign: + outputTriplet(out, visit, "(", " %= ", ")"); + break; + case EOpBitShiftLeftAssign: + outputTriplet(out, visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + outputTriplet(out, visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + outputTriplet(out, visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + outputTriplet(out, visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + outputTriplet(out, visit, "(", " |= ", ")"); + break; + case EOpIndexDirect: { const TType& leftType = node->getLeft()->getType(); if (leftType.isInterfaceBlock()) @@ -1077,6 +1057,42 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) return false; } break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + + TIntermAggregate *swizzle = node->getRight()->getAsAggregate(); + + if (swizzle) + { + TIntermSequence *sequence = swizzle->getSequence(); + + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) + { + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + + if (element) + { + int i = element->getIConst(0); + + switch (i) + { + case 0: out << "x"; break; + case 1: out << "y"; break; + case 2: out << "z"; break; + case 3: out << "w"; break; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + } + else UNREACHABLE(); + + return false; // Fully processed + } + break; case EOpAdd: outputTriplet(out, visit, "(", " + ", ")"); break; @@ -1280,12 +1296,9 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) outputTriplet(out, visit, "frac(", "", ")"); break; case EOpIsNan: - if (node->getUseEmulatedFunction()) - writeEmulatedFunctionTriplet(out, visit, "isnan("); - else - outputTriplet(out, visit, "isnan(", "", ")"); - mRequiresIEEEStrictCompiling = true; - break; + outputTriplet(out, visit, "isnan(", "", ")"); + mRequiresIEEEStrictCompiling = true; + break; case EOpIsInf: outputTriplet(out, visit, "isinf(", "", ")"); break; @@ -1418,232 +1431,236 @@ TString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node) } } -bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = getInfoSink(); - - if (mInsideFunction) - { - outputLineDirective(out, node->getLine().first_line); - out << "{\n"; - } - - for (TIntermSequence::iterator sit = node->getSequence()->begin(); - sit != node->getSequence()->end(); sit++) - { - outputLineDirective(out, (*sit)->getLine().first_line); - - (*sit)->traverse(this); - - // Don't output ; after case labels, they're terminated by : - // This is needed especially since outputting a ; after a case statement would turn empty - // case statements into non-empty case statements, disallowing fall-through from them. - // Also no need to output ; after if statements or sequences. This is done just for - // code clarity. - if ((*sit)->getAsCaseNode() == nullptr && (*sit)->getAsIfElseNode() == nullptr && - (*sit)->getAsBlock() == nullptr) - out << ";\n"; - } - - if (mInsideFunction) - { - outputLineDirective(out, node->getLine().last_line); - out << "}\n"; - } - - return false; -} - -bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { TInfoSinkBase &out = getInfoSink(); - ASSERT(mCurrentFunctionMetadata == nullptr); - - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - ASSERT(index != CallDAG::InvalidIndex); - mCurrentFunctionMetadata = &mASTMetadataList[index]; - - out << TypeString(node->getType()) << " "; - - TIntermSequence *parameters = node->getFunctionParameters()->getSequence(); - - if (node->getFunctionSymbolInfo()->isMain()) - { - out << "gl_main("; - } - else - { - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) - << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "("); - } - - for (unsigned int i = 0; i < parameters->size(); i++) + switch (node->getOp()) { - TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode(); - - if (symbol) + case EOpSequence: { - ensureStructDefined(symbol->getType()); - - out << argumentString(symbol); - - if (i < parameters->size() - 1) + if (mInsideFunction) { - out << ", "; + outputLineDirective(out, node->getLine().first_line); + out << "{\n"; } - } - else - UNREACHABLE(); - } - - out << ")\n"; - - mInsideFunction = true; - // The function body node will output braces. - node->getBody()->traverse(this); - mInsideFunction = false; - - mCurrentFunctionMetadata = nullptr; - - bool needsLod0 = mASTMetadataList[index].mNeedsLod0; - if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) - { - ASSERT(!node->getFunctionSymbolInfo()->isMain()); - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } - return false; -} + for (TIntermSequence::iterator sit = node->getSequence()->begin(); sit != node->getSequence()->end(); sit++) + { + outputLineDirective(out, (*sit)->getLine().first_line); + + (*sit)->traverse(this); + + // Don't output ; after case labels, they're terminated by : + // This is needed especially since outputting a ; after a case statement would turn empty + // case statements into non-empty case statements, disallowing fall-through from them. + // Also no need to output ; after selection (if) statements or sequences. This is done just + // for code clarity. + TIntermSelection *asSelection = (*sit)->getAsSelectionNode(); + ASSERT(asSelection == nullptr || !asSelection->usesTernaryOperator()); + if ((*sit)->getAsCaseNode() == nullptr && asSelection == nullptr && !IsSequence(*sit)) + out << ";\n"; + } -bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TInfoSinkBase &out = getInfoSink(); - if (visit == PreVisit) - { - TIntermSequence *sequence = node->getSequence(); - TIntermTyped *variable = (*sequence)[0]->getAsTyped(); - ASSERT(sequence->size() == 1); + if (mInsideFunction) + { + outputLineDirective(out, node->getLine().last_line); + out << "}\n"; + } - if (variable && - (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal || - variable->getQualifier() == EvqConst)) + return false; + } + case EOpDeclaration: + if (visit == PreVisit) { - ensureStructDefined(variable->getType()); + TIntermSequence *sequence = node->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); + ASSERT(sequence->size() == 1); - if (!variable->getAsSymbolNode() || - variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration + if (variable && + (variable->getQualifier() == EvqTemporary || + variable->getQualifier() == EvqGlobal || variable->getQualifier() == EvqConst)) { - if (!mInsideFunction) + ensureStructDefined(variable->getType()); + + if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration { - out << "static "; - } + if (!mInsideFunction) + { + out << "static "; + } - out << TypeString(variable->getType()) + " "; + out << TypeString(variable->getType()) + " "; - TIntermSymbol *symbol = variable->getAsSymbolNode(); + TIntermSymbol *symbol = variable->getAsSymbolNode(); - if (symbol) - { - symbol->traverse(this); - out << ArrayString(symbol->getType()); - out << " = " + initializer(symbol->getType()); + if (symbol) + { + symbol->traverse(this); + out << ArrayString(symbol->getType()); + out << " = " + initializer(symbol->getType()); + } + else + { + variable->traverse(this); + } } - else + else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration { - variable->traverse(this); + // Already added to constructor map } + else UNREACHABLE(); } - else if (variable->getAsSymbolNode() && - variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration + else if (variable && IsVaryingOut(variable->getQualifier())) { - // Already added to constructor map + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) + { + TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + + if (symbol) + { + // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking + mReferencedVaryings[symbol->getSymbol()] = symbol; + } + else + { + (*sit)->traverse(this); + } + } } - else - UNREACHABLE(); + + return false; } - else if (variable && IsVaryingOut(variable->getQualifier())) + else if (visit == InVisit) + { + out << ", "; + } + break; + case EOpInvariantDeclaration: + // Do not do any translation + return false; + case EOpPrototype: + if (visit == PreVisit) { - for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) + size_t index = mCallDag.findIndex(node); + // Skip the prototype if it is not implemented (and thus not used) + if (index == CallDAG::InvalidIndex) { - TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + return false; + } + + TIntermSequence *arguments = node->getSequence(); + + TString name = DecorateFunctionIfNeeded(node->getNameObj()); + out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments) + << (mOutputLod0Function ? "Lod0(" : "("); + + for (unsigned int i = 0; i < arguments->size(); i++) + { + TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); if (symbol) { - // Vertex (output) varyings which are declared but not written to should - // still be declared to allow successful linking - mReferencedVaryings[symbol->getSymbol()] = symbol; - } - else - { - (*sit)->traverse(this); + out << argumentString(symbol); + + if (i < arguments->size() - 1) + { + out << ", "; + } } + else UNREACHABLE(); } - } - } - return false; -} -bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) -{ - TInfoSinkBase &out = getInfoSink(); + out << ");\n"; - switch (node->getOp()) - { - case EOpInvariantDeclaration: - // Do not do any translation - return false; - case EOpPrototype: - if (visit == PreVisit) + // Also prototype the Lod0 variant if needed + bool needsLod0 = mASTMetadataList[index].mNeedsLod0; + if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) { - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); - // Skip the prototype if it is not implemented (and thus not used) - if (index == CallDAG::InvalidIndex) - { - return false; - } + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; + } + + return false; + } + break; + case EOpComma: + outputTriplet(out, visit, "(", ", ", ")"); + break; + case EOpFunction: + { + ASSERT(mCurrentFunctionMetadata == nullptr); + TString name = TFunction::unmangleName(node->getNameObj().getString()); + + size_t index = mCallDag.findIndex(node); + ASSERT(index != CallDAG::InvalidIndex); + mCurrentFunctionMetadata = &mASTMetadataList[index]; - TIntermSequence *arguments = node->getSequence(); + out << TypeString(node->getType()) << " "; - TString name = - DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - out << TypeString(node->getType()) << " " << name + TIntermSequence *sequence = node->getSequence(); + TIntermSequence *arguments = (*sequence)[0]->getAsAggregate()->getSequence(); + + if (name == "main") + { + out << "gl_main("; + } + else + { + out << DecorateFunctionIfNeeded(node->getNameObj()) << DisambiguateFunctionName(arguments) << (mOutputLod0Function ? "Lod0(" : "("); + } - for (unsigned int i = 0; i < arguments->size(); i++) + for (unsigned int i = 0; i < arguments->size(); i++) + { + TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); + + if (symbol) { - TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); + ensureStructDefined(symbol->getType()); - if (symbol) - { - out << argumentString(symbol); + out << argumentString(symbol); - if (i < arguments->size() - 1) - { - out << ", "; - } + if (i < arguments->size() - 1) + { + out << ", "; } - else - UNREACHABLE(); } + else UNREACHABLE(); + } - out << ");\n"; + out << ")\n"; - // Also prototype the Lod0 variant if needed - bool needsLod0 = mASTMetadataList[index].mNeedsLod0; - if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) - { - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; - } + if (sequence->size() > 1) + { + mInsideFunction = true; + TIntermNode *body = (*sequence)[1]; + // The function body node will output braces. + ASSERT(IsSequence(body)); + body->traverse(this); + mInsideFunction = false; + } + else + { + out << "{}\n"; + } - return false; + mCurrentFunctionMetadata = nullptr; + + bool needsLod0 = mASTMetadataList[index].mNeedsLod0; + if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER) + { + ASSERT(name != "main"); + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; } - break; - case EOpFunctionCall: + + return false; + } + break; + case EOpFunctionCall: { TIntermSequence *arguments = node->getSequence(); @@ -1654,23 +1671,23 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { UNIMPLEMENTED(); } - size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo()); + size_t index = mCallDag.findIndex(node); ASSERT(index != CallDAG::InvalidIndex); lod0 &= mASTMetadataList[index].mNeedsLod0; - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); + out << DecorateFunctionIfNeeded(node->getNameObj()); out << DisambiguateFunctionName(node->getSequence()); out << (lod0 ? "Lod0(" : "("); } - else if (node->getFunctionSymbolInfo()->getNameObj().isInternal()) + else if (node->getNameObj().isInternal()) { // This path is used for internal functions that don't have their definitions in the // AST, such as precision emulation functions. - out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "("; + out << DecorateFunctionIfNeeded(node->getNameObj()) << "("; } else { - TString name = TFunction::unmangleName(node->getFunctionSymbolInfo()->getName()); + TString name = TFunction::unmangleName(node->getNameObj().getString()); TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); int coords = (*arguments)[1]->getAsTyped()->getNominalSize(); TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction( @@ -1724,6 +1741,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) return false; } + break; case EOpParameters: outputTriplet(out, visit, "(", ", ", ")\n{\n"); break; @@ -1802,7 +1820,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpConstructMat4: outputConstructor(out, visit, node->getType(), "mat4", node->getSequence()); break; - case EOpConstructStruct: + case EOpConstructStruct: { if (node->getType().isArray()) { @@ -1831,31 +1849,31 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorNotEqual: outputTriplet(out, visit, "(", " != ", ")"); break; - case EOpMod: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, "mod("); - break; - case EOpModf: - outputTriplet(out, visit, "modf(", ", ", ")"); - break; - case EOpPow: - outputTriplet(out, visit, "pow(", ", ", ")"); - break; - case EOpAtan: - ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, "atan("); - break; - case EOpMin: - outputTriplet(out, visit, "min(", ", ", ")"); - break; - case EOpMax: - outputTriplet(out, visit, "max(", ", ", ")"); - break; - case EOpClamp: - outputTriplet(out, visit, "clamp(", ", ", ")"); - break; - case EOpMix: + case EOpMod: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, "mod("); + break; + case EOpModf: + outputTriplet(out, visit, "modf(", ", ", ")"); + break; + case EOpPow: + outputTriplet(out, visit, "pow(", ", ", ")"); + break; + case EOpAtan: + ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, "atan("); + break; + case EOpMin: + outputTriplet(out, visit, "min(", ", ", ")"); + break; + case EOpMax: + outputTriplet(out, visit, "max(", ", ", ")"); + break; + case EOpClamp: + outputTriplet(out, visit, "clamp(", ", ", ")"); + break; + case EOpMix: { TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped(); if (lastParamNode->getType().getBasicType() == EbtBool) @@ -1869,8 +1887,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { outputTriplet(out, visit, "lerp(", ", ", ")"); } - break; } + break; case EOpStep: outputTriplet(out, visit, "step(", ", ", ")"); break; @@ -1886,31 +1904,30 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpCross: outputTriplet(out, visit, "cross(", ", ", ")"); break; - case EOpFaceForward: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, "faceforward("); - break; - case EOpReflect: - outputTriplet(out, visit, "reflect(", ", ", ")"); - break; - case EOpRefract: - outputTriplet(out, visit, "refract(", ", ", ")"); - break; - case EOpOuterProduct: - ASSERT(node->getUseEmulatedFunction()); - writeEmulatedFunctionTriplet(out, visit, "outerProduct("); - break; - case EOpMul: - outputTriplet(out, visit, "(", " * ", ")"); - break; - default: - UNREACHABLE(); + case EOpFaceForward: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, "faceforward("); + break; + case EOpReflect: + outputTriplet(out, visit, "reflect(", ", ", ")"); + break; + case EOpRefract: + outputTriplet(out, visit, "refract(", ", ", ")"); + break; + case EOpOuterProduct: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(out, visit, "outerProduct("); + break; + case EOpMul: + outputTriplet(out, visit, "(", " * ", ")"); + break; + default: UNREACHABLE(); } return true; } -void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) +void OutputHLSL::writeSelection(TInfoSinkBase &out, TIntermSelection *node) { out << "if ("; @@ -1925,6 +1942,8 @@ void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) if (node->getTrueBlock()) { // The trueBlock child node will output braces. + ASSERT(IsSequence(node->getTrueBlock())); + node->getTrueBlock()->traverse(this); // Detect true discard @@ -1945,7 +1964,9 @@ void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) outputLineDirective(out, node->getFalseBlock()->getLine().first_line); - // The falseBlock child node will output braces. + // Either this is "else if" or the falseBlock child node will output braces. + ASSERT(IsSequence(node->getFalseBlock()) || node->getFalseBlock()->getAsSelectionNode() != nullptr); + node->getFalseBlock()->traverse(this); outputLineDirective(out, node->getFalseBlock()->getLine().first_line); @@ -1961,18 +1982,11 @@ void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node) } } -bool OutputHLSL::visitTernary(Visit, TIntermTernary *) -{ - // Ternary ops should have been already converted to something else in the AST. HLSL ternary - // operator doesn't short-circuit, so it's not the same as the GLSL ternary operator. - UNREACHABLE(); - return false; -} - -bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node) +bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { TInfoSinkBase &out = getInfoSink(); + ASSERT(!node->usesTernaryOperator()); ASSERT(mInsideFunction); // D3D errors when there is a gradient operation in a loop in an unflattened if. @@ -1981,7 +1995,7 @@ bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node) out << "FLATTEN "; } - writeIfElse(out, node); + writeSelection(out, node); return false; } @@ -2085,6 +2099,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) if (node->getBody()) { // The loop body node will output braces. + ASSERT(IsSequence(node->getBody())); node->getBody()->traverse(this); } else @@ -2172,6 +2187,39 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) return true; } +bool OutputHLSL::isSingleStatement(TIntermNode *node) +{ + TIntermAggregate *aggregate = node->getAsAggregate(); + + if (aggregate) + { + if (aggregate->getOp() == EOpSequence) + { + return false; + } + else if (aggregate->getOp() == EOpDeclaration) + { + // Declaring multiple comma-separated variables must be considered multiple statements + // because each individual declaration has side effects which are visible in the next. + return false; + } + else + { + for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++) + { + if (!isSingleStatement(*sit)) + { + return false; + } + } + + return true; + } + } + + return true; +} + // Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them // (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254). bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) @@ -2189,7 +2237,7 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) // Parse index name and intial value if (node->getInit()) { - TIntermDeclaration *init = node->getInit()->getAsDeclarationNode(); + TIntermAggregate *init = node->getInit()->getAsAggregate(); if (init) { @@ -2854,4 +2902,6 @@ void OutputHLSL::ensureStructDefined(const TType &type) } } -} // namespace sh + + +} diff --git a/gfx/angle/src/compiler/translator/OutputHLSL.h b/gfx/angle/src/compiler/translator/OutputHLSL.h index 833f4736b..e5204e419 100755 --- a/gfx/angle/src/compiler/translator/OutputHLSL.h +++ b/gfx/angle/src/compiler/translator/OutputHLSL.h @@ -30,14 +30,11 @@ typedef std::map<TString, TIntermSymbol*> ReferencedSymbols; class OutputHLSL : public TIntermTraverser { public: - OutputHLSL(sh::GLenum shaderType, - int shaderVersion, - const TExtensionBehavior &extensionBehavior, - const char *sourcePath, - ShShaderOutput outputType, - int numRenderTargets, - const std::vector<Uniform> &uniforms, - ShCompileOptions compileOptions); + OutputHLSL(sh::GLenum shaderType, int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, ShShaderOutput outputType, + int numRenderTargets, const std::vector<Uniform> &uniforms, + int compileOptions); ~OutputHLSL(); @@ -59,20 +56,16 @@ class OutputHLSL : public TIntermTraverser void visitSymbol(TIntermSymbol*); void visitRaw(TIntermRaw*); void visitConstantUnion(TIntermConstantUnion*); - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; bool visitBinary(Visit visit, TIntermBinary*); bool visitUnary(Visit visit, TIntermUnary*); - bool visitTernary(Visit visit, TIntermTernary *); - bool visitIfElse(Visit visit, TIntermIfElse *); + bool visitSelection(Visit visit, TIntermSelection*); bool visitSwitch(Visit visit, TIntermSwitch *); bool visitCase(Visit visit, TIntermCase *); - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitBlock(Visit visit, TIntermBlock *node); - bool visitDeclaration(Visit visit, TIntermDeclaration *node); bool visitLoop(Visit visit, TIntermLoop*); bool visitBranch(Visit visit, TIntermBranch*); + bool isSingleStatement(TIntermNode *node); bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node); // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString. @@ -108,7 +101,7 @@ class OutputHLSL : public TIntermTraverser TIntermTyped *expression); void writeDeferredGlobalInitializers(TInfoSinkBase &out); - void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node); + void writeSelection(TInfoSinkBase &out, TIntermSelection *node); // Returns the function name TString addStructEqualityFunction(const TStructure &structure); @@ -124,7 +117,7 @@ class OutputHLSL : public TIntermTraverser const TExtensionBehavior &mExtensionBehavior; const char *mSourcePath; const ShShaderOutput mOutputType; - ShCompileOptions mCompileOptions; + int mCompileOptions; bool mInsideFunction; diff --git a/gfx/angle/src/compiler/translator/ParseContext.cpp b/gfx/angle/src/compiler/translator/ParseContext.cpp index 4ad597c4f..5e15eea24 100755 --- a/gfx/angle/src/compiler/translator/ParseContext.cpp +++ b/gfx/angle/src/compiler/translator/ParseContext.cpp @@ -16,102 +16,12 @@ #include "compiler/translator/ValidateGlobalInitializer.h" #include "compiler/translator/util.h" -namespace sh -{ - /////////////////////////////////////////////////////////////////////// // // Sub- vector and matrix fields // //////////////////////////////////////////////////////////////////////// -namespace -{ - -const int kWebGLMaxStructNesting = 4; - -bool ContainsSampler(const TType &type) -{ - if (IsSampler(type.getBasicType())) - return true; - - if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) - { - const TFieldList &fields = type.getStruct()->fields(); - for (unsigned int i = 0; i < fields.size(); ++i) - { - if (ContainsSampler(*fields[i]->type())) - return true; - } - } - - return false; -} - -bool ContainsImage(const TType &type) -{ - if (IsImage(type.getBasicType())) - return true; - - if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) - { - const TFieldList &fields = type.getStruct()->fields(); - for (unsigned int i = 0; i < fields.size(); ++i) - { - if (ContainsImage(*fields[i]->type())) - return true; - } - } - - return false; -} - -} // namespace - -TParseContext::TParseContext(TSymbolTable &symt, - TExtensionBehavior &ext, - sh::GLenum type, - ShShaderSpec spec, - ShCompileOptions options, - bool checksPrecErrors, - TInfoSink &is, - const ShBuiltInResources &resources) - : intermediate(), - symbolTable(symt), - mDeferredSingleDeclarationErrorCheck(false), - mShaderType(type), - mShaderSpec(spec), - mCompileOptions(options), - mShaderVersion(100), - mTreeRoot(nullptr), - mLoopNestingLevel(0), - mStructNestingLevel(0), - mSwitchNestingLevel(0), - mCurrentFunctionType(nullptr), - mFunctionReturnsValue(false), - mChecksPrecisionErrors(checksPrecErrors), - mFragmentPrecisionHighOnESSL1(false), - mDefaultMatrixPacking(EmpColumnMajor), - mDefaultBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), - mDiagnostics(is), - mDirectiveHandler(ext, - mDiagnostics, - mShaderVersion, - mShaderType, - resources.WEBGL_debug_shader_precision == 1), - mPreprocessor(&mDiagnostics, &mDirectiveHandler), - mScanner(nullptr), - mUsesFragData(false), - mUsesFragColor(false), - mUsesSecondaryOutputs(false), - mMinProgramTexelOffset(resources.MinProgramTexelOffset), - mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), - mComputeShaderLocalSizeDeclared(false), - mDeclaringFunction(false) -{ - mComputeShaderLocalSize.fill(-1); -} - // // Look at a '.' field selector string and change it into offsets // for a vector. @@ -303,12 +213,6 @@ void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, { if (!mChecksPrecisionErrors) return; - - if (precision != EbpUndefined && !SupportsPrecision(type)) - { - error(line, "illegal type for precision qualifier", getBasicString(type)); - } - if (precision == EbpUndefined) { switch (type) @@ -327,11 +231,6 @@ void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, error(line, "No precision specified (sampler)", ""); return; } - if (IsImage(type)) - { - error(line, "No precision specified (image)", ""); - return; - } } } } @@ -342,18 +241,6 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn { TIntermSymbol *symNode = node->getAsSymbolNode(); TIntermBinary *binaryNode = node->getAsBinaryNode(); - TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); - - if (swizzleNode) - { - bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand()); - if (ok && swizzleNode->hasDuplicateOffsets()) - { - error(line, " l-value of swizzle cannot have duplicate components", op); - return false; - } - return ok; - } if (binaryNode) { @@ -364,10 +251,34 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn case EOpIndexDirectStruct: case EOpIndexDirectInterfaceBlock: return checkCanBeLValue(line, op, binaryNode->getLeft()); + case EOpVectorSwizzle: + { + bool ok = checkCanBeLValue(line, op, binaryNode->getLeft()); + if (ok) + { + int offsetCount[4] = {0, 0, 0, 0}; + + TIntermAggregate *swizzleOffsets = binaryNode->getRight()->getAsAggregate(); + + for (const auto &offset : *swizzleOffsets->getSequence()) + { + int value = offset->getAsTyped()->getAsConstantUnion()->getIConst(0); + offsetCount[value]++; + if (offsetCount[value] > 1) + { + error(line, " l-value of swizzle cannot have duplicate components", op); + return false; + } + } + } + + return ok; + } default: break; } error(line, " l-value required", op); + return false; } @@ -441,10 +352,6 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn { message = "can't modify a sampler"; } - if (IsImage(node->getBasicType())) - { - message = "can't modify an image"; - } } if (message == 0 && binaryNode == 0 && symNode == 0) @@ -528,7 +435,7 @@ bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &id error(line, reservedErrMsg, "gl_"); return false; } - if (sh::IsWebGLBasedSpec(mShaderSpec)) + if (IsWebGLBasedSpec(mShaderSpec)) { if (identifier.compare(0, 6, "webgl_") == 0) { @@ -540,6 +447,11 @@ bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &id error(line, reservedErrMsg, "_webgl_"); return false; } + if (mShaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) + { + error(line, reservedErrMsg, "css_"); + return false; + } } if (identifier.find("__") != TString::npos) { @@ -675,11 +587,6 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line, error(line, "cannot convert a sampler", "constructor"); return false; } - if (op != EOpConstructStruct && IsImage(argTyped->getBasicType())) - { - error(line, "cannot convert an image", "constructor"); - return false; - } if (argTyped->getBasicType() == EbtVoid) { error(line, "cannot convert a void", "constructor"); @@ -754,19 +661,19 @@ void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped // or not. void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType) { - if (pType.getBasicType() != EbtBool || pType.isAggregate()) + if (pType.type != EbtBool || pType.isAggregate()) { error(line, "boolean expression expected", ""); } } bool TParseContext::checkIsNotSampler(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, + const TPublicType &pType, const char *reason) { if (pType.type == EbtStruct) { - if (ContainsSampler(*pType.userDef)) + if (containsSampler(*pType.userDef)) { error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); return false; @@ -783,31 +690,6 @@ bool TParseContext::checkIsNotSampler(const TSourceLoc &line, return true; } -bool TParseContext::checkIsNotImage(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason) -{ - if (pType.type == EbtStruct) - { - if (ContainsImage(*pType.userDef)) - { - error(line, reason, getBasicString(pType.type), "(structure contains an image)"); - - return false; - } - - return true; - } - else if (IsImage(pType.type)) - { - error(line, reason, getBasicString(pType.type)); - - return false; - } - - return true; -} - void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType) { @@ -828,34 +710,33 @@ void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location, } } -void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line, - TQualifier qualifier, - const TType &type) -{ - checkOutParameterIsNotSampler(line, qualifier, type); - checkOutParameterIsNotImage(line, qualifier, type); -} - void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line, TQualifier qualifier, const TType &type) { - ASSERT(qualifier == EvqOut || qualifier == EvqInOut); - if (IsSampler(type.getBasicType())) + if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && + IsSampler(type.getBasicType())) { error(line, "samplers cannot be output parameters", type.getBasicString()); } } -void TParseContext::checkOutParameterIsNotImage(const TSourceLoc &line, - TQualifier qualifier, - const TType &type) +bool TParseContext::containsSampler(const TType &type) { - ASSERT(qualifier == EvqOut || qualifier == EvqInOut); - if (IsImage(type.getBasicType())) + if (IsSampler(type.getBasicType())) + return true; + + if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) { - error(line, "images cannot be output parameters", type.getBasicString()); + const TFieldList &fields = type.getStruct()->fields(); + for (unsigned int i = 0; i < fields.size(); ++i) + { + if (containsSampler(*fields[i]->type())) + return true; + } } + + return false; } // Do size checking for an array type's size. @@ -942,7 +823,7 @@ bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPubl // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere. // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section // 4.3.4). - if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct && + if (mShaderVersion >= 300 && elementType.type == EbtStruct && sh::IsVarying(elementType.qualifier)) { error(line, "cannot declare arrays of structs of this qualifier", @@ -1047,33 +928,27 @@ bool TParseContext::declareVariable(const TSourceLoc &line, return true; } -void TParseContext::checkIsParameterQualifierValid( - const TSourceLoc &line, - const TTypeQualifierBuilder &typeQualifierBuilder, - TType *type) +void TParseContext::checkIsParameterQualifierValid(const TSourceLoc &line, + TQualifier qualifier, + TQualifier paramQualifier, + TType *type) { - TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(&mDiagnostics); - - if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut) + if (qualifier != EvqConst && qualifier != EvqTemporary) { - checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type); - } - - if (!IsImage(type->getBasicType())) - { - checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, line); + error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); + return; } - else + if (qualifier == EvqConst && paramQualifier != EvqIn) { - type->setMemoryQualifier(typeQualifier.memoryQualifier); + error(line, "qualifier not allowed with ", getQualifierString(qualifier), + getQualifierString(paramQualifier)); + return; } - type->setQualifier(typeQualifier.qualifier); - - if (typeQualifier.precision != EbpUndefined) - { - type->setPrecision(typeQualifier.precision); - } + if (qualifier == EvqConst) + type->setQualifier(EvqConstReadOnly); + else + type->setQualifier(paramQualifier); } bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension) @@ -1113,7 +988,7 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, case EvqVertexIn: case EvqFragmentOut: case EvqComputeIn: - if (publicType.getBasicType() == EbtStruct) + if (publicType.type == EbtStruct) { error(identifierLocation, "cannot be used with a structure", getQualifierString(publicType.qualifier)); @@ -1125,14 +1000,7 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, } if (publicType.qualifier != EvqUniform && - !checkIsNotSampler(identifierLocation, publicType.typeSpecifierNonArray, - "samplers must be uniform")) - { - return; - } - if (publicType.qualifier != EvqUniform && - !checkIsNotImage(identifierLocation, publicType.typeSpecifierNonArray, - "images must be uniform")) + !checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform")) { return; } @@ -1160,89 +1028,6 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, { checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier); } - - if (IsImage(publicType.getBasicType())) - { - - switch (layoutQualifier.imageInternalFormat) - { - case EiifRGBA32F: - case EiifRGBA16F: - case EiifR32F: - case EiifRGBA8: - case EiifRGBA8_SNORM: - if (!IsFloatImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires a floating image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifRGBA32I: - case EiifRGBA16I: - case EiifRGBA8I: - case EiifR32I: - if (!IsIntegerImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires an integer image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifRGBA32UI: - case EiifRGBA16UI: - case EiifRGBA8UI: - case EiifR32UI: - if (!IsUnsignedImage(publicType.getBasicType())) - { - error(identifierLocation, - "internal image format requires an unsigned image type", - getBasicString(publicType.getBasicType())); - return; - } - break; - case EiifUnspecified: - error(identifierLocation, "layout qualifier", "No image internal format specified"); - return; - default: - error(identifierLocation, "layout qualifier", "unrecognized token"); - return; - } - - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - switch (layoutQualifier.imageInternalFormat) - { - case EiifR32F: - case EiifR32I: - case EiifR32UI: - break; - default: - if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly) - { - error(identifierLocation, "layout qualifier", - "Except for images with the r32f, r32i and r32ui format qualifiers, " - "image variables must be qualified readonly and/or writeonly"); - return; - } - break; - } - } - else - { - - if (!checkInternalFormatIsNotSpecified(identifierLocation, - layoutQualifier.imageInternalFormat)) - { - return; - } - - if (!checkIsMemoryQualifierNotSpecified(publicType.memoryQualifier, identifierLocation)) - { - return; - } - } } void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location, @@ -1273,18 +1058,6 @@ bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, return true; } -bool TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location, - TLayoutImageInternalFormat internalFormat) -{ - if (internalFormat != EiifUnspecified) - { - error(location, "invalid layout qualifier:", getImageInternalFormatString(internalFormat), - "only valid when used with images"); - return false; - } - return true; -} - void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall) { @@ -1304,27 +1077,12 @@ void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, } } -void TParseContext::checkInvariantVariableQualifier(bool invariant, - const TQualifier qualifier, - const TSourceLoc &invariantLocation) +void TParseContext::checkInvariantIsOutVariableES3(const TQualifier qualifier, + const TSourceLoc &invariantLocation) { - if (!invariant) - return; - - if (mShaderVersion < 300) - { - // input variables in the fragment shader can be also qualified as invariant - if (!sh::CanBeInvariantESSL1(qualifier)) - { - error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); - } - } - else + if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut) { - if (!sh::CanBeInvariantESSL3OrGreater(qualifier)) - { - error(invariantLocation, "Cannot be qualified as invariant.", "invariant"); - } + error(invariantLocation, "Only out variables can be invariant.", "invariant"); } } @@ -1522,26 +1280,15 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, TIntermTyped *initializer, - TIntermBinary **initNode) + TIntermNode **intermNode) { - ASSERT(initNode != nullptr); - ASSERT(*initNode == nullptr); + ASSERT(intermNode != nullptr); TType type = TType(pType); TVariable *variable = nullptr; if (type.isUnsizedArray()) { - // We have not checked yet whether the initializer actually is an array or not. - if (initializer->isArray()) - { - type.setArraySize(initializer->getArraySize()); - } - else - { - // Having a non-array initializer for an unsized array will result in an error later, - // so we don't generate an error message here. - type.setArraySize(1u); - } + type.setArraySize(initializer->getArraySize()); } if (!declareVariable(line, identifier, type, &variable)) { @@ -1607,7 +1354,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, if (initializer->getAsConstantUnion()) { variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - *initNode = nullptr; + *intermNode = nullptr; return false; } else if (initializer->getAsSymbolNode()) @@ -1620,7 +1367,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, if (constArray) { variable->shareConstPointer(constArray); - *initNode = nullptr; + *intermNode = nullptr; return false; } } @@ -1628,8 +1375,8 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, TIntermSymbol *intermSymbol = intermediate.addSymbol( variable->getUniqueId(), variable->getName(), variable->getType(), line); - *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line); - if (*initNode == nullptr) + *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line); + if (*intermNode == nullptr) { assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); return true; @@ -1638,80 +1385,51 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, return false; } -void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier) -{ - checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision, - typeSpecifier->getBasicType()); - - if (mShaderVersion < 300 && typeSpecifier->array) - { - error(typeSpecifier->getLine(), "not supported", "first-class array"); - typeSpecifier->clearArrayness(); - } -} - -TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, +TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, + bool invariant, + TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier) { - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); - TPublicType returnType = typeSpecifier; - returnType.qualifier = typeQualifier.qualifier; - returnType.invariant = typeQualifier.invariant; - returnType.layoutQualifier = typeQualifier.layoutQualifier; - returnType.memoryQualifier = typeQualifier.memoryQualifier; - returnType.precision = typeSpecifier.precision; - - if (typeQualifier.precision != EbpUndefined) - { - returnType.precision = typeQualifier.precision; - } + returnType.qualifier = qualifier; + returnType.invariant = invariant; + returnType.layoutQualifier = layoutQualifier; - checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision, - typeSpecifier.getBasicType()); - - checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, - typeSpecifier.getLine()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); + checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, layoutQualifier); if (mShaderVersion < 300) { if (typeSpecifier.array) { - error(typeSpecifier.getLine(), "not supported", "first-class array"); + error(typeSpecifier.line, "not supported", "first-class array"); returnType.clearArrayness(); } - if (returnType.qualifier == EvqAttribute && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) + if (qualifier == EvqAttribute && + (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) { - error(typeSpecifier.getLine(), "cannot be bool or int", - getQualifierString(returnType.qualifier)); + error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); } - if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) && - (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt)) + if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) && + (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) { - error(typeSpecifier.getLine(), "cannot be bool or int", - getQualifierString(returnType.qualifier)); + error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); } } else { - if (!returnType.layoutQualifier.isEmpty()) + if (!layoutQualifier.isEmpty()) { - checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout"); + checkIsAtGlobalLevel(typeSpecifier.line, "layout"); } - if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || - returnType.qualifier == EvqFragmentOut) + if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut) { - checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, - typeSpecifier.getLine()); + checkInputOutputTypeIsValidES3(qualifier, typeSpecifier, typeSpecifier.line); } - if (returnType.qualifier == EvqComputeIn) + if (qualifier == EvqComputeIn) { - error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size", + error(typeSpecifier.line, "'in' can be only used to specify the local group size", "in"); } } @@ -1724,7 +1442,7 @@ void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TSourceLoc &qualifierLocation) { // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere. - if (type.getBasicType() == EbtBool) + if (type.type == EbtBool) { error(qualifierLocation, "cannot be bool", getQualifierString(qualifier)); } @@ -1742,7 +1460,7 @@ void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, return; case EvqFragmentOut: // ESSL 3.00 section 4.3.6 - if (type.typeSpecifierNonArray.isMatrix()) + if (type.isMatrix()) { error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier)); } @@ -1755,15 +1473,15 @@ void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of // restrictions. bool typeContainsIntegers = - (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt || - type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt)); + (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) || + type.isStructureContainingType(EbtUInt)); if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut) { error(qualifierLocation, "must use 'flat' interpolation here", getQualifierString(qualifier)); } - if (type.getBasicType() == EbtStruct) + if (type.type == EbtStruct) { // ESSL 3.00 sections 4.3.4 and 4.3.6. // These restrictions are only implied by the ESSL 3.00 spec, but @@ -1791,57 +1509,9 @@ void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier, } } -void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier) -{ - if (qualifier.getType() == QtStorage) - { - const TStorageQualifierWrapper &storageQualifier = - static_cast<const TStorageQualifierWrapper &>(qualifier); - if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst && - !symbolTable.atGlobalLevel()) - { - error(storageQualifier.getLine(), - "Local variables can only use the const storage qualifier.", - storageQualifier.getQualifierString().c_str()); - } - } -} - -bool TParseContext::checkIsMemoryQualifierNotSpecified(const TMemoryQualifier &memoryQualifier, - const TSourceLoc &location) -{ - if (memoryQualifier.readonly) - { - error(location, "Only allowed with images.", "readonly"); - return false; - } - if (memoryQualifier.writeonly) - { - error(location, "Only allowed with images.", "writeonly"); - return false; - } - if (memoryQualifier.coherent) - { - error(location, "Only allowed with images.", "coherent"); - return false; - } - if (memoryQualifier.restrictQualifier) - { - error(location, "Only allowed with images.", "restrict"); - return false; - } - if (memoryQualifier.volatileQualifier) - { - error(location, "Only allowed with images.", "volatile"); - return false; - } - return true; -} - -TIntermDeclaration *TParseContext::parseSingleDeclaration( - TPublicType &publicType, - const TSourceLoc &identifierOrTypeLocation, - const TString &identifier) +TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType, + const TSourceLoc &identifierOrTypeLocation, + const TString &identifier) { TType type(publicType); if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) && @@ -1877,9 +1547,6 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration( mDeferredSingleDeclarationErrorCheck = emptyDeclaration; - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierOrTypeLocation); - if (emptyDeclaration) { if (publicType.isUnsizedArray()) @@ -1900,23 +1567,17 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration( declareVariable(identifierOrTypeLocation, identifier, type, &variable); if (variable && symbol) - { symbol->setId(variable->getUniqueId()); - } } - // We append the symbol even if the declaration is empty, mainly because of struct declarations - // that may just declare a type. - declaration->appendDeclarator(symbol); - - return declaration; + return intermediate.makeAggregate(symbol, identifierOrTypeLocation); } -TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - TIntermTyped *indexExpression) +TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &indexLocation, + TIntermTyped *indexExpression) { mDeferredSingleDeclarationErrorCheck = false; @@ -1936,44 +1597,38 @@ TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(TPublicType &publ TVariable *variable = nullptr; declareVariable(identifierLocation, identifier, arrayType, &variable); - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation); if (variable && symbol) - { symbol->setId(variable->getUniqueId()); - declaration->appendDeclarator(symbol); - } - return declaration; + return intermediate.makeAggregate(symbol, identifierLocation); } -TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer) +TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer) { mDeferredSingleDeclarationErrorCheck = false; singleDeclarationErrorCheck(publicType, identifierLocation); - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - - TIntermBinary *initNode = nullptr; - if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode)) + TIntermNode *intermNode = nullptr; + if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode)) { - if (initNode) - { - declaration->appendDeclarator(initNode); - } + // + // Build intermediate representation + // + return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr; + } + else + { + return nullptr; } - return declaration; } -TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration( +TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration( TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, @@ -2001,81 +1656,58 @@ TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration( // This ensures useless error messages regarding the variable's non-arrayness won't follow. arrayType.setArraySize(size); - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->setLine(identifierLocation); - // initNode will correspond to the whole of "type b[n] = initializer". - TIntermBinary *initNode = nullptr; + TIntermNode *initNode = nullptr; if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) { - if (initNode) - { - declaration->appendDeclarator(initNode); - } + return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr; } - - return declaration; -} - -TIntermAggregate *TParseContext::parseInvariantDeclaration( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &identifierLoc, - const TString *identifier, - const TSymbol *symbol) -{ - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); - - if (!typeQualifier.invariant) + else { - error(identifierLoc, "Expected invariant", identifier->c_str()); return nullptr; } - if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying")) - { +} + +TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc, + const TSourceLoc &identifierLoc, + const TString *identifier, + const TSymbol *symbol) +{ + // invariant declaration + if (!checkIsAtGlobalLevel(invariantLoc, "invariant varying")) return nullptr; - } + if (!symbol) { error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); return nullptr; } - if (!IsQualifierUnspecified(typeQualifier.qualifier)) - { - error(identifierLoc, "invariant declaration specifies qualifier", - getQualifierString(typeQualifier.qualifier)); - } - if (typeQualifier.precision != EbpUndefined) - { - error(identifierLoc, "invariant declaration specifies precision", - getPrecisionString(typeQualifier.precision)); - } - if (!typeQualifier.layoutQualifier.isEmpty()) + else { - error(identifierLoc, "invariant declaration specifies layout", "'layout'"); - } - - const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); - ASSERT(variable); - const TType &type = variable->getType(); - - checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(), - typeQualifier.line); - checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - - symbolTable.addInvariantVarying(std::string(identifier->c_str())); - - TIntermSymbol *intermSymbol = - intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc); + const TString kGlFrontFacing("gl_FrontFacing"); + if (*identifier == kGlFrontFacing) + { + error(identifierLoc, "identifier should not be declared as invariant", + identifier->c_str()); + return nullptr; + } + symbolTable.addInvariantVarying(std::string(identifier->c_str())); + const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); + ASSERT(variable); + const TType &type = variable->getType(); + TIntermSymbol *intermSymbol = + intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc); - TIntermAggregate *aggregate = TIntermediate::MakeAggregate(intermSymbol, identifierLoc); - aggregate->setOp(EOpInvariantDeclaration); - return aggregate; + TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc); + aggregate->setOp(EOpInvariantDeclaration); + return aggregate; + } } -void TParseContext::parseDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - TIntermDeclaration *declarationOut) +TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier) { // If the declaration starting this declarator list was empty (example: int,), some checks were // not performed. @@ -2095,18 +1727,17 @@ void TParseContext::parseDeclarator(TPublicType &publicType, TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); if (variable && symbol) - { symbol->setId(variable->getUniqueId()); - declarationOut->appendDeclarator(symbol); - } + + return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); } -void TParseContext::parseArrayDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &arrayLocation, - TIntermTyped *indexExpression, - TIntermDeclaration *declarationOut) +TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &arrayLocation, + TIntermTyped *indexExpression) { // If the declaration starting this declarator list was empty (example: int,), some checks were // not performed. @@ -2134,16 +1765,18 @@ void TParseContext::parseArrayDeclarator(TPublicType &publicType, if (variable && symbol) symbol->setId(variable->getUniqueId()); - declarationOut->appendDeclarator(symbol); + return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); } + + return nullptr; } -void TParseContext::parseInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut) +TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer) { // If the declaration starting this declarator list was empty (example: int,), some checks were // not performed. @@ -2155,27 +1788,35 @@ void TParseContext::parseInitDeclarator(const TPublicType &publicType, checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType); - TIntermBinary *initNode = nullptr; - if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &initNode)) + TIntermNode *intermNode = nullptr; + if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode)) { // // build the intermediate representation // - if (initNode) + if (intermNode) { - declarationOut->appendDeclarator(initNode); + return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation); } + else + { + return aggregateDeclaration; + } + } + else + { + return nullptr; } } -void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - TIntermTyped *indexExpression, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut) +TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &indexLocation, + TIntermTyped *indexExpression, + const TSourceLoc &initLocation, + TIntermTyped *initializer) { // If the declaration starting this declarator list was empty (example: int,), some checks were // not performed. @@ -2203,24 +1844,28 @@ void TParseContext::parseArrayInitDeclarator(const TPublicType &publicType, arrayType.setArraySize(size); // initNode will correspond to the whole of "b[n] = initializer". - TIntermBinary *initNode = nullptr; + TIntermNode *initNode = nullptr; if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode)) { if (initNode) { - declarationOut->appendDeclarator(initNode); + return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation); + } + else + { + return aggregateDeclaration; } } + else + { + return nullptr; + } } -void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder) +void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) { - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; - checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier, - typeQualifier.line); - // It should never be the case, but some strange parser errors can send us here. if (layoutQualifier.isEmpty()) { @@ -2234,10 +1879,6 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type return; } - checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - - checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat); - if (typeQualifier.qualifier == EvqComputeIn) { if (mComputeShaderLocalSizeDeclared && @@ -2325,31 +1966,30 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type } } -TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &parsedFunction, +TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location) { - // Note: function found from the symbol table could be the same as parsedFunction if this is the - // first declaration. Either way the instance in the symbol table is used to track whether the - // function is declared multiple times. - TFunction *function = static_cast<TFunction *>( - symbolTable.find(parsedFunction.getMangledName(), getShaderVersion())); - if (function->hasPrototypeDeclaration() && mShaderVersion == 100) + // Note: symbolTableFunction could be the same as function if this is the first declaration. + // Either way the instance in the symbol table is used to track whether the function is declared + // multiple times. + TFunction *symbolTableFunction = + static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion())); + if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100) { // ESSL 1.00.17 section 4.2.7. // Doesn't apply to ESSL 3.00.4: see section 4.2.3. error(location, "duplicate function prototype declarations are not allowed", "function"); } - function->setHasPrototypeDeclaration(); + symbolTableFunction->setHasPrototypeDeclaration(); TIntermAggregate *prototype = new TIntermAggregate; - // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could - // point to the data that already exists in the symbol table. - prototype->setType(function->getReturnType()); - prototype->getFunctionSymbolInfo()->setFromFunction(*function); + prototype->setType(function.getReturnType()); + prototype->setName(function.getMangledName()); + prototype->setFunctionId(function.getUniqueId()); - for (size_t i = 0; i < function->getParamCount(); i++) + for (size_t i = 0; i < function.getParamCount(); i++) { - const TConstParameter ¶m = function->getParam(i); + const TConstParameter ¶m = function.getParam(i); if (param.name != 0) { TVariable variable(param.name, *param.type); @@ -2378,83 +2018,71 @@ TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction return prototype; } -TIntermFunctionDefinition *TParseContext::addFunctionDefinition( - const TFunction &function, - TIntermAggregate *functionParameters, - TIntermBlock *functionBody, - const TSourceLoc &location) +TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function, + TIntermAggregate *functionPrototype, + TIntermAggregate *functionBody, + const TSourceLoc &location) { - // Check that non-void functions have at least one return statement. + //?? Check that all paths return a value if return type != void ? + // May be best done as post process phase on intermediate code if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue) { error(location, "function does not return a value:", "", function.getName().c_str()); } - if (functionBody == nullptr) - { - functionBody = new TIntermBlock(); - functionBody->setLine(location); - } - TIntermFunctionDefinition *functionNode = - new TIntermFunctionDefinition(function.getReturnType(), functionParameters, functionBody); - functionNode->setLine(location); - - functionNode->getFunctionSymbolInfo()->setFromFunction(function); + TIntermAggregate *aggregate = + intermediate.growAggregate(functionPrototype, functionBody, location); + intermediate.setAggregateOperator(aggregate, EOpFunction, location); + aggregate->setName(function.getMangledName().c_str()); + aggregate->setType(function.getReturnType()); + aggregate->setFunctionId(function.getUniqueId()); symbolTable.pop(); - return functionNode; + return aggregate; } -void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, - TFunction **function, - TIntermAggregate **aggregateOut) +void TParseContext::parseFunctionPrototype(const TSourceLoc &location, + TFunction *function, + TIntermAggregate **aggregateOut) { - ASSERT(function); - ASSERT(*function); const TSymbol *builtIn = - symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion()); + symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion()); if (builtIn) { - error(location, "built-in functions cannot be redefined", (*function)->getName().c_str()); + error(location, "built-in functions cannot be redefined", function->getName().c_str()); } - else - { - TFunction *prevDec = static_cast<TFunction *>( - symbolTable.find((*function)->getMangledName(), getShaderVersion())); - - // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it - // would have just been put in the symbol table. Otherwise, we're looking up an earlier - // occurance. - if (*function != prevDec) - { - // Swap the parameters of the previous declaration to the parameters of the function - // definition (parameter names may differ). - prevDec->swapParameters(**function); - - // The function definition will share the same symbol as any previous declaration. - *function = prevDec; - } - - if ((*function)->isDefined()) - { - error(location, "function already has a body", (*function)->getName().c_str()); - } - (*function)->setDefined(); + TFunction *prevDec = + static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion())); + // + // Note: 'prevDec' could be 'function' if this is the first time we've seen function + // as it would have just been put in the symbol table. Otherwise, we're looking up + // an earlier occurance. + // + if (prevDec->isDefined()) + { + // Then this function already has a body. + error(location, "function already has a body", function->getName().c_str()); } + prevDec->setDefined(); + // + // Overload the unique ID of the definition to be the same unique ID as the declaration. + // Eventually we will probably want to have only a single definition and just swap the + // arguments to be the definition's arguments. + // + function->setUniqueId(prevDec->getUniqueId()); // Raise error message if main function takes any parameters or return anything other than void - if ((*function)->getName() == "main") + if (function->getName() == "main") { - if ((*function)->getParamCount() > 0) + if (function->getParamCount() > 0) { - error(location, "function cannot take any parameter(s)", - (*function)->getName().c_str()); + error(location, "function cannot take any parameter(s)", function->getName().c_str()); } - if ((*function)->getReturnType().getBasicType() != EbtVoid) + if (function->getReturnType().getBasicType() != EbtVoid) { - error(location, "", (*function)->getReturnType().getBasicString(), + error(location, "", function->getReturnType().getBasicString(), "main function cannot return a value"); } } @@ -2462,7 +2090,7 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, // // Remember the return type for later checking for RETURN statements. // - mCurrentFunctionType = &((*function)->getReturnType()); + mCurrentFunctionType = &(prevDec->getReturnType()); mFunctionReturnsValue = false; // @@ -2474,9 +2102,9 @@ void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location, // knows where to find parameters. // TIntermAggregate *paramNodes = new TIntermAggregate; - for (size_t i = 0; i < (*function)->getParamCount(); i++) + for (size_t i = 0; i < function->getParamCount(); i++) { - const TConstParameter ¶m = (*function)->getParam(i); + const TConstParameter ¶m = function->getParam(i); if (param.name != 0) { TVariable *variable = new TVariable(param.name, *param.type); @@ -2534,7 +2162,7 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF { if (prevDec->getReturnType() != function->getReturnType()) { - error(location, "function must have the same return type in all of its declarations", + error(location, "overloaded functions must have the same return type", function->getReturnType().getBasicString()); } for (size_t i = 0; i < prevDec->getParamCount(); ++i) @@ -2542,8 +2170,7 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF if (prevDec->getParam(i).type->getQualifier() != function->getParam(i).type->getQualifier()) { - error(location, - "function must have the same parameter qualifiers in all of its declarations", + error(location, "overloaded functions must have the same parameter qualifiers", function->getParam(i).type->getQualifierString()); } } @@ -2563,7 +2190,9 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF else { // Insert the unmangled name to detect potential future redefinition as a variable. - symbolTable.getOuterLevel()->insertUnmangled(function); + TFunction *newFunction = + new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType()); + symbolTable.getOuterLevel()->insertUnmangled(newFunction); } // We're at the inner scope level of the function's arguments and body statement. @@ -2591,10 +2220,8 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, { error(location, "no qualifiers allowed for function return", "layout"); } - // make sure a sampler or an image is not involved as well... - checkIsNotSampler(location, type.typeSpecifierNonArray, - "samplers can't be function return values"); - checkIsNotImage(location, type.typeSpecifierNonArray, "images can't be function return values"); + // make sure a sampler is not involved as well... + checkIsNotSampler(location, type, "samplers can't be function return values"); if (mShaderVersion < 300) { // Array return values are forbidden, but there's also no valid syntax for declaring array @@ -2616,14 +2243,14 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) { TPublicType publicType = publicTypeIn; - if (publicType.isStructSpecifier()) + if (publicType.isStructSpecifier) { - error(publicType.getLine(), "constructor can't be a structure definition", - getBasicString(publicType.getBasicType())); + error(publicType.line, "constructor can't be a structure definition", + getBasicString(publicType.type)); } TOperator op = EOpNull; - if (publicType.getUserDef()) + if (publicType.userDef) { op = EOpConstructStruct; } @@ -2632,9 +2259,8 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) op = sh::TypeToConstructorOperator(TType(publicType)); if (op == EOpNull) { - error(publicType.getLine(), "cannot construct this type", - getBasicString(publicType.getBasicType())); - publicType.setBasicType(EbtFloat); + error(publicType.line, "cannot construct this type", getBasicString(publicType.type)); + publicType.type = EbtFloat; op = EOpConstructFloat; } } @@ -2657,12 +2283,6 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType type = fnCall->getReturnType(); if (type.isUnsizedArray()) { - if (fnCall->getParamCount() == 0) - { - error(line, "implicitly sized array constructor must have at least one argument", "[]"); - type.setArraySize(1u); - return TIntermTyped::CreateZero(type); - } type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount())); } bool constType = true; @@ -2702,7 +2322,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, constructor->setType(type); - TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, &mDiagnostics); + TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor); if (constConstructor) { return constConstructor; @@ -2711,36 +2331,118 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, return constructor; } +// This function returns vector field(s) being accessed from a constant vector. +TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields, + TIntermConstantUnion *baseNode, + const TSourceLoc &location) +{ + const TConstantUnion *unionArray = baseNode->getUnionArrayPointer(); + ASSERT(unionArray); + + TConstantUnion *constArray = new TConstantUnion[fields.num]; + const auto &type = baseNode->getType(); + + for (int i = 0; i < fields.num; i++) + { + // Out-of-range indices should already be checked. + ASSERT(fields.offsets[i] < type.getNominalSize()); + constArray[i] = unionArray[fields.offsets[i]]; + } + return intermediate.addConstantUnion(constArray, type, location); +} + +// This function returns the column vector being accessed from a constant matrix. +TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index, + TIntermConstantUnion *baseNode, + const TSourceLoc &location) +{ + ASSERT(index < baseNode->getType().getCols()); + + const TConstantUnion *unionArray = baseNode->getUnionArrayPointer(); + int size = baseNode->getType().getRows(); + return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location); +} + +// This function returns an element of an array accessed from a constant array. +TIntermConstantUnion *TParseContext::foldArraySubscript(int index, + TIntermConstantUnion *baseNode, + const TSourceLoc &location) +{ + ASSERT(index < static_cast<int>(baseNode->getArraySize())); + + TType arrayElementType = baseNode->getType(); + arrayElementType.clearArrayness(); + size_t arrayElementSize = arrayElementType.getObjectSize(); + const TConstantUnion *unionArray = baseNode->getUnionArrayPointer(); + return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(), + location); +} + +// +// This function returns the value of a particular field inside a constant structure from the symbol +// table. +// If there is an embedded/nested struct, it appropriately calls addConstStructNested or +// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested +// struct. +// +TIntermTyped *TParseContext::addConstStruct(const TString &identifier, + TIntermTyped *node, + const TSourceLoc &line) +{ + const TFieldList &fields = node->getType().getStruct()->fields(); + size_t instanceSize = 0; + + for (size_t index = 0; index < fields.size(); ++index) + { + if (fields[index]->name() == identifier) + { + break; + } + else + { + instanceSize += fields[index]->type()->getObjectSize(); + } + } + + TIntermTyped *typedNode; + TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); + if (tempConstantNode) + { + const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer(); + + // type will be changed in the calling function + typedNode = intermediate.addConstantUnion(constArray + instanceSize, + tempConstantNode->getType(), line); + } + else + { + error(line, "Cannot offset into the structure", "Error"); + return nullptr; + } + + return typedNode; +} + // // Interface/uniform blocks // -TIntermDeclaration *TParseContext::addInterfaceBlock( - const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &nameLine, - const TString &blockName, - TFieldList *fieldList, - const TString *instanceName, - const TSourceLoc &instanceLine, - TIntermTyped *arrayIndex, - const TSourceLoc &arrayIndexLine) +TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier, + const TSourceLoc &nameLine, + const TString &blockName, + TFieldList *fieldList, + const TString *instanceName, + const TSourceLoc &instanceLine, + TIntermTyped *arrayIndex, + const TSourceLoc &arrayIndexLine) { checkIsNotReserved(nameLine, blockName); - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); - if (typeQualifier.qualifier != EvqUniform) { error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform"); } - if (typeQualifier.invariant) - { - error(typeQualifier.line, "invalid qualifier on interface block member", "invariant"); - } - - checkIsMemoryQualifierNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line); - TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier); @@ -2756,8 +2458,6 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier); - checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat); - TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName); if (!symbolTable.declare(blockNameSymbol)) { @@ -2775,12 +2475,6 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( "sampler types are not allowed in interface blocks"); } - if (IsImage(fieldType->getBasicType())) - { - error(field->line(), "unsupported type", fieldType->getBasicString(), - "image types are not allowed in interface blocks"); - } - const TQualifier qualifier = fieldType->getQualifier(); switch (qualifier) { @@ -2793,11 +2487,6 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( break; } - if (fieldType->isInvariant()) - { - error(field->line(), "invalid qualifier on interface block member", "invariant"); - } - // check layout qualifiers TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier); @@ -2876,14 +2565,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( symbolName = instanceTypeDef->getName(); } - TIntermSymbol *blockSymbol = - intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line); - TIntermDeclaration *declaration = new TIntermDeclaration(); - declaration->appendDeclarator(blockSymbol); - declaration->setLine(nameLine); + TIntermAggregate *aggregate = intermediate.makeAggregate( + intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), + nameLine); + aggregate->setOp(EOpDeclaration); exitStructDeclaration(); - return declaration; + return aggregate; } void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier) @@ -2904,9 +2592,15 @@ void TParseContext::exitStructDeclaration() --mStructNestingLevel; } +namespace +{ +const int kWebGLMaxStructNesting = 4; + +} // namespace + void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field) { - if (!sh::IsWebGLBasedSpec(mShaderSpec)) + if (!IsWebGLBasedSpec(mShaderSpec)) { return; } @@ -2936,6 +2630,8 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression) { + TIntermTyped *indexedExpression = NULL; + if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) { if (baseExpression->getAsSymbolNode()) @@ -2947,11 +2643,6 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, { error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); } - - TConstantUnion *unionArray = new TConstantUnion[1]; - unionArray->setFConst(0.0f); - return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), - location); } TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); @@ -2981,78 +2672,151 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, if (indexConstantUnion) { - // If an out-of-range index is not qualified as constant, the behavior in the spec is - // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may - // constant fold expressions that are not constant expressions). The most compatible way to - // handle this case is to report a warning instead of an error and force the index to be in - // the correct range. + // If the index is not qualified as constant, the behavior in the spec is undefined. This + // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold + // expressions that are not constant expressions). The most compatible way to handle this + // case is to report a warning instead of an error and force the index to be in the + // correct range. bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst; int index = indexConstantUnion->getIConst(0); + if (!baseExpression->isArray()) + { + // Array checks are done later because a different error message might be generated + // based on the index in some cases. + if (baseExpression->isVector()) + { + index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, + baseExpression->getType().getNominalSize(), + "vector field selection out of range", "[]"); + } + else if (baseExpression->isMatrix()) + { + index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, + baseExpression->getType().getCols(), + "matrix field selection out of range", "[]"); + } + } - int safeIndex = -1; - - if (baseExpression->isArray()) + TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion(); + if (baseConstantUnion) { - if (baseExpression->getQualifier() == EvqFragData && index > 0) + if (baseExpression->isArray()) { - if (mShaderSpec == SH_WEBGL2_SPEC) + index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, + baseExpression->getArraySize(), + "array index out of range", "[]"); + // Constant folding for array indexing. + indexedExpression = foldArraySubscript(index, baseConstantUnion, location); + } + else if (baseExpression->isVector()) + { + // Constant folding for vector indexing - reusing vector swizzle folding. + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = index; + indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location); + } + else if (baseExpression->isMatrix()) + { + // Constant folding for matrix indexing. + indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location); + } + } + else + { + int safeIndex = -1; + + if (baseExpression->isArray()) + { + if (baseExpression->getQualifier() == EvqFragData && index > 0) { - // Error has been already generated if index is not const. - if (indexExpression->getQualifier() == EvqConst) + if (mShaderSpec == SH_WEBGL2_SPEC) { - error(location, "", "[", - "array index for gl_FragData must be constant zero"); + // Error has been already generated if index is not const. + if (indexExpression->getQualifier() == EvqConst) + { + error(location, "", "[", + "array index for gl_FragData must be constant zero"); + } + safeIndex = 0; + } + else if (!isExtensionEnabled("GL_EXT_draw_buffers")) + { + outOfRangeError(outOfRangeIndexIsError, location, "", "[", + "array index for gl_FragData must be zero when " + "GL_EXT_draw_buffers is disabled"); + safeIndex = 0; } - safeIndex = 0; } - else if (!isExtensionEnabled("GL_EXT_draw_buffers")) + // Only do generic out-of-range check if similar error hasn't already been reported. + if (safeIndex < 0) { - outOfRangeError(outOfRangeIndexIsError, location, "", "[", - "array index for gl_FragData must be zero when " - "GL_EXT_draw_buffers is disabled"); - safeIndex = 0; + safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, + baseExpression->getArraySize(), + "array index out of range", "[]"); } } - // Only do generic out-of-range check if similar error hasn't already been reported. - if (safeIndex < 0) + + // Data of constant unions can't be changed, because it may be shared with other + // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new + // sanitized object. + if (safeIndex != -1) { - safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, - baseExpression->getArraySize(), - "array index out of range", "[]"); + TConstantUnion *safeConstantUnion = new TConstantUnion(); + safeConstantUnion->setIConst(safeIndex); + indexConstantUnion->replaceConstantUnion(safeConstantUnion); } - } - else if (baseExpression->isMatrix()) - { - safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, - baseExpression->getType().getCols(), - "matrix field selection out of range", "[]"); - } - else if (baseExpression->isVector()) - { - safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index, - baseExpression->getType().getNominalSize(), - "vector field selection out of range", "[]"); - } - ASSERT(safeIndex >= 0); - // Data of constant unions can't be changed, because it may be shared with other - // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new - // sanitized object. - if (safeIndex != index) - { - TConstantUnion *safeConstantUnion = new TConstantUnion(); - safeConstantUnion->setIConst(safeIndex); - indexConstantUnion->replaceConstantUnion(safeConstantUnion); + indexedExpression = + intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); } + } + else + { + indexedExpression = + intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); + } + + if (indexedExpression == 0) + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setFConst(0.0f); + indexedExpression = + intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); + } + else if (baseExpression->isArray()) + { + TType indexedType = baseExpression->getType(); + indexedType.clearArrayness(); + indexedExpression->setType(indexedType); + } + else if (baseExpression->isMatrix()) + { + indexedExpression->setType(TType(baseExpression->getBasicType(), + baseExpression->getPrecision(), EvqTemporary, + static_cast<unsigned char>(baseExpression->getRows()))); + } + else if (baseExpression->isVector()) + { + indexedExpression->setType( + TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary)); + } + else + { + indexedExpression->setType(baseExpression->getType()); + } - return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location, - &mDiagnostics); + if (baseExpression->getType().getQualifier() == EvqConst && + indexExpression->getType().getQualifier() == EvqConst) + { + indexedExpression->getTypePointer()->setQualifier(EvqConst); } else { - return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location, - &mDiagnostics); + indexedExpression->getTypePointer()->setQualifier(EvqTemporary); } + + return indexedExpression; } int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError, @@ -3085,10 +2849,11 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre const TString &fieldString, const TSourceLoc &fieldLocation) { + TIntermTyped *indexedExpression = NULL; + if (baseExpression->isArray()) { error(fieldLocation, "cannot apply dot operator to an array", "."); - return baseExpression; } if (baseExpression->isVector()) @@ -3101,19 +2866,41 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre fields.offsets[0] = 0; } - return TIntermediate::AddSwizzle(baseExpression, fields, dotLocation); + if (baseExpression->getAsConstantUnion()) + { + // constant folding for vector fields + indexedExpression = + foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation); + } + else + { + TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation); + indexedExpression = + intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation); + } + if (indexedExpression == nullptr) + { + indexedExpression = baseExpression; + } + else + { + // Note that the qualifier set here will be corrected later. + indexedExpression->setType(TType(baseExpression->getBasicType(), + baseExpression->getPrecision(), EvqTemporary, + static_cast<unsigned char>(fields.num))); + } } else if (baseExpression->getBasicType() == EbtStruct) { + bool fieldFound = false; const TFieldList &fields = baseExpression->getType().getStruct()->fields(); if (fields.empty()) { error(dotLocation, "structure has no fields", "Internal Error"); - return baseExpression; + indexedExpression = baseExpression; } else { - bool fieldFound = false; unsigned int i; for (i = 0; i < fields.size(); ++i) { @@ -3125,29 +2912,47 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre } if (fieldFound) { - TIntermTyped *index = TIntermTyped::CreateIndexNode(i); - index->setLine(fieldLocation); - return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, - dotLocation, &mDiagnostics); + if (baseExpression->getAsConstantUnion()) + { + indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation); + if (indexedExpression == 0) + { + indexedExpression = baseExpression; + } + else + { + indexedExpression->setType(*fields[i]->type()); + } + } + else + { + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped *index = intermediate.addConstantUnion( + unionArray, *fields[i]->type(), fieldLocation); + indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, + index, dotLocation); + indexedExpression->setType(*fields[i]->type()); + } } else { error(dotLocation, " no such field in structure", fieldString.c_str()); - return baseExpression; + indexedExpression = baseExpression; } } } else if (baseExpression->isInterfaceBlock()) { + bool fieldFound = false; const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields(); if (fields.empty()) { error(dotLocation, "interface block has no fields", "Internal Error"); - return baseExpression; + indexedExpression = baseExpression; } else { - bool fieldFound = false; unsigned int i; for (i = 0; i < fields.size(); ++i) { @@ -3159,15 +2964,18 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre } if (fieldFound) { - TIntermTyped *index = TIntermTyped::CreateIndexNode(i); - index->setLine(fieldLocation); - return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, - dotLocation, &mDiagnostics); + TConstantUnion *unionArray = new TConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped *index = + intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); + indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, + baseExpression, index, dotLocation); + indexedExpression->setType(*fields[i]->type()); } else { error(dotLocation, " no such field in interface block", fieldString.c_str()); - return baseExpression; + indexedExpression = baseExpression; } } } @@ -3185,8 +2993,19 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre "side", fieldString.c_str()); } - return baseExpression; + indexedExpression = baseExpression; + } + + if (baseExpression->getQualifier() == EvqConst) + { + indexedExpression->getTypePointer()->setQualifier(EvqConst); } + else + { + indexedExpression->getTypePointer()->setQualifier(EvqTemporary); + } + + return indexedExpression; } TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, @@ -3196,18 +3015,10 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp if (qualifierType == "shared") { - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared"); - } qualifier.blockStorage = EbsShared; } else if (qualifierType == "packed") { - if (sh::IsWebGLBasedSpec(mShaderSpec)) - { - error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed"); - } qualifier.blockStorage = EbsPacked; } else if (qualifierType == "std140") @@ -3227,72 +3038,6 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument"); } - else if (qualifierType == "rgba32f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32F; - } - else if (qualifierType == "rgba16f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16F; - } - else if (qualifierType == "r32f") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32F; - } - else if (qualifierType == "rgba8") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8; - } - else if (qualifierType == "rgba8_snorm") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8_SNORM; - } - else if (qualifierType == "rgba32i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32I; - } - else if (qualifierType == "rgba16i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16I; - } - else if (qualifierType == "rgba8i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8I; - } - else if (qualifierType == "r32i") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32I; - } - else if (qualifierType == "rgba32ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA32UI; - } - else if (qualifierType == "rgba16ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA16UI; - } - else if (qualifierType == "rgba8ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifRGBA8UI; - } - else if (qualifierType == "r32ui") - { - checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); - qualifier.imageInternalFormat = EiifR32UI; - } - else { error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); @@ -3338,7 +3083,6 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp else { qualifier.location = intValue; - qualifier.locationsSpecified = 1; } } else if (qualifierType == "local_size_x") @@ -3364,48 +3108,106 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp 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 rightQualifier, const TSourceLoc &rightQualifierLocation) { - return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation, - &mDiagnostics); + TLayoutQualifier joinedQualifier = leftQualifier; + + if (rightQualifier.location != -1) + { + joinedQualifier.location = rightQualifier.location; + } + if (rightQualifier.matrixPacking != EmpUnspecified) + { + joinedQualifier.matrixPacking = rightQualifier.matrixPacking; + } + if (rightQualifier.blockStorage != EbsUnspecified) + { + joinedQualifier.blockStorage = rightQualifier.blockStorage; + } + + for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i) + { + if (rightQualifier.localSize[i] != -1) + { + if (joinedQualifier.localSize[i] != -1 && + joinedQualifier.localSize[i] != rightQualifier.localSize[i]) + { + error(rightQualifierLocation, + "Cannot have multiple different work group size specifiers", + getWorkGroupSizeString(i)); + } + joinedQualifier.localSize[i] = rightQualifier.localSize[i]; + } + } + + return joinedQualifier; } -TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( - const TTypeQualifierBuilder &typeQualifierBuilder, - TPublicType *typeSpecifier, - TFieldList *fieldList) +TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, + TQualifier interpolationQualifier, + const TSourceLoc &storageLoc, + TQualifier storageQualifier) { - TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(&mDiagnostics); + TQualifier mergedQualifier = EvqSmoothIn; - typeSpecifier->qualifier = typeQualifier.qualifier; - typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; - typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier; - typeSpecifier->invariant = typeQualifier.invariant; - if (typeQualifier.precision != EbpUndefined) + if (storageQualifier == EvqFragmentIn) { - typeSpecifier->precision = typeQualifier.precision; + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqSmoothIn; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatIn; + else + UNREACHABLE(); + } + else if (storageQualifier == EvqCentroidIn) + { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqCentroidIn; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatIn; + else + UNREACHABLE(); + } + else if (storageQualifier == EvqVertexOut) + { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqSmoothOut; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatOut; + else + UNREACHABLE(); + } + else if (storageQualifier == EvqCentroidOut) + { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqCentroidOut; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatOut; + else + UNREACHABLE(); } - return addStructDeclaratorList(*typeSpecifier, fieldList); + else + { + error(interpolationLoc, + "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", + getInterpolationString(interpolationQualifier)); + + mergedQualifier = storageQualifier; + } + + TPublicType type; + type.setBasic(EbtVoid, mergedQualifier, storageLoc); + return type; } TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList) { - checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision, - typeSpecifier.getBasicType()); + checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type); - checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType()); - - checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier); + checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier); for (unsigned int i = 0; i < fieldList->size(); ++i) { @@ -3413,43 +3215,42 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif // Careful not to replace already known aspects of type, like array-ness // TType *type = (*fieldList)[i]->type(); - type->setBasicType(typeSpecifier.getBasicType()); - type->setPrimarySize(typeSpecifier.getPrimarySize()); - type->setSecondarySize(typeSpecifier.getSecondarySize()); + type->setBasicType(typeSpecifier.type); + type->setPrimarySize(typeSpecifier.primarySize); + type->setSecondarySize(typeSpecifier.secondarySize); type->setPrecision(typeSpecifier.precision); type->setQualifier(typeSpecifier.qualifier); type->setLayoutQualifier(typeSpecifier.layoutQualifier); - type->setMemoryQualifier(typeSpecifier.memoryQualifier); - type->setInvariant(typeSpecifier.invariant); // don't allow arrays of arrays if (type->isArray()) { - checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier); + checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier); } if (typeSpecifier.array) type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize)); - if (typeSpecifier.getUserDef()) + if (typeSpecifier.userDef) { - type->setStruct(typeSpecifier.getUserDef()->getStruct()); + type->setStruct(typeSpecifier.userDef->getStruct()); } - checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]); + checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]); } return fieldList; } -TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, - const TSourceLoc &nameLine, - const TString *structName, - TFieldList *fieldList) +TPublicType TParseContext::addStructure(const TSourceLoc &structLine, + const TSourceLoc &nameLine, + const TString *structName, + TFieldList *fieldList) { TStructure *structure = new TStructure(structName, fieldList); TType *structureType = new TType(structure); // Store a bool in the struct if we're at global scope, to allow us to // skip the local struct scoping workaround in HLSL. + structure->setUniqueId(TSymbolTable::nextUniqueId()); structure->setAtGlobalScope(symbolTable.atGlobalLevel()); if (!structName->empty()) @@ -3477,31 +3278,19 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine, getQualifierString(qualifier)); break; } - if (field.type()->isInvariant()) - { - error(field.line(), "invalid qualifier on struct member", "invariant"); - } - if (IsImage(field.type()->getBasicType())) - { - error(field.line(), "disallowed type in struct", field.type()->getBasicString()); - } - - checkIsMemoryQualifierNotSpecified(field.type()->getMemoryQualifier(), field.line()); - - checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier()); } - TTypeSpecifierNonArray typeSpecifierNonArray; - typeSpecifierNonArray.initialize(EbtStruct, structLine); - typeSpecifierNonArray.userDef = structureType; - typeSpecifierNonArray.isStructSpecifier = true; + TPublicType publicType; + publicType.setBasic(EbtStruct, EvqTemporary, structLine); + publicType.userDef = structureType; + publicType.isStructSpecifier = true; exitStructDeclaration(); - return typeSpecifierNonArray; + return publicType; } TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, - TIntermBlock *statementList, + TIntermAggregate *statementList, const TSourceLoc &loc) { TBasicType switchType = init->getBasicType(); @@ -3613,7 +3402,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, case EOpNegative: case EOpPositive: if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool || - child->isArray() || IsOpaqueType(child->getBasicType())) + child->isArray() || IsSampler(child->getBasicType())) { return nullptr; } @@ -3622,14 +3411,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, break; } - TIntermUnary *node = new TIntermUnary(op, child); - node->setLine(loc); - - TIntermTyped *foldedNode = node->fold(&mDiagnostics); - if (foldedNode) - return foldedNode; - - return node; + return intermediate.addUnaryMath(op, child, loc, funcReturnType); } TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) @@ -3778,14 +3560,6 @@ bool TParseContext::binaryOpCommonCheck(TOperator op, GetOperatorString(op)); return false; } - - if ((op == EOpAssign || op == EOpInitialize) && - left->getType().isStructureContainingImages()) - { - error(loc, "undefined operation for structs containing images", - GetOperatorString(op)); - return false; - } case EOpLessThan: case EOpGreaterThan: case EOpLessThanEqual: @@ -3916,12 +3690,10 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, case EOpLogicalAnd: ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() && !right->getType().getStruct()); - if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar()) + if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector()) { return nullptr; } - // Basic types matching should have been already checked. - ASSERT(right->getBasicType() == EbtBool); break; case EOpAdd: case EOpSub: @@ -4000,10 +3772,10 @@ TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, return node; } -TIntermBinary *TParseContext::createAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc) +TIntermTyped *TParseContext::createAssign(TOperator op, + TIntermTyped *left, + TIntermTyped *right, + const TSourceLoc &loc) { if (binaryOpCommonCheck(op, left, right, loc)) { @@ -4053,7 +3825,7 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left, ","); } - return TIntermediate::AddComma(left, right, loc, mShaderVersion); + return intermediate.addComma(left, right, loc, mShaderVersion); } TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) @@ -4105,7 +3877,7 @@ TIntermBranch *TParseContext::addBranch(TOperator op, void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall) { ASSERT(!functionCall->isUserDefined()); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); + const TString &name = functionCall->getName(); TIntermNode *offset = nullptr; TIntermSequence *arguments = functionCall->getSequence(); if (name.compare(0, 16, "texelFetchOffset") == 0 || @@ -4153,99 +3925,6 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall) } } -// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers -void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall) -{ - ASSERT(!functionCall->isUserDefined()); - const TString &name = functionCall->getFunctionSymbolInfo()->getName(); - - if (name.compare(0, 5, "image") == 0) - { - TIntermSequence *arguments = functionCall->getSequence(); - TIntermNode *imageNode = (*arguments)[0]; - TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode(); - - const TMemoryQualifier &memoryQualifier = imageSymbol->getMemoryQualifier(); - - if (name.compare(5, 5, "Store") == 0) - { - if (memoryQualifier.readonly) - { - error(imageNode->getLine(), - "'imageStore' cannot be used with images qualified as 'readonly'", - imageSymbol->getSymbol().c_str()); - } - } - else if (name.compare(5, 4, "Load") == 0) - { - if (memoryQualifier.writeonly) - { - error(imageNode->getLine(), - "'imageLoad' cannot be used with images qualified as 'writeonly'", - imageSymbol->getSymbol().c_str()); - } - } - } -} - -// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters -void TParseContext::checkImageMemoryAccessForUserDefinedFunctions( - const TFunction *functionDefinition, - const TIntermAggregate *functionCall) -{ - ASSERT(functionCall->isUserDefined()); - - const TIntermSequence &arguments = *functionCall->getSequence(); - - ASSERT(functionDefinition->getParamCount() == arguments.size()); - - for (size_t i = 0; i < arguments.size(); ++i) - { - const TType &functionArgumentType = arguments[i]->getAsTyped()->getType(); - const TType &functionParameterType = *functionDefinition->getParam(i).type; - ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType()); - - if (IsImage(functionArgumentType.getBasicType())) - { - const TMemoryQualifier &functionArgumentMemoryQualifier = - functionArgumentType.getMemoryQualifier(); - const TMemoryQualifier &functionParameterMemoryQualifier = - functionParameterType.getMemoryQualifier(); - if (functionArgumentMemoryQualifier.readonly && - !functionParameterMemoryQualifier.readonly) - { - error(functionCall->getLine(), - "Function call discards the 'readonly' qualifier from image", - arguments[i]->getAsSymbolNode()->getSymbol().c_str()); - } - - if (functionArgumentMemoryQualifier.writeonly && - !functionParameterMemoryQualifier.writeonly) - { - error(functionCall->getLine(), - "Function call discards the 'writeonly' qualifier from image", - arguments[i]->getAsSymbolNode()->getSymbol().c_str()); - } - - if (functionArgumentMemoryQualifier.coherent && - !functionParameterMemoryQualifier.coherent) - { - error(functionCall->getLine(), - "Function call discards the 'coherent' qualifier from image", - arguments[i]->getAsSymbolNode()->getSymbol().c_str()); - } - - if (functionArgumentMemoryQualifier.volatileQualifier && - !functionParameterMemoryQualifier.volatileQualifier) - { - error(functionCall->getLine(), - "Function call discards the 'volatile' qualifier from image", - arguments[i]->getAsSymbolNode()->getSymbol().c_str()); - } - } - } -} - TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, @@ -4361,8 +4040,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, // See if we can constant fold a built-in. Note that this may be possible even // if it is not const-qualified. - TIntermTyped *foldedNode = - intermediate.foldAggregateBuiltIn(aggregate, &mDiagnostics); + TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate); if (foldedNode) { callNode = foldedNode; @@ -4387,20 +4065,15 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, // if builtIn == true, it's definitely a builtIn function with EOpNull if (!builtIn) aggregate->setUserDefined(); - aggregate->getFunctionSymbolInfo()->setFromFunction(*fnCandidate); + aggregate->setName(fnCandidate->getMangledName()); + aggregate->setFunctionId(fnCandidate->getUniqueId()); - // This needs to happen after the function info including name is set + // This needs to happen after the name is set if (builtIn) { aggregate->setBuiltInFunctionPrecision(); checkTextureOffsetConst(aggregate); - - checkImageMemoryAccessForBuiltinFunctions(aggregate); - } - else - { - checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, aggregate); } callNode = aggregate; @@ -4422,46 +4095,34 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, } TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, + TIntermTyped *trueBlock, + TIntermTyped *falseBlock, const TSourceLoc &loc) { checkIsScalarBool(loc, cond); - if (trueExpression->getType() != falseExpression->getType()) + if (trueBlock->getType() != falseBlock->getType()) { - binaryOpError(loc, ":", trueExpression->getCompleteString(), - falseExpression->getCompleteString()); - return falseExpression; + binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString()); + return falseBlock; } - if (IsOpaqueType(trueExpression->getBasicType())) - { - // ESSL 1.00 section 4.1.7 - // ESSL 3.00 section 4.1.7 - // Opaque/sampler types are not allowed in most types of expressions, including ternary. - // Note that structs containing opaque types don't need to be checked as structs are - // forbidden below. - error(loc, "ternary operator is not allowed for opaque types", ":"); - return falseExpression; - } - // ESSL1 sections 5.2 and 5.7: // ESSL3 section 5.7: // Ternary operator is not among the operators allowed for structures/arrays. - if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct) + if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct) { error(loc, "ternary operator is not allowed for structures or arrays", ":"); - return falseExpression; + return falseBlock; } // WebGL2 section 5.26, the following results in an error: // "Ternary operator applied to void, arrays, or structs containing arrays" - if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid) + if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid) { error(loc, "ternary operator is not allowed for void", ":"); - return falseExpression; + return falseBlock; } - return TIntermediate::AddTernarySelection(cond, trueExpression, falseExpression, loc); + return intermediate.addSelection(cond, trueBlock, falseBlock, loc); } // @@ -4488,5 +4149,3 @@ int PaParseStrings(size_t count, return (error == 0) && (context->numErrors() == 0) ? 0 : 1; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ParseContext.h b/gfx/angle/src/compiler/translator/ParseContext.h index cdc80755a..cf153db36 100755 --- a/gfx/angle/src/compiler/translator/ParseContext.h +++ b/gfx/angle/src/compiler/translator/ParseContext.h @@ -11,12 +11,8 @@ #include "compiler/translator/DirectiveHandler.h" #include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" -#include "compiler/translator/QualifierTypes.h" #include "compiler/preprocessor/Preprocessor.h" -namespace sh -{ - struct TMatrixFields { bool wholeRow; @@ -34,12 +30,47 @@ class TParseContext : angle::NonCopyable public: TParseContext(TSymbolTable &symt, TExtensionBehavior &ext, + TIntermediate &interm, sh::GLenum type, ShShaderSpec spec, - ShCompileOptions options, + int options, bool checksPrecErrors, TInfoSink &is, - const ShBuiltInResources &resources); + const ShBuiltInResources &resources) + : intermediate(interm), + symbolTable(symt), + mDeferredSingleDeclarationErrorCheck(false), + mShaderType(type), + mShaderSpec(spec), + mCompileOptions(options), + mShaderVersion(100), + mTreeRoot(nullptr), + mLoopNestingLevel(0), + mStructNestingLevel(0), + mSwitchNestingLevel(0), + mCurrentFunctionType(nullptr), + mFunctionReturnsValue(false), + mChecksPrecisionErrors(checksPrecErrors), + mFragmentPrecisionHighOnESSL1(false), + mDefaultMatrixPacking(EmpColumnMajor), + mDefaultBlockStorage(EbsShared), + mDiagnostics(is), + mDirectiveHandler(ext, + mDiagnostics, + mShaderVersion, + mShaderType, + resources.WEBGL_debug_shader_precision == 1), + mPreprocessor(&mDiagnostics, &mDirectiveHandler), + mScanner(nullptr), + mUsesFragData(false), + mUsesFragColor(false), + mUsesSecondaryOutputs(false), + mMinProgramTexelOffset(resources.MinProgramTexelOffset), + mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), + mComputeShaderLocalSizeDeclared(false) + { + mComputeShaderLocalSize.fill(-1); + } const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } pp::Preprocessor &getPreprocessor() { return mPreprocessor; } @@ -62,8 +93,8 @@ class TParseContext : angle::NonCopyable const char *token, const char *extraInfo = ""); - TIntermBlock *getTreeRoot() const { return mTreeRoot; } - void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; } + TIntermNode *getTreeRoot() const { return mTreeRoot; } + void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } bool getFragmentPrecisionHigh() const { @@ -88,12 +119,6 @@ class TParseContext : angle::NonCopyable bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } sh::WorkGroupSize getComputeShaderLocalSize() const; - void enterFunctionDeclaration() { mDeclaringFunction = true; } - - void exitFunctionDeclaration() { mDeclaringFunction = false; } - - bool declaringFunction() const { return mDeclaringFunction; } - // This method is guaranteed to succeed, even if no variable with 'name' exists. const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); TIntermTyped *parseVariableIdentifier(const TSourceLoc &location, @@ -127,17 +152,16 @@ class TParseContext : angle::NonCopyable bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type); void checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type); void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType); - bool checkIsNotSampler(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason); - bool checkIsNotImage(const TSourceLoc &line, - const TTypeSpecifierNonArray &pType, - const char *reason); + bool checkIsNotSampler(const TSourceLoc &line, const TPublicType &pType, const char *reason); void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType); void checkLocationIsNotSpecified(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier); + void checkOutParameterIsNotSampler(const TSourceLoc &line, + TQualifier qualifier, + const TType &type); void checkIsParameterQualifierValid(const TSourceLoc &line, - const TTypeQualifierBuilder &typeQualifierBuilder, + TQualifier qualifier, + TQualifier paramQualifier, TType *type); bool checkCanUseExtension(const TSourceLoc &line, const TString &extension); void singleDeclarationErrorCheck(const TPublicType &publicType, @@ -147,16 +171,14 @@ class TParseContext : angle::NonCopyable int versionRequired); bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier); - bool checkInternalFormatIsNotSpecified(const TSourceLoc &location, - TLayoutImageInternalFormat internalFormat); + void functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall); - void checkInvariantVariableQualifier(bool invariant, - const TQualifier qualifier, - const TSourceLoc &invariantLocation); + void checkInvariantIsOutVariableES3(const TQualifier qualifier, + const TSourceLoc &invariantLocation); void checkInputOutputTypeIsValidES3(const TQualifier qualifier, const TPublicType &type, const TSourceLoc &qualifierLocation); - void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier); + const TPragma &pragma() const { return mDirectiveHandler.pragma(); } const TExtensionBehavior &extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); } bool supportsExtension(const char *extension); @@ -164,84 +186,86 @@ class TParseContext : angle::NonCopyable void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior); void handlePragmaDirective(const TSourceLoc &loc, const char *name, const char *value, bool stdgl); + bool containsSampler(const TType &type); const TFunction* findFunction( const TSourceLoc &line, TFunction *pfnCall, int inputShaderVersion, bool *builtIn = 0); bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, TIntermTyped *initializer, - TIntermBinary **initNode); + TIntermNode **intermNode); - void addFullySpecifiedType(TPublicType *typeSpecifier); - TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, + TPublicType addFullySpecifiedType(TQualifier qualifier, + bool invariant, + TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); - TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType, - const TSourceLoc &identifierOrTypeLocation, - const TString &identifier); - TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - TIntermTyped *indexExpression); - TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer); + TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, + const TSourceLoc &identifierOrTypeLocation, + const TString &identifier); + TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &indexLocation, + TIntermTyped *indexExpression); + TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer); // Parse a declaration like "type a[n] = initializer" // Note that this does not apply to declarations like "type[n] a = initializer" - TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - TIntermTyped *indexExpression, - const TSourceLoc &initLocation, - TIntermTyped *initializer); - - TIntermAggregate *parseInvariantDeclaration(const TTypeQualifierBuilder &typeQualifierBuilder, + TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &indexLocation, + TIntermTyped *indexExpression, + const TSourceLoc &initLocation, + TIntermTyped *initializer); + + TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, const TSymbol *symbol); - void parseDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - TIntermDeclaration *declarationOut); - void parseArrayDeclarator(TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &arrayLocation, - TIntermTyped *indexExpression, - TIntermDeclaration *declarationOut); - void parseInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut); + TIntermAggregate *parseDeclarator(TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier); + TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &arrayLocation, + TIntermTyped *indexExpression); + TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &initLocation, + TIntermTyped *initializer); // Parse a declarator like "a[n] = initializer" - void parseArrayInitDeclarator(const TPublicType &publicType, - const TSourceLoc &identifierLocation, - const TString &identifier, - const TSourceLoc &indexLocation, - TIntermTyped *indexExpression, - const TSourceLoc &initLocation, - TIntermTyped *initializer, - TIntermDeclaration *declarationOut); - - void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder); - TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &parsedFunction, + TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, + TIntermAggregate *aggregateDeclaration, + const TSourceLoc &identifierLocation, + const TString &identifier, + const TSourceLoc &indexLocation, + TIntermTyped *indexExpression, + const TSourceLoc &initLocation, + TIntermTyped *initializer); + + void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); + TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location); - TIntermFunctionDefinition *addFunctionDefinition(const TFunction &function, - TIntermAggregate *functionParameters, - TIntermBlock *functionBody, - const TSourceLoc &location); - void parseFunctionDefinitionHeader(const TSourceLoc &location, - TFunction **function, - TIntermAggregate **aggregateOut); + TIntermAggregate *addFunctionDefinition(const TFunction &function, + TIntermAggregate *functionPrototype, + TIntermAggregate *functionBody, + const TSourceLoc &location); + void parseFunctionPrototype(const TSourceLoc &location, + TFunction *function, + TIntermAggregate **aggregateOut); TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); TFunction *parseFunctionHeader(const TPublicType &type, @@ -253,6 +277,8 @@ class TParseContext : angle::NonCopyable TFunction *fnCall, const TSourceLoc &line); + TIntermTyped *addConstStruct( + const TString &identifier, TIntermTyped *node, const TSourceLoc& line); TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); @@ -261,24 +287,20 @@ class TParseContext : angle::NonCopyable const TString &fieldString, const TSourceLoc &fieldLocation); - TFieldList *addStructDeclaratorListWithQualifiers( - const TTypeQualifierBuilder &typeQualifierBuilder, - TPublicType *typeSpecifier, - TFieldList *fieldList); TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); - TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine, + TPublicType addStructure(const TSourceLoc &structLine, + const TSourceLoc &nameLine, + const TString *structName, + TFieldList *fieldList); + + TIntermAggregate* addInterfaceBlock(const TPublicType &typeQualifier, const TSourceLoc &nameLine, - const TString *structName, - TFieldList *fieldList); - - TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder, - const TSourceLoc &nameLine, - const TString &blockName, - TFieldList *fieldList, - const TString *instanceName, - const TSourceLoc &instanceLine, - TIntermTyped *arrayIndex, - const TSourceLoc &arrayIndexLine); + const TString &blockName, + TFieldList *fieldList, + const TString *instanceName, + const TSourceLoc &instanceLine, + TIntermTyped *arrayIndex, + const TSourceLoc& arrayIndexLine); void parseLocalSize(const TString &qualifierType, const TSourceLoc &qualifierTypeLine, @@ -293,10 +315,11 @@ class TParseContext : angle::NonCopyable const TSourceLoc &qualifierTypeLine, int intValue, const TSourceLoc &intValueLine); - TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc); TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier, const TSourceLoc &rightQualifierLocation); + TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, + const TSourceLoc &storageLoc, TQualifier storageQualifier); // Performs an error check for embedded struct declarations. void enterStructDeclaration(const TSourceLoc &line, const TString &identifier); @@ -304,9 +327,7 @@ class TParseContext : angle::NonCopyable void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field); - TIntermSwitch *addSwitch(TIntermTyped *init, - TIntermBlock *statementList, - const TSourceLoc &loc); + TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); TIntermCase *addDefault(const TSourceLoc &loc); @@ -325,22 +346,17 @@ class TParseContext : angle::NonCopyable TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); void checkTextureOffsetConst(TIntermAggregate *functionCall); - void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall); - void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition, - const TIntermAggregate *functionCall); TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError); - TIntermTyped *addTernarySelection(TIntermTyped *cond, - TIntermTyped *trueExpression, - TIntermTyped *falseExpression, - const TSourceLoc &line); + TIntermTyped *addTernarySelection( + TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line); // TODO(jmadill): make these private - TIntermediate intermediate; // to build a parse tree + TIntermediate &intermediate; // to hold and build a parse tree TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed private: @@ -352,6 +368,18 @@ class TParseContext : angle::NonCopyable const char *reason, const char *token); + // Constant folding for element access. Note that the returned node does not have the correct + // type - it is expected to be fixed later. + TIntermConstantUnion *foldVectorSwizzle(TVectorFields &fields, + TIntermConstantUnion *baseNode, + const TSourceLoc &location); + TIntermConstantUnion *foldMatrixSubscript(int index, + TIntermConstantUnion *baseNode, + const TSourceLoc &location); + TIntermConstantUnion *foldArraySubscript(int index, + TIntermConstantUnion *baseNode, + const TSourceLoc &location); + bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line, @@ -364,24 +392,10 @@ class TParseContext : angle::NonCopyable // Assumes that multiplication op has already been set based on the types. bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right); - bool checkIsMemoryQualifierNotSpecified(const TMemoryQualifier &memoryQualifier, - const TSourceLoc &location); - void checkOutParameterIsNotImage(const TSourceLoc &line, - TQualifier qualifier, - const TType &type); - void checkOutParameterIsNotOpaqueType(const TSourceLoc &line, - TQualifier qualifier, - const TType &type); - void checkOutParameterIsNotSampler(const TSourceLoc &line, - TQualifier qualifier, - const TType &type); - TIntermTyped *addBinaryMathInternal( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); - TIntermBinary *createAssign(TOperator op, - TIntermTyped *left, - TIntermTyped *right, - const TSourceLoc &loc); + TIntermTyped *createAssign( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); // The funcReturnType parameter is expected to be non-null when the operation is a built-in function. // It is expected to be null for other unary operators. TIntermTyped *createUnaryMath( @@ -395,18 +409,16 @@ class TParseContext : angle::NonCopyable bool mDeferredSingleDeclarationErrorCheck; sh::GLenum mShaderType; // vertex or fragment language (future: pack or unpack) - ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. - ShCompileOptions mCompileOptions; // Options passed to TCompiler + ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. + int mCompileOptions; // Options passed to TCompiler int mShaderVersion; - TIntermBlock *mTreeRoot; // root of parse tree being created + TIntermNode *mTreeRoot; // root of parse tree being created int mLoopNestingLevel; // 0 if outside all loops - int mStructNestingLevel; // incremented while parsing a struct declaration + int mStructNestingLevel; // incremented while parsing a struct declaration int mSwitchNestingLevel; // 0 if outside all switch statements - const TType - *mCurrentFunctionType; // the return type of the function that's currently being parsed + const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed bool mFunctionReturnsValue; // true if a non-void function has a return - bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared - // without precision, explicit or implicit. + bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling // ESSL1. TLayoutMatrixPacking mDefaultMatrixPacking; @@ -426,13 +438,9 @@ class TParseContext : angle::NonCopyable // keep track of local group size declared in layout. It should be declared only once. bool mComputeShaderLocalSizeDeclared; sh::WorkGroupSize mComputeShaderLocalSize; - // keeps track whether we are declaring / defining a function - bool mDeclaringFunction; }; int PaParseStrings( size_t count, const char *const string[], const int length[], TParseContext *context); -} // namespace sh - #endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_ diff --git a/gfx/angle/src/compiler/translator/PoolAlloc.cpp b/gfx/angle/src/compiler/translator/PoolAlloc.cpp index 3b44afe33..27e1c06b5 100755 --- a/gfx/angle/src/compiler/translator/PoolAlloc.cpp +++ b/gfx/angle/src/compiler/translator/PoolAlloc.cpp @@ -50,18 +50,29 @@ void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) // Implement the functionality of the TPoolAllocator class, which // is documented in PoolAlloc.h. // -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) - : alignment(allocationAlignment), -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - pageSize(growthIncrement), - freeList(0), - inUseList(0), - numCalls(0), - totalBytes(0), -#endif - mLocked(false) +TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : + pageSize(growthIncrement), + alignment(allocationAlignment), + freeList(0), + inUseList(0), + numCalls(0), + totalBytes(0), + mLocked(false) { // + // Don't allow page sizes we know are smaller than all common + // OS page sizes. + // + if (pageSize < 4*1024) + pageSize = 4*1024; + + // + // A large currentPageOffset indicates a new page needs to + // be obtained to allocate memory. + // + currentPageOffset = pageSize; + + // // Adjust alignment to be at least pointer aligned and // power of 2. // @@ -75,20 +86,6 @@ TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) alignment = a; alignmentMask = a - 1; -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - // - // Don't allow page sizes we know are smaller than all common - // OS page sizes. - // - if (pageSize < 4 * 1024) - pageSize = 4 * 1024; - - // - // A large currentPageOffset indicates a new page needs to - // be obtained to allocate memory. - // - currentPageOffset = pageSize; - // // Align header skip // @@ -96,14 +93,10 @@ TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) if (headerSkip < sizeof(tHeader)) { headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; } -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif } TPoolAllocator::~TPoolAllocator() { -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) while (inUseList) { tHeader* next = inUseList->nextPage; inUseList->~tHeader(); @@ -120,16 +113,6 @@ TPoolAllocator::~TPoolAllocator() delete [] reinterpret_cast<char*>(freeList); freeList = next; } -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - for (auto &allocs : mStack) - { - for (auto alloc : allocs) - { - free(alloc); - } - } - mStack.clear(); -#endif } // Support MSVC++ 6.0 @@ -170,18 +153,14 @@ void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, co void TPoolAllocator::push() { -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) tAllocState state = { currentPageOffset, inUseList }; - mStack.push_back(state); - + stack.push_back(state); + // // Indicate there is no current page to allocate from. // currentPageOffset = pageSize; -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - mStack.push_back({}); -#endif } // @@ -193,12 +172,11 @@ void TPoolAllocator::push() // void TPoolAllocator::pop() { - if (mStack.size() < 1) + if (stack.size() < 1) return; -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - tHeader *page = mStack.back().page; - currentPageOffset = mStack.back().offset; + tHeader* page = stack.back().page; + currentPageOffset = stack.back().offset; while (inUseList != page) { // invoke destructor to free allocation list @@ -214,14 +192,7 @@ void TPoolAllocator::pop() inUseList = nextInUse; } - mStack.pop_back(); -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - for (auto &alloc : mStack.back()) - { - free(alloc); - } - mStack.pop_back(); -#endif + stack.pop_back(); } // @@ -230,7 +201,7 @@ void TPoolAllocator::pop() // void TPoolAllocator::popAll() { - while (mStack.size() > 0) + while (stack.size() > 0) pop(); } @@ -238,7 +209,6 @@ void* TPoolAllocator::allocate(size_t numBytes) { ASSERT(!mLocked); -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) // // Just keep some interesting statistics. // @@ -315,14 +285,6 @@ void* TPoolAllocator::allocate(size_t numBytes) currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; return initializeAllocation(inUseList, ret, numBytes); -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - void *alloc = malloc(numBytes + alignmentMask); - mStack.back().push_back(alloc); - - intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc); - intAlloc = (intAlloc + alignmentMask) & ~alignmentMask; - return reinterpret_cast<void *>(intAlloc); -#endif } void TPoolAllocator::lock() diff --git a/gfx/angle/src/compiler/translator/PoolAlloc.h b/gfx/angle/src/compiler/translator/PoolAlloc.h index f15b3e05d..026e7a5c1 100755 --- a/gfx/angle/src/compiler/translator/PoolAlloc.h +++ b/gfx/angle/src/compiler/translator/PoolAlloc.h @@ -157,12 +157,7 @@ public: void lock(); void unlock(); - private: - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - -#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) +protected: friend struct tHeader; struct tHeader { @@ -205,21 +200,20 @@ public: } size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; size_t headerSkip; // amount of memory to skip to make room for the // header (basically, size of header, rounded // up to make it aligned size_t currentPageOffset; // next offset in top of inUseList to allocate from tHeader* freeList; // list of popped memory tHeader* inUseList; // list of all memory currently being used - tAllocStack mStack; // stack of where to allocate from, to partition pool + tAllocStack stack; // stack of where to allocate from, to partition pool int numCalls; // just an interesting statistic size_t totalBytes; // just an interesting statistic - -#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC) - std::vector<std::vector<void *>> mStack; -#endif - +private: TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor bool mLocked; diff --git a/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.cpp b/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.cpp index 7ec434796..8cbeb7dee 100755 --- a/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.cpp +++ b/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.cpp @@ -9,9 +9,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - namespace { @@ -21,7 +18,7 @@ class PruneEmptyDeclarationsTraverser : private TIntermTraverser static void apply(TIntermNode *root); private: PruneEmptyDeclarationsTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; }; void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root) @@ -36,71 +33,65 @@ PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser() { } -bool PruneEmptyDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +bool PruneEmptyDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node) { - TIntermSequence *sequence = node->getSequence(); - if (sequence->size() >= 1) + if (node->getOp() == EOpDeclaration) { - TIntermSymbol *sym = sequence->front()->getAsSymbolNode(); - // Prune declarations without a variable name, unless it's an interface block declaration. - if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock()) + TIntermSequence *sequence = node->getSequence(); + if (sequence->size() >= 1) { - if (sequence->size() > 1) - { - // Generate a replacement that will remove the empty declarator in the beginning of - // a declarator list. Example of a declaration that will be changed: - // float, a; - // will be changed to - // float a; - // This applies also to struct declarations. - TIntermSequence emptyReplacement; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(node, sym, emptyReplacement)); - } - else if (sym->getBasicType() != EbtStruct) + TIntermSymbol *sym = sequence->front()->getAsSymbolNode(); + // Prune declarations without a variable name, unless it's an interface block declaration. + if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock()) { - // Single struct declarations may just declare the struct type and no variables, so - // they should not be pruned. All other single empty declarations can be pruned - // entirely. Example of an empty declaration that will be pruned: - // float; - TIntermSequence emptyReplacement; - TIntermBlock *parentAsBlock = getParentNode()->getAsBlock(); - // The declaration may be inside a block or in a loop init expression. - ASSERT(parentAsBlock != nullptr || getParentNode()->getAsLoopNode() != nullptr); - if (parentAsBlock) + if (sequence->size() > 1) { - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement)); + // Generate a replacement that will remove the empty declarator in the beginning of a declarator + // list. Example of a declaration that will be changed: + // float, a; + // will be changed to + // float a; + // This applies also to struct declarations. + TIntermSequence emptyReplacement; + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(node, sym, emptyReplacement)); } - else + else if (sym->getBasicType() != EbtStruct) { - queueReplacement(node, nullptr, OriginalNode::IS_DROPPED); + // Single struct declarations may just declare the struct type and no variables, so they should + // not be pruned. All other single empty declarations can be pruned entirely. Example of an empty + // declaration that will be pruned: + // float; + TIntermSequence emptyReplacement; + TIntermAggregate *parentAgg = getParentNode()->getAsAggregate(); + ASSERT(parentAgg != nullptr); + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, emptyReplacement)); } - } - else if (sym->getType().getQualifier() != EvqGlobal && - sym->getType().getQualifier() != EvqTemporary) - { - // We've hit an empty struct declaration with a qualifier, for example like - // this: - // const struct a { int i; }; - // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so - // we convert the declaration to a regular struct declaration. This is okay, - // since ESSL 1.00 spec section 4.1.8 says about structs that "The optional - // qualifiers only apply to any declarators, and are not part of the type being - // defined for name." - - if (mInGlobalScope) - { - sym->getTypePointer()->setQualifier(EvqGlobal); - } - else + else if (sym->getType().getQualifier() != EvqGlobal && + sym->getType().getQualifier() != EvqTemporary) { - sym->getTypePointer()->setQualifier(EvqTemporary); + // We've hit an empty struct declaration with a qualifier, for example like + // this: + // const struct a { int i; }; + // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so + // we convert the declaration to a regular struct declaration. This is okay, + // since ESSL 1.00 spec section 4.1.8 says about structs that "The optional + // qualifiers only apply to any declarators, and are not part of the type being + // defined for name." + + if (mInGlobalScope) + { + sym->getTypePointer()->setQualifier(EvqGlobal); + } + else + { + sym->getTypePointer()->setQualifier(EvqTemporary); + } } } } + return false; } - return false; + return true; } } // namespace @@ -109,5 +100,3 @@ void PruneEmptyDeclarations(TIntermNode *root) { PruneEmptyDeclarationsTraverser::apply(root); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.h b/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.h index f03657766..122e83090 100755 --- a/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.h +++ b/gfx/angle/src/compiler/translator/PruneEmptyDeclarations.h @@ -8,11 +8,8 @@ #ifndef COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_ #define COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_ -namespace sh -{ class TIntermNode; void PruneEmptyDeclarations(TIntermNode *root); -} #endif // COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_ diff --git a/gfx/angle/src/compiler/translator/QualifierTypes.cpp b/gfx/angle/src/compiler/translator/QualifierTypes.cpp deleted file mode 100644 index 302f5177d..000000000 --- a/gfx/angle/src/compiler/translator/QualifierTypes.cpp +++ /dev/null @@ -1,727 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/QualifierTypes.h" - -#include "compiler/translator/Diagnostics.h" - -#include <algorithm> - -namespace sh -{ - -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; -} - -bool IsScopeQualifier(TQualifier qualifier) -{ - return qualifier == EvqGlobal || qualifier == EvqTemporary; -} - -bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier) -{ - if (qualifier->getType() != QtStorage) - return false; - const TStorageQualifierWrapper *storageQualifier = - static_cast<const TStorageQualifierWrapper *>(qualifier); - TQualifier q = storageQualifier->getQualifier(); - return IsScopeQualifier(q); -} - -// Returns true if the invariant for the qualifier sequence holds -bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers) -{ - // We should have at least one qualifier. - // The first qualifier always tells the scope. - return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]); -} - -// Returns true if there are qualifiers which have been specified multiple times -// If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed. -bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers, - bool areQualifierChecksRelaxed, - std::string *errorMessage) -{ - bool invariantFound = false; - bool precisionFound = false; - bool layoutFound = false; - bool interpolationFound = false; - - unsigned int locationsSpecified = 0; - bool isOut = false; - - // The iteration starts from one since the first qualifier only reveals the scope of the - // expression. It is inserted first whenever the sequence gets created. - for (size_t i = 1; i < qualifiers.size(); ++i) - { - switch (qualifiers[i]->getType()) - { - case QtInvariant: - { - if (invariantFound) - { - *errorMessage = "The invariant qualifier specified multiple times."; - return true; - } - invariantFound = true; - break; - } - case QtPrecision: - { - if (precisionFound) - { - *errorMessage = "The precision qualifier specified multiple times."; - return true; - } - precisionFound = true; - break; - } - case QtLayout: - { - if (layoutFound && !areQualifierChecksRelaxed) - { - *errorMessage = "The layout qualifier specified multiple times."; - return true; - } - if (invariantFound && !areQualifierChecksRelaxed) - { - // This combination is not correct according to the syntax specified in the - // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have - // a similar restriction. - *errorMessage = - "The layout qualifier and invariant qualifier cannot coexist in the same " - "declaration according to the grammar."; - return true; - } - layoutFound = true; - const TLayoutQualifier ¤tQualifier = - static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier(); - locationsSpecified += currentQualifier.locationsSpecified; - break; - } - case QtInterpolation: - { - // 'centroid' is treated as a storage qualifier - // 'flat centroid' will be squashed to 'flat' - // 'smooth centroid' will be squashed to 'centroid' - if (interpolationFound) - { - *errorMessage = "The interpolation qualifier specified multiple times."; - return true; - } - interpolationFound = true; - break; - } - case QtStorage: - { - // Go over all of the storage qualifiers up until the current one and check for - // repetitions. - TQualifier currentQualifier = - static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier(); - if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut) - { - isOut = true; - } - for (size_t j = 1; j < i; ++j) - { - if (qualifiers[j]->getType() == QtStorage) - { - const TStorageQualifierWrapper *previousQualifierWrapper = - static_cast<const TStorageQualifierWrapper *>(qualifiers[j]); - TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); - if (currentQualifier == previousQualifier) - { - *errorMessage = previousQualifierWrapper->getQualifierString().c_str(); - *errorMessage += " specified multiple times"; - return true; - } - } - } - break; - } - case QtMemory: - { - // Go over all of the memory qualifiers up until the current one and check for - // repetitions. - // Having both readonly and writeonly in a sequence is valid. - // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers - TQualifier currentQualifier = - static_cast<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier(); - for (size_t j = 1; j < i; ++j) - { - if (qualifiers[j]->getType() == QtMemory) - { - const TMemoryQualifierWrapper *previousQualifierWrapper = - static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]); - TQualifier previousQualifier = previousQualifierWrapper->getQualifier(); - if (currentQualifier == previousQualifier) - { - *errorMessage = previousQualifierWrapper->getQualifierString().c_str(); - *errorMessage += " specified multiple times"; - return true; - } - } - } - break; - } - default: - UNREACHABLE(); - } - } - - if (locationsSpecified > 1 && isOut) - { - // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers - // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers - // "The qualifier may appear at most once within a declaration." - *errorMessage = "Output layout location specified multiple times."; - return true; - } - - return false; -} - -// GLSL ES 3.00_6, 4.7 Order of Qualification -// The correct order of qualifiers is: -// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier -// layout-qualifier has to be before storage-qualifier. -bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers, - std::string *errorMessage) -{ - bool foundInterpolation = false; - bool foundStorage = false; - bool foundPrecision = false; - for (size_t i = 1; i < qualifiers.size(); ++i) - { - switch (qualifiers[i]->getType()) - { - case QtInvariant: - if (foundInterpolation || foundStorage || foundPrecision) - { - *errorMessage = "The invariant qualifier has to be first in the expression."; - return false; - } - break; - case QtInterpolation: - if (foundStorage) - { - *errorMessage = "Storage qualifiers have to be after interpolation qualifiers."; - return false; - } - else if (foundPrecision) - { - *errorMessage = - "Precision qualifiers have to be after interpolation qualifiers."; - return false; - } - foundInterpolation = true; - break; - case QtLayout: - if (foundStorage) - { - *errorMessage = "Storage qualifiers have to be after layout qualifiers."; - return false; - } - else if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after layout qualifiers."; - return false; - } - break; - case QtStorage: - if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after storage qualifiers."; - return false; - } - foundStorage = true; - break; - case QtMemory: - if (foundPrecision) - { - *errorMessage = "Precision qualifiers have to be after memory qualifiers."; - return false; - } - break; - case QtPrecision: - foundPrecision = true; - break; - default: - UNREACHABLE(); - } - } - return true; -} - -struct QualifierComparator -{ - bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2) - { - return q1->getRank() < q2->getRank(); - } -}; - -void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers) -{ - // We need a stable sorting algorithm since the order of layout-qualifier declarations matter. - // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope - // and we always want it to be first. - std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator()); -} - -// Handles the joining of storage qualifiers for variables. -bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) -{ - switch (*joinedQualifier) - { - case EvqGlobal: - *joinedQualifier = storageQualifier; - break; - case EvqTemporary: - { - switch (storageQualifier) - { - case EvqConst: - *joinedQualifier = storageQualifier; - break; - default: - return false; - } - break; - } - case EvqSmooth: - { - switch (storageQualifier) - { - case EvqCentroid: - *joinedQualifier = EvqCentroid; - break; - case EvqVertexOut: - *joinedQualifier = EvqSmoothOut; - break; - case EvqFragmentIn: - *joinedQualifier = EvqSmoothIn; - break; - default: - return false; - } - break; - } - case EvqFlat: - { - switch (storageQualifier) - { - case EvqCentroid: - *joinedQualifier = EvqFlat; - break; - case EvqVertexOut: - *joinedQualifier = EvqFlatOut; - break; - case EvqFragmentIn: - *joinedQualifier = EvqFlatIn; - break; - default: - return false; - } - break; - } - case EvqCentroid: - { - switch (storageQualifier) - { - case EvqVertexOut: - *joinedQualifier = EvqCentroidOut; - break; - case EvqFragmentIn: - *joinedQualifier = EvqCentroidIn; - break; - default: - return false; - } - break; - } - default: - return false; - } - return true; -} - -// Handles the joining of storage qualifiers for a parameter in a function. -bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier) -{ - switch (*joinedQualifier) - { - case EvqTemporary: - *joinedQualifier = storageQualifier; - break; - case EvqConst: - { - switch (storageQualifier) - { - case EvqIn: - *joinedQualifier = EvqConstReadOnly; - break; - default: - return false; - } - break; - } - default: - return false; - } - return true; -} - -bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier) -{ - switch (memoryQualifier) - { - case EvqReadOnly: - joinedMemoryQualifier->readonly = true; - break; - case EvqWriteOnly: - joinedMemoryQualifier->writeonly = true; - break; - case EvqCoherent: - joinedMemoryQualifier->coherent = true; - break; - case EvqRestrict: - joinedMemoryQualifier->restrictQualifier = true; - break; - case EvqVolatile: - // Variables having the volatile qualifier are automatcally treated as coherent as well. - // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers - joinedMemoryQualifier->volatileQualifier = true; - joinedMemoryQualifier->coherent = true; - break; - default: - UNREACHABLE(); - } - return true; -} - -TTypeQualifier GetVariableTypeQualifierFromSortedSequence( - const TTypeQualifierBuilder::QualifierSequence &sortedSequence, - TDiagnostics *diagnostics) -{ - TTypeQualifier typeQualifier( - static_cast<const TStorageQualifierWrapper *>(sortedSequence[0])->getQualifier(), - sortedSequence[0]->getLine()); - for (size_t i = 1; i < sortedSequence.size(); ++i) - { - const TQualifierWrapperBase *qualifier = sortedSequence[i]; - bool isQualifierValid = false; - switch (qualifier->getType()) - { - case QtInvariant: - isQualifierValid = true; - typeQualifier.invariant = true; - break; - case QtInterpolation: - { - switch (typeQualifier.qualifier) - { - case EvqGlobal: - isQualifierValid = true; - typeQualifier.qualifier = - static_cast<const TInterpolationQualifierWrapper *>(qualifier) - ->getQualifier(); - break; - default: - isQualifierValid = false; - } - break; - } - case QtLayout: - { - const TLayoutQualifierWrapper *layoutQualifierWrapper = - static_cast<const TLayoutQualifierWrapper *>(qualifier); - isQualifierValid = true; - typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers( - typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(), - layoutQualifierWrapper->getLine(), diagnostics); - break; - } - case QtStorage: - isQualifierValid = JoinVariableStorageQualifier( - &typeQualifier.qualifier, - static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier()); - break; - case QtPrecision: - isQualifierValid = true; - typeQualifier.precision = - static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier(); - ASSERT(typeQualifier.precision != EbpUndefined); - break; - case QtMemory: - isQualifierValid = JoinMemoryQualifier( - &typeQualifier.memoryQualifier, - static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier()); - break; - default: - UNREACHABLE(); - } - if (!isQualifierValid) - { - const TString &qualifierString = qualifier->getQualifierString(); - diagnostics->error(qualifier->getLine(), "invalid qualifier combination", - qualifierString.c_str(), ""); - break; - } - } - return typeQualifier; -} - -TTypeQualifier GetParameterTypeQualifierFromSortedSequence( - const TTypeQualifierBuilder::QualifierSequence &sortedSequence, - TDiagnostics *diagnostics) -{ - TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine()); - for (size_t i = 1; i < sortedSequence.size(); ++i) - { - const TQualifierWrapperBase *qualifier = sortedSequence[i]; - bool isQualifierValid = false; - switch (qualifier->getType()) - { - case QtInvariant: - case QtInterpolation: - case QtLayout: - break; - case QtMemory: - isQualifierValid = JoinMemoryQualifier( - &typeQualifier.memoryQualifier, - static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier()); - break; - case QtStorage: - isQualifierValid = JoinParameterStorageQualifier( - &typeQualifier.qualifier, - static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier()); - break; - case QtPrecision: - isQualifierValid = true; - typeQualifier.precision = - static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier(); - ASSERT(typeQualifier.precision != EbpUndefined); - break; - default: - UNREACHABLE(); - } - if (!isQualifierValid) - { - const TString &qualifierString = qualifier->getQualifierString(); - diagnostics->error(qualifier->getLine(), "invalid parameter qualifier", - qualifierString.c_str(), ""); - break; - } - } - - switch (typeQualifier.qualifier) - { - case EvqIn: - case EvqConstReadOnly: // const in - case EvqOut: - case EvqInOut: - break; - case EvqConst: - typeQualifier.qualifier = EvqConstReadOnly; - break; - case EvqTemporary: - // no qualifier has been specified, set it to EvqIn which is the default - typeQualifier.qualifier = EvqIn; - break; - default: - diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ", - getQualifierString(typeQualifier.qualifier), ""); - } - return typeQualifier; -} -} // namespace - -TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation, - TDiagnostics *diagnostics) -{ - TLayoutQualifier joinedQualifier = leftQualifier; - - if (rightQualifier.location != -1) - { - joinedQualifier.location = rightQualifier.location; - ++joinedQualifier.locationsSpecified; - } - if (rightQualifier.matrixPacking != EmpUnspecified) - { - joinedQualifier.matrixPacking = rightQualifier.matrixPacking; - } - if (rightQualifier.blockStorage != EbsUnspecified) - { - joinedQualifier.blockStorage = rightQualifier.blockStorage; - } - - for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i) - { - if (rightQualifier.localSize[i] != -1) - { - if (joinedQualifier.localSize[i] != -1 && - joinedQualifier.localSize[i] != rightQualifier.localSize[i]) - { - diagnostics->error(rightQualifierLocation, - "Cannot have multiple different work group size specifiers", - getWorkGroupSizeString(i), ""); - } - joinedQualifier.localSize[i] = rightQualifier.localSize[i]; - } - } - - if (rightQualifier.imageInternalFormat != EiifUnspecified) - { - joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat; - } - - return joinedQualifier; -} - -unsigned int TInvariantQualifierWrapper::getRank() const -{ - return 0u; -} - -unsigned int TInterpolationQualifierWrapper::getRank() const -{ - return 1u; -} - -unsigned int TLayoutQualifierWrapper::getRank() const -{ - return 2u; -} - -unsigned int TStorageQualifierWrapper::getRank() const -{ - // Force the 'centroid' auxilary storage qualifier to be always first among all storage - // qualifiers. - if (mStorageQualifier == EvqCentroid) - { - return 3u; - } - else - { - return 4u; - } -} - -unsigned int TMemoryQualifierWrapper::getRank() const -{ - return 4u; -} - -unsigned int TPrecisionQualifierWrapper::getRank() const -{ - return 5u; -} - -TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) - : layoutQualifier(TLayoutQualifier::create()), - memoryQualifier(TMemoryQualifier::create()), - precision(EbpUndefined), - qualifier(scope), - invariant(false), - line(loc) -{ - ASSERT(IsScopeQualifier(qualifier)); -} - -TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, - int shaderVersion) - : mShaderVersion(shaderVersion) -{ - ASSERT(IsScopeQualifier(scope->getQualifier())); - mQualifiers.push_back(scope); -} - -void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier) -{ - mQualifiers.push_back(qualifier); -} - -bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const -{ - bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion); - std::string errorMessage; - if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage)) - { - diagnostics->error(mQualifiers[0]->getLine(), "qualifier sequence", errorMessage.c_str(), - ""); - return false; - } - - if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage)) - { - diagnostics->error(mQualifiers[0]->getLine(), "qualifier sequence", errorMessage.c_str(), - ""); - return false; - } - - return true; -} - -TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const -{ - ASSERT(IsInvariantCorrect(mQualifiers)); - ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() == - EvqTemporary); - - if (!checkSequenceIsValid(diagnostics)) - { - return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine()); - } - - // 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 - // combine the qualifiers. - if (AreTypeQualifierChecksRelaxed(mShaderVersion)) - { - // Copy the qualifier sequence so that we can sort them. - QualifierSequence sortedQualifierSequence = mQualifiers; - SortSequence(sortedQualifierSequence); - return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); - } - return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics); -} - -TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const -{ - ASSERT(IsInvariantCorrect(mQualifiers)); - - if (!checkSequenceIsValid(diagnostics)) - { - return TTypeQualifier( - static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(), - mQualifiers[0]->getLine()); - } - - // 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 - // combine the qualifiers. - if (AreTypeQualifierChecksRelaxed(mShaderVersion)) - { - // Copy the qualifier sequence so that we can sort them. - QualifierSequence sortedQualifierSequence = mQualifiers; - SortSequence(sortedQualifierSequence); - return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics); - } - return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics); -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/QualifierTypes.h b/gfx/angle/src/compiler/translator/QualifierTypes.h deleted file mode 100644 index 10bdeed89..000000000 --- a/gfx/angle/src/compiler/translator/QualifierTypes.h +++ /dev/null @@ -1,191 +0,0 @@ -// -// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ -#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ - -#include "common/angleutils.h" -#include "compiler/translator/BaseTypes.h" -#include "compiler/translator/Types.h" - -namespace sh -{ -class TDiagnostics; - -TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, - TLayoutQualifier rightQualifier, - const TSourceLoc &rightQualifierLocation, - TDiagnostics *diagnostics); - -enum TQualifierType -{ - QtInvariant, - QtInterpolation, - QtLayout, - QtStorage, - QtPrecision, - QtMemory -}; - -class TQualifierWrapperBase : angle::NonCopyable -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {} - virtual ~TQualifierWrapperBase(){}; - virtual TQualifierType getType() const = 0; - virtual TString getQualifierString() const = 0; - virtual unsigned int getRank() const = 0; - const TSourceLoc &getLine() const { return mLine; } - private: - TSourceLoc mLine; -}; - -class TInvariantQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {} - ~TInvariantQualifierWrapper() {} - - TQualifierType getType() const { return QtInvariant; } - TString getQualifierString() const { return "invariant"; } - unsigned int getRank() const; -}; - -class TInterpolationQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier) - { - } - ~TInterpolationQualifierWrapper() {} - - TQualifierType getType() const { return QtInterpolation; } - TString getQualifierString() const { return sh::getQualifierString(mInterpolationQualifier); } - TQualifier getQualifier() const { return mInterpolationQualifier; } - unsigned int getRank() const; - - private: - TQualifier mInterpolationQualifier; -}; - -class TLayoutQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier) - { - } - ~TLayoutQualifierWrapper() {} - - TQualifierType getType() const { return QtLayout; } - TString getQualifierString() const { return "layout"; } - const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; } - unsigned int getRank() const; - - private: - TLayoutQualifier mLayoutQualifier; -}; - -class TStorageQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier) - { - } - ~TStorageQualifierWrapper() {} - - TQualifierType getType() const { return QtStorage; } - TString getQualifierString() const { return sh::getQualifierString(mStorageQualifier); } - TQualifier getQualifier() const { return mStorageQualifier; } - unsigned int getRank() const; - - private: - TQualifier mStorageQualifier; -}; - -class TPrecisionQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier) - { - } - ~TPrecisionQualifierWrapper() {} - - TQualifierType getType() const { return QtPrecision; } - TString getQualifierString() const { return sh::getPrecisionString(mPrecisionQualifier); } - TPrecision getQualifier() const { return mPrecisionQualifier; } - unsigned int getRank() const; - - private: - TPrecision mPrecisionQualifier; -}; - -class TMemoryQualifierWrapper final : public TQualifierWrapperBase -{ - public: - TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line) - : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier) - { - } - ~TMemoryQualifierWrapper() {} - - TQualifierType getType() const { return QtMemory; } - TString getQualifierString() const { return sh::getQualifierString(mMemoryQualifier); } - TQualifier getQualifier() const { return mMemoryQualifier; } - unsigned int getRank() const; - - private: - TQualifier mMemoryQualifier; -}; - -// TTypeQualifier tightly covers type_qualifier from the grammar -struct TTypeQualifier -{ - // initializes all of the qualifiers and sets the scope - TTypeQualifier(TQualifier scope, const TSourceLoc &loc); - - TLayoutQualifier layoutQualifier; - TMemoryQualifier memoryQualifier; - TPrecision precision; - TQualifier qualifier; - bool invariant; - TSourceLoc line; -}; - -// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed. -// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it. -class TTypeQualifierBuilder : angle::NonCopyable -{ - public: - using QualifierSequence = TVector<const TQualifierWrapperBase *>; - - public: - POOL_ALLOCATOR_NEW_DELETE(); - TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion); - // Adds the passed qualifier to the end of the sequence. - void appendQualifier(const TQualifierWrapperBase *qualifier); - // Checks for the order of qualification and repeating qualifiers. - bool checkSequenceIsValid(TDiagnostics *diagnostics) const; - // Goes over the qualifier sequence and parses it to form a type qualifier for a function - // parameter. - // The returned object is initialized even if the parsing fails. - TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const; - // 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. - TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const; - - private: - QualifierSequence mQualifiers; - int mShaderVersion; -}; - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_ diff --git a/gfx/angle/src/compiler/translator/RecordConstantPrecision.cpp b/gfx/angle/src/compiler/translator/RecordConstantPrecision.cpp index 6b8515a2c..af1d1d1a3 100755 --- a/gfx/angle/src/compiler/translator/RecordConstantPrecision.cpp +++ b/gfx/angle/src/compiler/translator/RecordConstantPrecision.cpp @@ -18,9 +18,6 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" -namespace sh -{ - namespace { @@ -48,11 +45,6 @@ RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser() bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand) { - if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock()) - { - return false; - } - const TIntermBinary *parentAsBinary = getParentNode()->getAsBinaryNode(); if (parentAsBinary != nullptr) { @@ -163,5 +155,3 @@ void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex) } while (traverser.foundHigherPrecisionConstant()); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RecordConstantPrecision.h b/gfx/angle/src/compiler/translator/RecordConstantPrecision.h index a62831e22..2cd401b41 100755 --- a/gfx/angle/src/compiler/translator/RecordConstantPrecision.h +++ b/gfx/angle/src/compiler/translator/RecordConstantPrecision.h @@ -16,11 +16,8 @@ #ifndef COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ #define COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ -namespace sh -{ class TIntermNode; void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex); -} // namespace sh #endif // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_ diff --git a/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp b/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp index a01d79abe..5e0db2ad2 100755 --- a/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp +++ b/gfx/angle/src/compiler/translator/RegenerateStructNames.cpp @@ -7,9 +7,6 @@ #include "common/debug.h" #include "compiler/translator/RegenerateStructNames.h" -namespace sh -{ - void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) { ASSERT(symbol); @@ -61,16 +58,25 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) userType->setName(tmp); } -bool RegenerateStructNames::visitBlock(Visit, TIntermBlock *block) +bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate) { - ++mScopeDepth; - TIntermSequence &sequence = *(block->getSequence()); - for (TIntermNode *node : sequence) + ASSERT(aggregate); + switch (aggregate->getOp()) { - node->traverse(this); + case EOpSequence: + ++mScopeDepth; + { + TIntermSequence &sequence = *(aggregate->getSequence()); + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermNode *node = sequence[ii]; + ASSERT(node != NULL); + node->traverse(this); + } + } + --mScopeDepth; + return false; + default: + return true; } - --mScopeDepth; - return false; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RegenerateStructNames.h b/gfx/angle/src/compiler/translator/RegenerateStructNames.h index 86c5060b3..3b98e5d70 100755 --- a/gfx/angle/src/compiler/translator/RegenerateStructNames.h +++ b/gfx/angle/src/compiler/translator/RegenerateStructNames.h @@ -12,9 +12,6 @@ #include <set> -namespace sh -{ - class RegenerateStructNames : public TIntermTraverser { public: @@ -27,7 +24,7 @@ class RegenerateStructNames : public TIntermTraverser protected: void visitSymbol(TIntermSymbol *) override; - bool visitBlock(Visit, TIntermBlock *block) override; + bool visitAggregate(Visit, TIntermAggregate *) override; private: const TSymbolTable &mSymbolTable; @@ -41,6 +38,4 @@ class RegenerateStructNames : public TIntermTraverser std::set<int> mDeclaredGlobalStructs; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ diff --git a/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.cpp b/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.cpp index 31914dcf3..37955e736 100755 --- a/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.cpp +++ b/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.cpp @@ -14,9 +14,6 @@ #include "compiler/translator/IntermNodePatternMatcher.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - namespace { @@ -95,15 +92,21 @@ TIntermBinary *CreateIndexDirectBaseSymbolNode(const TType &indexedType, const int index, TQualifier baseQualifier) { + TIntermBinary *indexNode = new TIntermBinary(EOpIndexDirect); + indexNode->setType(fieldType); TIntermSymbol *baseSymbol = CreateBaseSymbol(indexedType, baseQualifier); - TIntermBinary *indexNode = - new TIntermBinary(EOpIndexDirect, baseSymbol, TIntermTyped::CreateIndexNode(index)); + indexNode->setLeft(baseSymbol); + indexNode->setRight(CreateIntConstantNode(index)); return indexNode; } TIntermBinary *CreateAssignValueSymbolNode(TIntermTyped *targetNode, const TType &assignedValueType) { - return new TIntermBinary(EOpAssign, targetNode, CreateValueSymbol(assignedValueType)); + TIntermBinary *assignNode = new TIntermBinary(EOpAssign); + assignNode->setType(assignedValueType); + assignNode->setLeft(targetNode); + assignNode->setRight(CreateValueSymbol(assignedValueType)); + return assignNode; } TIntermTyped *EnsureSignedInt(TIntermTyped *node) @@ -175,7 +178,7 @@ TType GetFieldType(const TType &indexedType) // base[1] = value; // } // Note that else is not used in above functions to avoid the RewriteElseBlocks transformation. -TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write) +TIntermAggregate *GetIndexFunctionDefinition(TType type, bool write) { ASSERT(!type.isArray()); // Conservatively use highp here, even if the indexed type is not highp. That way the code can't @@ -183,6 +186,8 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write) // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in // principle this code could be used with multiple backends. type.setPrecision(EbpHigh); + TIntermAggregate *indexingFunction = new TIntermAggregate(EOpFunction); + indexingFunction->setNameObj(GetIndexFunctionName(type, write)); TType fieldType = GetFieldType(type); int numCases = 0; @@ -194,6 +199,14 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write) { numCases = type.getNominalSize(); } + if (write) + { + indexingFunction->setType(TType(EbtVoid)); + } + else + { + indexingFunction->setType(fieldType); + } TIntermAggregate *paramsNode = new TIntermAggregate(EOpParameters); TQualifier baseQualifier = EvqInOut; @@ -208,8 +221,9 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write) TIntermSymbol *valueParam = CreateValueSymbol(fieldType); paramsNode->getSequence()->push_back(valueParam); } + indexingFunction->getSequence()->push_back(paramsNode); - TIntermBlock *statementList = new TIntermBlock(); + TIntermAggregate *statementList = new TIntermAggregate(EOpSequence); for (int i = 0; i < numCases; ++i) { TIntermCase *caseNode = new TIntermCase(CreateIntConstantNode(i)); @@ -239,17 +253,18 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write) TIntermSwitch *switchNode = new TIntermSwitch(CreateIndexSymbol(), statementList); - TIntermBlock *bodyNode = new TIntermBlock(); + TIntermAggregate *bodyNode = new TIntermAggregate(EOpSequence); bodyNode->getSequence()->push_back(switchNode); - TIntermBinary *cond = - new TIntermBinary(EOpLessThan, CreateIndexSymbol(), CreateIntConstantNode(0)); + TIntermBinary *cond = new TIntermBinary(EOpLessThan); cond->setType(TType(EbtBool, EbpUndefined)); + cond->setLeft(CreateIndexSymbol()); + cond->setRight(CreateIntConstantNode(0)); // Two blocks: one accesses (either reads or writes) the first element and returns, // the other accesses the last element. - TIntermBlock *useFirstBlock = new TIntermBlock(); - TIntermBlock *useLastBlock = new TIntermBlock(); + TIntermAggregate *useFirstBlock = new TIntermAggregate(EOpSequence); + TIntermAggregate *useLastBlock = new TIntermAggregate(EOpSequence); TIntermBinary *indexFirstNode = CreateIndexDirectBaseSymbolNode(type, fieldType, 0, baseQualifier); TIntermBinary *indexLastNode = @@ -272,20 +287,12 @@ TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type, bool write) TIntermBranch *returnLastNode = new TIntermBranch(EOpReturn, indexLastNode); useLastBlock->getSequence()->push_back(returnLastNode); } - TIntermIfElse *ifNode = new TIntermIfElse(cond, useFirstBlock, nullptr); + TIntermSelection *ifNode = new TIntermSelection(cond, useFirstBlock, nullptr); bodyNode->getSequence()->push_back(ifNode); bodyNode->getSequence()->push_back(useLastBlock); - TIntermFunctionDefinition *indexingFunction = nullptr; - if (write) - { - indexingFunction = new TIntermFunctionDefinition(TType(EbtVoid), paramsNode, bodyNode); - } - else - { - indexingFunction = new TIntermFunctionDefinition(fieldType, paramsNode, bodyNode); - } - indexingFunction->getFunctionSymbolInfo()->setNameObj(GetIndexFunctionName(type, write)); + indexingFunction->getSequence()->push_back(bodyNode); + return indexingFunction; } @@ -327,8 +334,8 @@ RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(const TSymbolTabl void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root) { - TIntermBlock *rootBlock = root->getAsBlock(); - ASSERT(rootBlock != nullptr); + TIntermAggregate *rootAgg = root->getAsAggregate(); + ASSERT(rootAgg != nullptr && rootAgg->getOp() == EOpSequence); TIntermSequence insertions; for (TType type : mIndexedVecAndMatrixTypes) { @@ -338,7 +345,7 @@ void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root) { insertions.push_back(GetIndexFunctionDefinition(type, true)); } - mInsertions.push_back(NodeInsertMultipleEntry(rootBlock, 0, insertions, TIntermSequence())); + mInsertions.push_back(NodeInsertMultipleEntry(rootAgg, 0, insertions, TIntermSequence())); } // Create a call to dyn_index_*() based on an indirect indexing op node @@ -350,8 +357,7 @@ TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node, TIntermAggregate *indexingCall = new TIntermAggregate(EOpFunctionCall); indexingCall->setLine(node->getLine()); indexingCall->setUserDefined(); - indexingCall->getFunctionSymbolInfo()->setNameObj( - GetIndexFunctionName(indexedNode->getType(), false)); + indexingCall->setNameObj(GetIndexFunctionName(indexedNode->getType(), false)); indexingCall->getSequence()->push_back(indexedNode); indexingCall->getSequence()->push_back(index); @@ -369,8 +375,7 @@ TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node, ASSERT(leftCopy != nullptr && leftCopy->getAsTyped() != nullptr); TIntermAggregate *indexedWriteCall = CreateIndexFunctionCall(node, leftCopy->getAsTyped(), index); - indexedWriteCall->getFunctionSymbolInfo()->setNameObj( - GetIndexFunctionName(node->getLeft()->getType(), true)); + indexedWriteCall->setNameObj(GetIndexFunctionName(node->getLeft()->getType(), true)); indexedWriteCall->setType(TType(EbtVoid)); indexedWriteCall->getSequence()->push_back(writtenValue); return indexedWriteCall; @@ -393,7 +398,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod // Now v_expr[s0] can be safely executed several times without unintended side effects. // Init the temp variable holding the index - TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight()); + TIntermAggregate *initIndex = createTempInitDeclaration(node->getRight()); insertStatementInParentBlock(initIndex); mUsedTreeInsertion = true; @@ -444,7 +449,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod // Store the index in a temporary signed int variable. TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight()); - TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer); + TIntermAggregate *initIndex = createTempInitDeclaration(indexInitializer); initIndex->setLine(node->getLine()); insertionsBefore.push_back(initIndex); @@ -509,5 +514,3 @@ void RemoveDynamicIndexing(TIntermNode *root, traverser.insertHelperDefinitions(root); traverser.updateTree(); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.h b/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.h index 06305d0f8..ae3a93c9b 100755 --- a/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.h +++ b/gfx/angle/src/compiler/translator/RemoveDynamicIndexing.h @@ -10,9 +10,6 @@ #ifndef COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ #define COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ -namespace sh -{ - class TIntermNode; class TSymbolTable; @@ -21,6 +18,4 @@ void RemoveDynamicIndexing(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion); -} // namespace sh - #endif // COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_ diff --git a/gfx/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp b/gfx/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp deleted file mode 100644 index f6f016310..000000000 --- a/gfx/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/RemoveInvariantDeclaration.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -namespace -{ - -// An AST traverser that removes invariant declaration for input in fragment shader -// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2. -class RemoveInvariantDeclarationTraverser : public TIntermTraverser -{ - public: - RemoveInvariantDeclarationTraverser() : TIntermTraverser(true, false, false) {} - - private: - bool visitAggregate(Visit visit, TIntermAggregate *node) override - { - if (node->getOp() == EOpInvariantDeclaration) - { - TIntermSequence emptyReplacement; - mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), - node, emptyReplacement)); - return false; - } - return true; - } -}; - -} // anonymous namespace - -void RemoveInvariantDeclaration(TIntermNode *root) -{ - RemoveInvariantDeclarationTraverser traverser; - root->traverse(&traverser); - traverser.updateTree(); -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RemoveInvariantDeclaration.h b/gfx/angle/src/compiler/translator/RemoveInvariantDeclaration.h deleted file mode 100644 index cf9d4aa4c..000000000 --- a/gfx/angle/src/compiler/translator/RemoveInvariantDeclaration.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ -#define COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ - -class TIntermNode; -namespace sh -{ - -void RemoveInvariantDeclaration(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_ diff --git a/gfx/angle/src/compiler/translator/RemovePow.cpp b/gfx/angle/src/compiler/translator/RemovePow.cpp index 192084c36..ba505753a 100755 --- a/gfx/angle/src/compiler/translator/RemovePow.cpp +++ b/gfx/angle/src/compiler/translator/RemovePow.cpp @@ -13,9 +13,6 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" -namespace sh -{ - namespace { @@ -58,15 +55,19 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node) TIntermTyped *x = node->getSequence()->at(0)->getAsTyped(); TIntermTyped *y = node->getSequence()->at(1)->getAsTyped(); - TIntermUnary *log = new TIntermUnary(EOpLog2, x); + TIntermUnary *log = new TIntermUnary(EOpLog2); + log->setOperand(x); log->setLine(node->getLine()); + log->setType(x->getType()); TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType()); TIntermBinary *mul = new TIntermBinary(op, y, log); mul->setLine(node->getLine()); - TIntermUnary *exp = new TIntermUnary(EOpExp2, mul); + TIntermUnary *exp = new TIntermUnary(EOpExp2); + exp->setOperand(mul); exp->setLine(node->getLine()); + exp->setType(node->getType()); queueReplacement(node, exp, OriginalNode::IS_DROPPED); @@ -95,5 +96,3 @@ void RemovePow(TIntermNode *root) } while (traverser.needAnotherIteration()); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RemovePow.h b/gfx/angle/src/compiler/translator/RemovePow.h index 1e2f4e116..40f9d672b 100755 --- a/gfx/angle/src/compiler/translator/RemovePow.h +++ b/gfx/angle/src/compiler/translator/RemovePow.h @@ -11,11 +11,8 @@ #ifndef COMPILER_TRANSLATOR_REMOVEPOW_H_ #define COMPILER_TRANSLATOR_REMOVEPOW_H_ -namespace sh -{ class TIntermNode; void RemovePow(TIntermNode *root); -} // namespace sh #endif // COMPILER_TRANSLATOR_REMOVEPOW_H_ diff --git a/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp index dd995af47..b278b5343 100755 --- a/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp +++ b/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp @@ -6,10 +6,7 @@ #include "compiler/translator/RemoveSwitchFallThrough.h" -namespace sh -{ - -TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statementList) +TIntermAggregate *RemoveSwitchFallThrough::removeFallThrough(TIntermAggregate *statementList) { RemoveSwitchFallThrough rm(statementList); ASSERT(statementList); @@ -25,13 +22,14 @@ TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statement return rm.mStatementListOut; } -RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList) +RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermAggregate *statementList) : TIntermTraverser(true, false, false), mStatementList(statementList), mLastStatementWasBreak(false), mPreviousCase(nullptr) { - mStatementListOut = new TIntermBlock(); + mStatementListOut = new TIntermAggregate(); + mStatementListOut->setOp(EOpSequence); } void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node) @@ -64,14 +62,7 @@ bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node) return false; } -bool RemoveSwitchFallThrough::visitTernary(Visit, TIntermTernary *node) -{ - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThrough::visitIfElse(Visit, TIntermIfElse *node) +bool RemoveSwitchFallThrough::visitSelection(Visit, TIntermSelection *node) { mPreviousCase->getSequence()->push_back(node); mLastStatementWasBreak = false; @@ -132,7 +123,8 @@ void RemoveSwitchFallThrough::handlePreviousCase() bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node) { handlePreviousCase(); - mPreviousCase = new TIntermBlock(); + mPreviousCase = new TIntermAggregate(); + mPreviousCase->setOp(EOpSequence); mPreviousCase->getSequence()->push_back(node); // Don't traverse the condition of the case statement return false; @@ -140,13 +132,6 @@ bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node) bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node) { - mPreviousCase->getSequence()->push_back(node); - mLastStatementWasBreak = false; - return false; -} - -bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node) -{ if (node != mStatementList) { mPreviousCase->getSequence()->push_back(node); @@ -170,5 +155,3 @@ bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node) mLastStatementWasBreak = true; return false; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.h index fd8bf4fa2..db8699327 100755 --- a/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.h +++ b/gfx/angle/src/compiler/translator/RemoveSwitchFallThrough.h @@ -9,42 +9,35 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - class RemoveSwitchFallThrough : public TIntermTraverser { public: // When given a statementList from a switch AST node, return an updated // statementList that has fall-through removed. - static TIntermBlock *removeFallThrough(TIntermBlock *statementList); + static TIntermAggregate *removeFallThrough(TIntermAggregate *statementList); private: - RemoveSwitchFallThrough(TIntermBlock *statementList); + RemoveSwitchFallThrough(TIntermAggregate *statementList); void visitSymbol(TIntermSymbol *node) override; void visitConstantUnion(TIntermConstantUnion *node) override; bool visitBinary(Visit, TIntermBinary *node) override; bool visitUnary(Visit, TIntermUnary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; bool visitSwitch(Visit, TIntermSwitch *node) override; bool visitCase(Visit, TIntermCase *node) override; bool visitAggregate(Visit, TIntermAggregate *node) override; - bool visitBlock(Visit, TIntermBlock *node) override; bool visitLoop(Visit, TIntermLoop *node) override; bool visitBranch(Visit, TIntermBranch *node) override; void outputSequence(TIntermSequence *sequence, size_t startIndex); void handlePreviousCase(); - TIntermBlock *mStatementList; - TIntermBlock *mStatementListOut; + TIntermAggregate *mStatementList; + TIntermAggregate *mStatementListOut; bool mLastStatementWasBreak; - TIntermBlock *mPreviousCase; - std::vector<TIntermBlock *> mCasesSharingBreak; + TIntermAggregate *mPreviousCase; + std::vector<TIntermAggregate *> mCasesSharingBreak; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ diff --git a/gfx/angle/src/compiler/translator/RenameFunction.h b/gfx/angle/src/compiler/translator/RenameFunction.h new file mode 100644 index 000000000..fd6a365fe --- /dev/null +++ b/gfx/angle/src/compiler/translator/RenameFunction.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ +#define COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ + +#include "compiler/translator/IntermNode.h" + +// +// Renames a function, including its declaration and any calls to it. +// +class RenameFunction : public TIntermTraverser +{ +public: + RenameFunction(const TString& oldFunctionName, const TString& newFunctionName) + : TIntermTraverser(true, false, false) + , mOldFunctionName(oldFunctionName) + , mNewFunctionName(newFunctionName) {} + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + TOperator op = node->getOp(); + if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName) + node->setName(mNewFunctionName); + return true; + } + +private: + const TString mOldFunctionName; + const TString mNewFunctionName; +}; + +#endif // COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ diff --git a/gfx/angle/src/compiler/translator/RewriteDoWhile.cpp b/gfx/angle/src/compiler/translator/RewriteDoWhile.cpp index 7999cbf49..834744754 100755 --- a/gfx/angle/src/compiler/translator/RewriteDoWhile.cpp +++ b/gfx/angle/src/compiler/translator/RewriteDoWhile.cpp @@ -11,9 +11,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - namespace { @@ -46,11 +43,15 @@ class DoWhileRewriter : public TIntermTraverser public: DoWhileRewriter() : TIntermTraverser(true, false, false) {} - bool visitBlock(Visit, TIntermBlock *node) override + bool visitAggregate(Visit, TIntermAggregate *node) override { - // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal - // we are able to replace the do-while in the sequence directly as the content of the - // do-while will be traversed later. + // A well-formed AST can only have do-while in EOpSequence which represent lists of + // statements. By doing a prefix traversal we are able to replace the do-while in the + // sequence directly as the content of the do-while will be traversed later. + if (node->getOp() != EOpSequence) + { + return true; + } TIntermSequence *statements = node->getSequence(); @@ -70,7 +71,7 @@ class DoWhileRewriter : public TIntermTraverser TType boolType = TType(EbtBool); // bool temp = false; - TIntermDeclaration *tempDeclaration = nullptr; + TIntermAggregate *tempDeclaration = nullptr; { TConstantUnion *falseConstant = new TConstantUnion(); falseConstant->setBConst(false); @@ -94,22 +95,23 @@ class DoWhileRewriter : public TIntermTraverser // break; // } // } - TIntermIfElse *breakIf = nullptr; + TIntermSelection *breakIf = nullptr; { TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr); - TIntermBlock *breakBlock = new TIntermBlock(); + TIntermAggregate *breakBlock = new TIntermAggregate(EOpSequence); breakBlock->getSequence()->push_back(breakStatement); - TIntermUnary *negatedCondition = - new TIntermUnary(EOpLogicalNot, loop->getCondition()); + TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot); + negatedCondition->setOperand(loop->getCondition()); - TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr); + TIntermSelection *innerIf = + new TIntermSelection(negatedCondition, breakBlock, nullptr); - TIntermBlock *innerIfBlock = new TIntermBlock(); + TIntermAggregate *innerIfBlock = new TIntermAggregate(EOpSequence); innerIfBlock->getSequence()->push_back(innerIf); - breakIf = new TIntermIfElse(createTempSymbol(boolType), innerIfBlock, nullptr); + breakIf = new TIntermSelection(createTempSymbol(boolType), innerIfBlock, nullptr); } // Assemble the replacement loops, reusing the do-while loop's body and inserting our @@ -120,10 +122,14 @@ class DoWhileRewriter : public TIntermTraverser trueConstant->setBConst(true); TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType); - TIntermBlock *body = loop->getBody(); - if (body == nullptr) + TIntermAggregate *body = nullptr; + if (loop->getBody() != nullptr) { - body = new TIntermBlock(); + body = loop->getBody()->getAsAggregate(); + } + else + { + body = new TIntermAggregate(EOpSequence); } auto sequence = body->getSequence(); sequence->insert(sequence->begin(), assignTrue); @@ -155,5 +161,3 @@ void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex) root->traverse(&rewriter); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/RewriteDoWhile.h b/gfx/angle/src/compiler/translator/RewriteDoWhile.h index 91a7958c0..f6ec1caf0 100755 --- a/gfx/angle/src/compiler/translator/RewriteDoWhile.h +++ b/gfx/angle/src/compiler/translator/RewriteDoWhile.h @@ -10,10 +10,7 @@ #ifndef COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ #define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ -namespace sh -{ class TIntermNode; void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex); -} // namespace sh #endif // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_ diff --git a/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp b/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp index 937de11cd..52ede1743 100755 --- a/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp +++ b/gfx/angle/src/compiler/translator/RewriteElseBlocks.cpp @@ -8,8 +8,6 @@ // #include "compiler/translator/RewriteElseBlocks.h" - -#include "compiler/translator/Intermediate.h" #include "compiler/translator/NodeSearch.h" #include "compiler/translator/SymbolTable.h" @@ -25,60 +23,81 @@ class ElseBlockRewriter : public TIntermTraverser ElseBlockRewriter(); protected: - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override; - bool visitBlock(Visit visit, TIntermBlock *block) override; + bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override; private: const TType *mFunctionType; - TIntermNode *rewriteIfElse(TIntermIfElse *ifElse); + TIntermNode *rewriteSelection(TIntermSelection *selection); }; +TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand) +{ + TIntermUnary *unary = new TIntermUnary(op, operand->getType()); + unary->setOperand(operand); + return unary; +} + ElseBlockRewriter::ElseBlockRewriter() : TIntermTraverser(true, false, true), mFunctionType(NULL) {} -bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) +bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) { - // Store the current function context (see comment below) - mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr); - return true; -} - -bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node) -{ - if (visit == PostVisit) + switch (node->getOp()) { - for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); - statementIndex++) + case EOpSequence: + if (visit == PostVisit) { - TIntermNode *statement = (*node->getSequence())[statementIndex]; - TIntermIfElse *ifElse = statement->getAsIfElseNode(); - if (ifElse && ifElse->getFalseBlock() != nullptr) + for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++) { - (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse); + TIntermNode *statement = (*node->getSequence())[statementIndex]; + TIntermSelection *selection = statement->getAsSelectionNode(); + if (selection && selection->getFalseBlock() != nullptr) + { + // Check for if / else if + TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode(); + if (elseIfBranch) + { + selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch)); + delete elseIfBranch; + } + + (*node->getSequence())[statementIndex] = rewriteSelection(selection); + delete selection; + } } } + break; + + case EOpFunction: + // Store the current function context (see comment below) + mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL); + break; + + default: break; } + return true; } -TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) +TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection) { - ASSERT(ifElse != nullptr); + ASSERT(selection != nullptr); nextTemporaryIndex(); - TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition()); + TIntermTyped *typedCondition = selection->getCondition()->getAsTyped(); + TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition); - TIntermBlock *falseBlock = nullptr; + TIntermSelection *falseBlock = nullptr; TType boolType(EbtBool, EbpUndefined, EvqTemporary); - if (ifElse->getFalseBlock()) + if (selection->getFalseBlock()) { - TIntermBlock *negatedElse = nullptr; + TIntermAggregate *negatedElse = nullptr; // crbug.com/346463 // D3D generates error messages claiming a function has no return value, when rewriting // an if-else clause that returns something non-void in a function. By appending dummy @@ -89,24 +108,22 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) mFunctionType->getBasicString(); TString rawText = "return (" + typeString + ")0"; TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText); - negatedElse = new TIntermBlock(); + negatedElse = new TIntermAggregate(EOpSequence); negatedElse->getSequence()->push_back(returnNode); } TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType); - TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse); - TIntermIfElse *falseIfElse = - new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse); - falseBlock = TIntermediate::EnsureBlock(falseIfElse); + TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse); + falseBlock = new TIntermSelection(negatedCondition, + selection->getFalseBlock(), negatedElse); } TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType); - TIntermIfElse *newIfElse = - new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock); + TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, selection->getTrueBlock(), falseBlock); - TIntermBlock *block = new TIntermBlock(); + TIntermAggregate *block = new TIntermAggregate(EOpSequence); block->getSequence()->push_back(storeCondition); - block->getSequence()->push_back(newIfElse); + block->getSequence()->push_back(newSelection); return block; } diff --git a/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp b/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp index 487c90991..4ceceb226 100755 --- a/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp +++ b/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp @@ -22,6 +22,7 @@ class Traverser : public TIntermTraverser { public: static void Apply(TIntermNode *root, + unsigned int *tempIndex, const TSymbolTable &symbolTable, int shaderVersion); @@ -42,10 +43,12 @@ Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion) // static void Traverser::Apply(TIntermNode *root, + unsigned int *tempIndex, const TSymbolTable &symbolTable, int shaderVersion) { Traverser traverser(symbolTable, shaderVersion); + traverser.useTemporaryIndex(tempIndex); do { traverser.nextIteration(); @@ -60,6 +63,7 @@ void Traverser::Apply(TIntermNode *root, void Traverser::nextIteration() { mFound = false; + nextTemporaryIndex(); } bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) @@ -75,7 +79,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) return true; } - if (node->getFunctionSymbolInfo()->getName().compare(0, 16, "texelFetchOffset") != 0) + if (node->getName().compare(0, 16, "texelFetchOffset") != 0) { return true; } @@ -83,36 +87,42 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) // Potential problem case detected, apply workaround. const TIntermSequence *sequence = node->getSequence(); ASSERT(sequence->size() == 4u); + nextTemporaryIndex(); // Decide if there is a 2DArray sampler. - bool is2DArray = node->getFunctionSymbolInfo()->getName().find("s2a1") != TString::npos; + bool is2DArray = node->getName().find("s2a1") != TString::npos; // Create new argument list from node->getName(). // e.g. Get "(is2a1;vi3;i1;" from "texelFetchOffset(is2a1;vi3;i1;vi2;" - TString newArgs = node->getFunctionSymbolInfo()->getName().substr( - 16, node->getFunctionSymbolInfo()->getName().length() - 20); + TString newArgs = node->getName().substr(16, node->getName().length() - 20); TString newName = "texelFetch" + newArgs; TSymbol *texelFetchSymbol = symbolTable->findBuiltIn(newName, shaderVersion); ASSERT(texelFetchSymbol); int uniqueId = texelFetchSymbol->getUniqueId(); // Create new node that represents the call of function texelFetch. - // Its argument list will be: texelFetch(sampler, Position+offset, lod). TIntermAggregate *texelFetchNode = new TIntermAggregate(EOpFunctionCall); - texelFetchNode->getFunctionSymbolInfo()->setName(newName); - texelFetchNode->getFunctionSymbolInfo()->setId(uniqueId); + texelFetchNode->setName(newName); + texelFetchNode->setFunctionId(uniqueId); texelFetchNode->setType(node->getType()); texelFetchNode->setLine(node->getLine()); + // Create argument List of texelFetch(sampler, Position+offset, lod). + TIntermSequence newsequence; + // sampler - texelFetchNode->getSequence()->push_back(sequence->at(0)); + newsequence.push_back(sequence->at(0)); + // Position+offset + TIntermBinary *add = new TIntermBinary(EOpAdd); + add->setType(node->getType()); // Position TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped(); ASSERT(texCoordNode); - + add->setLine(texCoordNode->getLine()); + add->setType(texCoordNode->getType()); + add->setLeft(texCoordNode); // offset - TIntermTyped *offsetNode = nullptr; ASSERT(sequence->at(3)->getAsTyped()); if (is2DArray) { @@ -122,31 +132,28 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) constructIVec3Node->setLine(texCoordNode->getLine()); constructIVec3Node->setType(texCoordNode->getType()); - constructIVec3Node->getSequence()->push_back(sequence->at(3)->getAsTyped()); + TIntermSequence ivec3Sequence; + ivec3Sequence.push_back(sequence->at(3)->getAsTyped()); TConstantUnion *zero = new TConstantUnion(); zero->setIConst(0); TType *intType = new TType(EbtInt); TIntermConstantUnion *zeroNode = new TIntermConstantUnion(zero, *intType); - constructIVec3Node->getSequence()->push_back(zeroNode); + ivec3Sequence.push_back(zeroNode); + constructIVec3Node->insertChildNodes(0, ivec3Sequence); - offsetNode = constructIVec3Node; + add->setRight(constructIVec3Node); } else { - offsetNode = sequence->at(3)->getAsTyped(); + add->setRight(sequence->at(3)->getAsTyped()); } - - // Position+offset - TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode); - add->setLine(texCoordNode->getLine()); - texelFetchNode->getSequence()->push_back(add); + newsequence.push_back(add); // lod - texelFetchNode->getSequence()->push_back(sequence->at(2)); - - ASSERT(texelFetchNode->getSequence()->size() == 3u); + newsequence.push_back(sequence->at(2)); + texelFetchNode->insertChildNodes(0, newsequence); // Replace the old node by this new node. queueReplacement(node, texelFetchNode, OriginalNode::IS_DROPPED); @@ -157,6 +164,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) } // anonymous namespace void RewriteTexelFetchOffset(TIntermNode *root, + unsigned int *tempIndex, const TSymbolTable &symbolTable, int shaderVersion) { @@ -164,7 +172,7 @@ void RewriteTexelFetchOffset(TIntermNode *root, if (shaderVersion < 300) return; - Traverser::Apply(root, symbolTable, shaderVersion); + Traverser::Apply(root, tempIndex, symbolTable, shaderVersion); } } // namespace sh
\ No newline at end of file diff --git a/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.h b/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.h index 4218f0b69..a60c26331 100755 --- a/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.h +++ b/gfx/angle/src/compiler/translator/RewriteTexelFetchOffset.h @@ -22,6 +22,7 @@ namespace sh { void RewriteTexelFetchOffset(TIntermNode *root, + unsigned int *tempIndex, const TSymbolTable &symbolTable, int shaderVersion); diff --git a/gfx/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp b/gfx/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp deleted file mode 100644 index ef708cb2e..000000000 --- a/gfx/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of evaluating unary integer variable bug workaround. -// See header for more info. - -#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" - -#include "compiler/translator/IntermNode.h" - -namespace sh -{ - -namespace -{ - -class Traverser : public TIntermTraverser -{ - public: - static void Apply(TIntermNode *root); - - private: - Traverser(); - bool visitUnary(Visit visit, TIntermUnary *node) override; - void nextIteration(); - - bool mFound = false; -}; - -// static -void Traverser::Apply(TIntermNode *root) -{ - Traverser traverser; - do - { - traverser.nextIteration(); - root->traverse(&traverser); - if (traverser.mFound) - { - traverser.updateTree(); - } - } while (traverser.mFound); -} - -Traverser::Traverser() : TIntermTraverser(true, false, false) -{ -} - -void Traverser::nextIteration() -{ - mFound = false; -} - -bool Traverser::visitUnary(Visit visit, TIntermUnary *node) -{ - if (mFound) - { - return false; - } - - // Decide if the current unary operator is unary minus. - if (node->getOp() != EOpNegative) - { - return true; - } - - // Decide if the current operand is an integer variable. - TIntermTyped *opr = node->getOperand(); - if (!opr->getType().isScalarInt()) - { - return true; - } - - // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1. - // ~(int) - TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr); - bitwiseNot->setLine(opr->getLine()); - - // Constant 1 (or 1u) - TConstantUnion *one = new TConstantUnion(); - if (opr->getType().getBasicType() == EbtInt) - { - one->setIConst(1); - } - else - { - one->setUConst(1u); - } - TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, opr->getType()); - oneNode->getTypePointer()->setQualifier(EvqConst); - oneNode->setLine(opr->getLine()); - - // ~(int) + 1 - TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode); - add->setLine(opr->getLine()); - - queueReplacement(node, add, OriginalNode::IS_DROPPED); - - mFound = true; - return false; -} - -} // anonymous namespace - -void RewriteUnaryMinusOperatorInt(TIntermNode *root) -{ - Traverser::Apply(root); -} - -} // namespace sh
\ No newline at end of file diff --git a/gfx/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h b/gfx/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h deleted file mode 100644 index 50f0c442a..000000000 --- a/gfx/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This mutating tree traversal works around a bug on evaluating unary -// integer variable on Intel D3D driver. It works by rewriting -(int) to -// ~(int) + 1 when evaluating unary integer variables. - -#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ -#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ - -class TIntermNode; -namespace sh -{ - -void RewriteUnaryMinusOperatorInt(TIntermNode *root); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
\ No newline at end of file diff --git a/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp index 5afa0d308..775c5d871 100755 --- a/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp +++ b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -3,10 +3,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Scalarize vector and matrix constructor args, so that vectors built from components don't have -// matrix arguments, and matrices built from components don't have vector arguments. This avoids -// driver bugs around vector and matrix constructors. -// #include "common/debug.h" #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" @@ -15,10 +11,6 @@ #include "angle_gl.h" #include "common/angleutils.h" -#include "compiler/translator/IntermNode.h" - -namespace sh -{ namespace { @@ -45,9 +37,23 @@ bool ContainsVectorNode(const TIntermSequence &sequence) return false; } +TIntermConstantUnion *ConstructIndexNode(int index) +{ + TConstantUnion *u = new TConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index) { - return new TIntermBinary(EOpIndexDirect, symbolNode, TIntermTyped::CreateIndexNode(index)); + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(symbolNode); + TIntermConstantUnion *indexNode = ConstructIndexNode(index); + binary->setRight(indexNode); + return binary; } TIntermBinary *ConstructMatrixIndexBinaryNode( @@ -56,53 +62,40 @@ TIntermBinary *ConstructMatrixIndexBinaryNode( TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex); - return new TIntermBinary(EOpIndexDirect, colVectorNode, - TIntermTyped::CreateIndexNode(rowIndex)); + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(colVectorNode); + TIntermConstantUnion *rowIndexNode = ConstructIndexNode(rowIndex); + binary->setRight(rowIndexNode); + return binary; } -class ScalarizeArgsTraverser : public TIntermTraverser -{ - public: - ScalarizeArgsTraverser(sh::GLenum shaderType, - bool fragmentPrecisionHigh, - unsigned int *temporaryIndex) - : TIntermTraverser(true, false, false), - mShaderType(shaderType), - mFragmentPrecisionHigh(fragmentPrecisionHigh) - { - useTemporaryIndex(temporaryIndex); - } - - protected: - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitBlock(Visit visit, TIntermBlock *node) override; - - private: - void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix); - - // If we have the following code: - // mat4 m(0); - // vec4 v(1, m); - // We will rewrite to: - // mat4 m(0); - // mat4 s0 = m; - // vec4 v(1, s0[0][0], s0[0][1], s0[0][2]); - // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This - // way the possible side effects of the constructor argument will only be evaluated once. - void createTempVariable(TIntermTyped *original); - - std::vector<TIntermSequence> mBlockStack; - - sh::GLenum mShaderType; - bool mFragmentPrecisionHigh; -}; +} // namespace anonymous -bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +bool ScalarizeVecAndMatConstructorArgs::visitAggregate(Visit visit, TIntermAggregate *node) { if (visit == PreVisit) { switch (node->getOp()) { + case EOpSequence: + mSequenceStack.push_back(TIntermSequence()); + { + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *child = *iter; + ASSERT(child != NULL); + child->traverse(this); + mSequenceStack.back().push_back(child); + } + } + if (mSequenceStack.back().size() > node->getSequence()->size()) + { + node->getSequence()->clear(); + *(node->getSequence()) = mSequenceStack.back(); + } + mSequenceStack.pop_back(); + return false; case EOpConstructVec2: case EOpConstructVec3: case EOpConstructVec4: @@ -134,29 +127,8 @@ bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node) return true; } -bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - mBlockStack.push_back(TIntermSequence()); - { - for (TIntermNode *child : *node->getSequence()) - { - ASSERT(child != nullptr); - child->traverse(this); - mBlockStack.back().push_back(child); - } - } - if (mBlockStack.back().size() > node->getSequence()->size()) - { - node->getSequence()->clear(); - *(node->getSequence()) = mBlockStack.back(); - } - mBlockStack.pop_back(); - return false; -} - -void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, - bool scalarizeVector, - bool scalarizeMatrix) +void ScalarizeVecAndMatConstructorArgs::scalarizeArgs( + TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix) { ASSERT(aggregate); int size = 0; @@ -207,10 +179,12 @@ void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, ASSERT(size > 0); TIntermTyped *node = original[ii]->getAsTyped(); ASSERT(node); - createTempVariable(node); + TString varName = createTempVariable(node); if (node->isScalar()) { - sequence->push_back(createTempSymbol(node->getType())); + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); size--; } else if (node->isVector()) @@ -221,7 +195,8 @@ void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, size -= repeat; for (int index = 0; index < repeat; ++index) { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); TIntermBinary *newNode = ConstructVectorIndexBinaryNode( symbolNode, index); sequence->push_back(newNode); @@ -229,7 +204,8 @@ void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, } else { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); sequence->push_back(symbolNode); size -= node->getNominalSize(); } @@ -244,7 +220,8 @@ void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, size -= repeat; while (repeat > 0) { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); TIntermBinary *newNode = ConstructMatrixIndexBinaryNode( symbolNode, colIndex, rowIndex); sequence->push_back(newNode); @@ -259,7 +236,8 @@ void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, } else { - TIntermSymbol *symbolNode = createTempSymbol(node->getType()); + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); sequence->push_back(symbolNode); size -= node->getCols() * node->getRows(); } @@ -267,13 +245,29 @@ void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate, } } -void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original) +TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original) { - ASSERT(original); - nextTemporaryIndex(); - TIntermDeclaration *decl = createTempInitDeclaration(original); + TString tempVarName = "_webgl_tmp_"; + if (original->isScalar()) + { + tempVarName += "scalar_"; + } + else if (original->isVector()) + { + tempVarName += "vec_"; + } + else + { + ASSERT(original->isMatrix()); + tempVarName += "mat_"; + } + tempVarName += Str(mTempVarCount).c_str(); + mTempVarCount++; + ASSERT(original); TType type = original->getType(); + type.setQualifier(EvqTemporary); + if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat && type.getPrecision() == EbpUndefined) @@ -281,26 +275,21 @@ void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original) // We use the highest available precision for the temporary variable // to avoid computing the actual precision using the rules defined // in GLSL ES 1.0 Section 4.5.2. - TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode(); - init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); - init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh - : EbpMedium); + type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); } - ASSERT(mBlockStack.size() > 0); - TIntermSequence &sequence = mBlockStack.back(); - sequence.push_back(decl); -} + TIntermBinary *init = new TIntermBinary(EOpInitialize); + TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); + init->setLeft(symbolNode); + init->setRight(original); + init->setType(type); -} // namespace anonymous + TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration); + decl->getSequence()->push_back(init); -void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root, - sh::GLenum shaderType, - bool fragmentPrecisionHigh, - unsigned int *temporaryIndex) -{ - ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, temporaryIndex); - root->traverse(&scalarizer); -} + ASSERT(mSequenceStack.size() > 0); + TIntermSequence &sequence = mSequenceStack.back(); + sequence.push_back(decl); -} // namespace sh + return tempVarName; +} diff --git a/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h index 14bbbe13e..d7553be23 100755 --- a/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ b/gfx/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -3,24 +3,46 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Scalarize vector and matrix constructor args, so that vectors built from components don't have -// matrix arguments, and matrices built from components don't have vector arguments. This avoids -// driver bugs around vector and matrix constructors. -// #ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ #define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ -#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/IntermNode.h" -namespace sh +class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser { -class TIntermBlock; + public: + ScalarizeVecAndMatConstructorArgs(sh::GLenum shaderType, + bool fragmentPrecisionHigh) + : TIntermTraverser(true, false, false), + mTempVarCount(0), + mShaderType(shaderType), + mFragmentPrecisionHigh(fragmentPrecisionHigh) {} + + protected: + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + + private: + void scalarizeArgs(TIntermAggregate *aggregate, + bool scalarizeVector, bool scalarizeMatrix); + + // If we have the following code: + // mat4 m(0); + // vec4 v(1, m); + // We will rewrite to: + // mat4 m(0); + // mat4 _webgl_tmp_mat_0 = m; + // vec4 v(1, _webgl_tmp_mat_0[0][0], _webgl_tmp_mat_0[0][1], _webgl_tmp_mat_0[0][2]); + // This function is to create nodes for "mat4 _webgl_tmp_mat_0 = m;" and insert it to + // the code sequence. + // Return the temporary variable name. + TString createTempVariable(TIntermTyped *original); + + std::vector<TIntermSequence> mSequenceStack; + int mTempVarCount; -void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root, - sh::GLenum shaderType, - bool fragmentPrecisionHigh, - unsigned int *temporaryIndex); -} // namespace sh + sh::GLenum mShaderType; + bool mFragmentPrecisionHigh; +}; #endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ diff --git a/gfx/angle/src/compiler/translator/SeparateArrayInitialization.cpp b/gfx/angle/src/compiler/translator/SeparateArrayInitialization.cpp index 98e010a56..de9050cd8 100755 --- a/gfx/angle/src/compiler/translator/SeparateArrayInitialization.cpp +++ b/gfx/angle/src/compiler/translator/SeparateArrayInitialization.cpp @@ -20,9 +20,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/OutputHLSL.h" -namespace sh -{ - namespace { @@ -32,7 +29,7 @@ class SeparateArrayInitTraverser : private TIntermTraverser static void apply(TIntermNode *root); private: SeparateArrayInitTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; }; void SeparateArrayInitTraverser::apply(TIntermNode *root) @@ -47,38 +44,44 @@ SeparateArrayInitTraverser::SeparateArrayInitTraverser() { } -bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node) { - TIntermSequence *sequence = node->getSequence(); - TIntermBinary *initNode = sequence->back()->getAsBinaryNode(); - if (initNode != nullptr && initNode->getOp() == EOpInitialize) + if (node->getOp() == EOpDeclaration) { - TIntermTyped *initializer = initNode->getRight(); - if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer)) + TIntermSequence *sequence = node->getSequence(); + TIntermBinary *initNode = sequence->back()->getAsBinaryNode(); + if (initNode != nullptr && initNode->getOp() == EOpInitialize) { - // We rely on that array declarations have been isolated to single declarations. - ASSERT(sequence->size() == 1); - TIntermTyped *symbol = initNode->getLeft(); - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - ASSERT(parentBlock != nullptr); + TIntermTyped *initializer = initNode->getRight(); + if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer)) + { + // We rely on that array declarations have been isolated to single declarations. + ASSERT(sequence->size() == 1); + TIntermTyped *symbol = initNode->getLeft(); + TIntermAggregate *parentAgg = getParentNode()->getAsAggregate(); + ASSERT(parentAgg != nullptr); - TIntermSequence replacements; + TIntermSequence replacements; - TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); - replacementDeclaration->appendDeclarator(symbol); - replacementDeclaration->setLine(symbol->getLine()); - replacements.push_back(replacementDeclaration); + TIntermAggregate *replacementDeclaration = new TIntermAggregate; + replacementDeclaration->setOp(EOpDeclaration); + replacementDeclaration->getSequence()->push_back(symbol); + replacementDeclaration->setLine(symbol->getLine()); + replacements.push_back(replacementDeclaration); - TIntermBinary *replacementAssignment = - new TIntermBinary(EOpAssign, symbol, initializer); - replacementAssignment->setLine(symbol->getLine()); - replacements.push_back(replacementAssignment); + TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign); + replacementAssignment->setLeft(symbol); + replacementAssignment->setRight(initializer); + replacementAssignment->setType(initializer->getType()); + replacementAssignment->setLine(symbol->getLine()); + replacements.push_back(replacementAssignment); - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements)); + } } + return false; } - return false; + return true; } } // namespace @@ -87,5 +90,3 @@ void SeparateArrayInitialization(TIntermNode *root) { SeparateArrayInitTraverser::apply(root); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SeparateArrayInitialization.h b/gfx/angle/src/compiler/translator/SeparateArrayInitialization.h index 038d38a61..d16357a3a 100755 --- a/gfx/angle/src/compiler/translator/SeparateArrayInitialization.h +++ b/gfx/angle/src/compiler/translator/SeparateArrayInitialization.h @@ -18,11 +18,8 @@ #ifndef COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ #define COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ -namespace sh -{ class TIntermNode; void SeparateArrayInitialization(TIntermNode *root); -} // namespace sh #endif // COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_ diff --git a/gfx/angle/src/compiler/translator/SeparateDeclarations.cpp b/gfx/angle/src/compiler/translator/SeparateDeclarations.cpp index 4d3835370..d33747f85 100755 --- a/gfx/angle/src/compiler/translator/SeparateDeclarations.cpp +++ b/gfx/angle/src/compiler/translator/SeparateDeclarations.cpp @@ -17,9 +17,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - namespace { @@ -29,7 +26,7 @@ class SeparateDeclarationsTraverser : private TIntermTraverser static void apply(TIntermNode *root); private: SeparateDeclarationsTraverser(); - bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; }; void SeparateDeclarationsTraverser::apply(TIntermNode *root) @@ -44,28 +41,32 @@ SeparateDeclarationsTraverser::SeparateDeclarationsTraverser() { } -bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node) +bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node) { - TIntermSequence *sequence = node->getSequence(); - if (sequence->size() > 1) + if (node->getOp() == EOpDeclaration) { - TIntermBlock *parentBlock = getParentNode()->getAsBlock(); - ASSERT(parentBlock != nullptr); - - TIntermSequence replacementDeclarations; - for (size_t ii = 0; ii < sequence->size(); ++ii) + TIntermSequence *sequence = node->getSequence(); + if (sequence->size() > 1) { - TIntermDeclaration *replacementDeclaration = new TIntermDeclaration(); + TIntermAggregate *parentAgg = getParentNode()->getAsAggregate(); + ASSERT(parentAgg != nullptr); - replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped()); - replacementDeclaration->setLine(sequence->at(ii)->getLine()); - replacementDeclarations.push_back(replacementDeclaration); - } + TIntermSequence replacementDeclarations; + for (size_t ii = 0; ii < sequence->size(); ++ii) + { + TIntermAggregate *replacementDeclaration = new TIntermAggregate; - mMultiReplacements.push_back( - NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations)); + replacementDeclaration->setOp(EOpDeclaration); + replacementDeclaration->getSequence()->push_back(sequence->at(ii)); + replacementDeclaration->setLine(sequence->at(ii)->getLine()); + replacementDeclarations.push_back(replacementDeclaration); + } + + mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacementDeclarations)); + } + return false; } - return false; + return true; } } // namespace @@ -74,5 +75,3 @@ void SeparateDeclarations(TIntermNode *root) { SeparateDeclarationsTraverser::apply(root); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SeparateDeclarations.h b/gfx/angle/src/compiler/translator/SeparateDeclarations.h index 2c2611a49..77913ab8b 100755 --- a/gfx/angle/src/compiler/translator/SeparateDeclarations.h +++ b/gfx/angle/src/compiler/translator/SeparateDeclarations.h @@ -16,11 +16,8 @@ #ifndef COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ #define COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ -namespace sh -{ class TIntermNode; void SeparateDeclarations(TIntermNode *root); -} // namespace sh #endif // COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_ diff --git a/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp index 0f7c404d3..4041be971 100755 --- a/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp +++ b/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp @@ -14,9 +14,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNodePatternMatcher.h" -namespace sh -{ - namespace { @@ -52,7 +49,11 @@ SeparateExpressionsTraverser::SeparateExpressionsTraverser() // and also needs to be replaced in its original location by a different node. TIntermBinary *CopyAssignmentNode(TIntermBinary *node) { - return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight()); + TIntermBinary *copyNode = new TIntermBinary(node->getOp()); + copyNode->setLeft(node->getLeft()); + copyNode->setRight(node->getRight()); + copyNode->setType(node->getType()); + return copyNode; } // Performs a shallow copy of a constructor/function call node. @@ -62,11 +63,12 @@ TIntermAggregate *CopyAggregateNode(TIntermAggregate *node) TIntermSequence *copySeq = copyNode->getSequence(); copySeq->insert(copySeq->begin(), node->getSequence()->begin(), node->getSequence()->end()); copyNode->setType(node->getType()); - *copyNode->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo(); + copyNode->setFunctionId(node->getFunctionId()); if (node->isUserDefined()) { copyNode->setUserDefined(); } + copyNode->setNameObj(node->getNameObj()); return copyNode; } @@ -140,5 +142,3 @@ void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *tempora } while (traverser.foundArrayExpression()); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h b/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h index d0c73dc18..b178ebb3e 100755 --- a/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h +++ b/gfx/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h @@ -12,11 +12,8 @@ #ifndef COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ #define COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ -namespace sh -{ class TIntermNode; void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex); -} // namespace sh #endif // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_ diff --git a/gfx/angle/src/compiler/translator/ShaderLang.cpp b/gfx/angle/src/compiler/translator/ShaderLang.cpp index b776ca50b..429bbf2e4 100755 --- a/gfx/angle/src/compiler/translator/ShaderLang.cpp +++ b/gfx/angle/src/compiler/translator/ShaderLang.cpp @@ -20,8 +20,6 @@ #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" -using namespace sh; - namespace { @@ -36,31 +34,31 @@ template <typename VarT> const std::vector<VarT> *GetVariableList(const TCompiler *compiler); template <> -const std::vector<Uniform> *GetVariableList(const TCompiler *compiler) +const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler) { return &compiler->getUniforms(); } template <> -const std::vector<Varying> *GetVariableList(const TCompiler *compiler) +const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler) { return &compiler->getVaryings(); } template <> -const std::vector<Attribute> *GetVariableList(const TCompiler *compiler) +const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler) { return &compiler->getAttributes(); } template <> -const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler) +const std::vector<sh::OutputVariable> *GetVariableList(const TCompiler *compiler) { return &compiler->getOutputVariables(); } template <> -const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler) +const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler) { return &compiler->getInterfaceBlocks(); } @@ -237,9 +235,8 @@ ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec, } // Generate built-in symbol table. - if (!compiler->Init(*resources)) - { - sh::Destruct(base); + if (!compiler->Init(*resources)) { + ShDestruct(base); return 0; } @@ -271,10 +268,11 @@ const std::string &ShGetBuiltInResourcesString(const ShHandle handle) // Return: The return value of ShCompile is really boolean, indicating // success or failure. // -bool ShCompile(const ShHandle handle, - const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) +bool ShCompile( + const ShHandle handle, + const char *const shaderStrings[], + size_t numStrings, + int compileOptions) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); @@ -335,32 +333,32 @@ const std::map<std::string, std::string> *ShGetNameHashingMap( return &(compiler->getNameMap()); } -const std::vector<Uniform> *ShGetUniforms(const ShHandle handle) +const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle) { - return GetShaderVariables<Uniform>(handle); + return GetShaderVariables<sh::Uniform>(handle); } -const std::vector<Varying> *ShGetVaryings(const ShHandle handle) +const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle) { - return GetShaderVariables<Varying>(handle); + return GetShaderVariables<sh::Varying>(handle); } -const std::vector<Attribute> *ShGetAttributes(const ShHandle handle) +const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle) { - return GetShaderVariables<Attribute>(handle); + return GetShaderVariables<sh::Attribute>(handle); } -const std::vector<OutputVariable> *ShGetOutputVariables(const ShHandle handle) +const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle) { - return GetShaderVariables<OutputVariable>(handle); + return GetShaderVariables<sh::OutputVariable>(handle); } -const std::vector<InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle) +const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle) { - return GetShaderVariables<InterfaceBlock>(handle); + return GetShaderVariables<sh::InterfaceBlock>(handle); } -WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle) +sh::WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle) { ASSERT(handle); @@ -372,7 +370,7 @@ WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle) } bool ShCheckVariablesWithinPackingLimits(int maxVectors, - const std::vector<ShaderVariable> &variables) + const std::vector<sh::ShaderVariable> &variables) { VariablePacker packer; return packer.CheckVariablesWithinPackingLimits(maxVectors, variables); @@ -408,126 +406,7 @@ const std::map<std::string, unsigned int> *ShGetUniformRegisterMap(const ShHandl return translator->getUniformRegisterMap(); #else - return nullptr; + static std::map<std::string, unsigned int> map; + return ↦ #endif // ANGLE_ENABLE_HLSL } - -namespace sh -{ -bool Initialize() -{ - return ShInitialize(); -} - -bool Finalize() -{ - return ShFinalize(); -} - -void InitBuiltInResources(ShBuiltInResources *resources) -{ - ShInitBuiltInResources(resources); -} - -const std::string &GetBuiltInResourcesString(const ShHandle handle) -{ - return ShGetBuiltInResourcesString(handle); -} - -ShHandle ConstructCompiler(sh::GLenum type, - ShShaderSpec spec, - ShShaderOutput output, - const ShBuiltInResources *resources) -{ - return ShConstructCompiler(type, spec, output, resources); -} - -void Destruct(ShHandle handle) -{ - return ShDestruct(handle); -} - -bool Compile(const ShHandle handle, - const char *const shaderStrings[], - size_t numStrings, - ShCompileOptions compileOptions) -{ - return ShCompile(handle, shaderStrings, numStrings, compileOptions); -} - -void ClearResults(const ShHandle handle) -{ - return ShClearResults(handle); -} - -int GetShaderVersion(const ShHandle handle) -{ - return ShGetShaderVersion(handle); -} - -ShShaderOutput GetShaderOutputType(const ShHandle handle) -{ - return ShGetShaderOutputType(handle); -} - -const std::string &GetInfoLog(const ShHandle handle) -{ - return ShGetInfoLog(handle); -} - -const std::string &GetObjectCode(const ShHandle handle) -{ - return ShGetObjectCode(handle); -} - -const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle) -{ - return ShGetNameHashingMap(handle); -} - -const std::vector<sh::Uniform> *GetUniforms(const ShHandle handle) -{ - return ShGetUniforms(handle); -} -const std::vector<sh::Varying> *GetVaryings(const ShHandle handle) -{ - return ShGetVaryings(handle); -} -const std::vector<sh::Attribute> *GetAttributes(const ShHandle handle) -{ - return ShGetAttributes(handle); -} - -const std::vector<sh::OutputVariable> *GetOutputVariables(const ShHandle handle) -{ - return ShGetOutputVariables(handle); -} -const std::vector<sh::InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle) -{ - return ShGetInterfaceBlocks(handle); -} - -sh::WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) -{ - return ShGetComputeShaderLocalGroupSize(handle); -} - -bool CheckVariablesWithinPackingLimits(int maxVectors, - const std::vector<sh::ShaderVariable> &variables) -{ - return ShCheckVariablesWithinPackingLimits(maxVectors, variables); -} - -bool GetInterfaceBlockRegister(const ShHandle handle, - const std::string &interfaceBlockName, - unsigned int *indexOut) -{ - return ShGetInterfaceBlockRegister(handle, interfaceBlockName, indexOut); -} - -const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle) -{ - return ShGetUniformRegisterMap(handle); -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SimplifyLoopConditions.cpp b/gfx/angle/src/compiler/translator/SimplifyLoopConditions.cpp index 85c166e59..61a68fc93 100755 --- a/gfx/angle/src/compiler/translator/SimplifyLoopConditions.cpp +++ b/gfx/angle/src/compiler/translator/SimplifyLoopConditions.cpp @@ -13,9 +13,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNodePatternMatcher.h" -namespace sh -{ - namespace { @@ -39,7 +36,7 @@ class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; void nextIteration(); bool foundLoopToChange() const { return mFoundLoopToChange; } @@ -97,20 +94,20 @@ bool SimplifyLoopConditionsTraverser::visitAggregate(Visit visit, TIntermAggrega // If we're outside a loop condition, we only need to traverse nodes that may contain loops. if (!mInsideLoopConditionOrExpression) - return false; + return (node->getOp() == EOpSequence || node->getOp() == EOpFunction); mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode()); return !mFoundLoopToChange; } -bool SimplifyLoopConditionsTraverser::visitTernary(Visit visit, TIntermTernary *node) +bool SimplifyLoopConditionsTraverser::visitSelection(Visit visit, TIntermSelection *node) { if (mFoundLoopToChange) return false; // Don't traverse ternary operators outside loop conditions. if (!mInsideLoopConditionOrExpression) - return false; + return !node->usesTernaryOperator(); mFoundLoopToChange = mConditionsToSimplify.match(node); return !mFoundLoopToChange; @@ -148,9 +145,10 @@ void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) tempInitSeq.push_back(createTempInitDeclaration(node->getCondition()->deepCopy())); insertStatementsInParentBlock(tempInitSeq); - TIntermBlock *newBody = new TIntermBlock(); + TIntermAggregate *newBody = new TIntermAggregate(EOpSequence); if (node->getBody()) { + ASSERT(node->getBody()->getOp() == EOpSequence); newBody->getSequence()->push_back(node->getBody()); } newBody->getSequence()->push_back( @@ -178,9 +176,10 @@ void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) tempInitSeq.push_back(createTempInitDeclaration(CreateBoolConstantNode(true))); insertStatementsInParentBlock(tempInitSeq); - TIntermBlock *newBody = new TIntermBlock(); + TIntermAggregate *newBody = new TIntermAggregate(EOpSequence); if (node->getBody()) { + ASSERT(node->getBody()->getOp() == EOpSequence); newBody->getSequence()->push_back(node->getBody()); } newBody->getSequence()->push_back( @@ -203,7 +202,7 @@ void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) // bool s0 = expr; // while (s0) { { body; } exprB; s0 = expr; } // } - TIntermBlock *loopScope = new TIntermBlock(); + TIntermAggregate *loopScope = new TIntermAggregate(EOpSequence); if (node->getInit()) { loopScope->getSequence()->push_back(node->getInit()); @@ -211,15 +210,12 @@ void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) loopScope->getSequence()->push_back( createTempInitDeclaration(node->getCondition()->deepCopy())); - TIntermBlock *whileLoopBody = new TIntermBlock(); + TIntermAggregate *whileLoopBody = new TIntermAggregate(EOpSequence); if (node->getBody()) { whileLoopBody->getSequence()->push_back(node->getBody()); } - if (node->getExpression()) - { - whileLoopBody->getSequence()->push_back(node->getExpression()); - } + whileLoopBody->getSequence()->push_back(node->getExpression()); whileLoopBody->getSequence()->push_back( createTempAssignment(node->getCondition()->deepCopy())); TIntermLoop *whileLoop = new TIntermLoop( @@ -246,8 +242,8 @@ void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node) // for (init; expr; ) { { body; } exprB; } TIntermTyped *loopExpression = node->getExpression(); node->setExpression(nullptr); - TIntermBlock *oldBody = node->getBody(); - node->setBody(new TIntermBlock()); + TIntermAggregate *oldBody = node->getBody(); + node->setBody(new TIntermAggregate(EOpSequence)); if (oldBody != nullptr) { node->getBody()->getSequence()->push_back(oldBody); @@ -284,5 +280,3 @@ void SimplifyLoopConditions(TIntermNode *root, traverser.updateTree(); } while (traverser.foundLoopToChange()); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SimplifyLoopConditions.h b/gfx/angle/src/compiler/translator/SimplifyLoopConditions.h index 968089d54..b8802aa11 100755 --- a/gfx/angle/src/compiler/translator/SimplifyLoopConditions.h +++ b/gfx/angle/src/compiler/translator/SimplifyLoopConditions.h @@ -11,8 +11,6 @@ #ifndef COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ #define COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ -namespace sh -{ class TIntermNode; class TSymbolTable; @@ -21,6 +19,5 @@ void SimplifyLoopConditions(TIntermNode *root, unsigned int *temporaryIndex, const TSymbolTable &symbolTable, int shaderVersion); -} // namespace sh #endif // COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_ diff --git a/gfx/angle/src/compiler/translator/SplitSequenceOperator.cpp b/gfx/angle/src/compiler/translator/SplitSequenceOperator.cpp index 4c63b59f7..45fc8dc9b 100755 --- a/gfx/angle/src/compiler/translator/SplitSequenceOperator.cpp +++ b/gfx/angle/src/compiler/translator/SplitSequenceOperator.cpp @@ -14,9 +14,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNodePatternMatcher.h" -namespace sh -{ - namespace { @@ -29,7 +26,7 @@ class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; void nextIteration(); bool foundExpressionToSplit() const { return mFoundExpressionToSplit; } @@ -60,7 +57,7 @@ void SplitSequenceOperatorTraverser::nextIteration() nextTemporaryIndex(); } -bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node) { if (mFoundExpressionToSplit) return false; @@ -68,14 +65,15 @@ bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregat if (mInsideSequenceOperator > 0 && visit == PreVisit) { // Detect expressions that need to be simplified - mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode()); + mFoundExpressionToSplit = + mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere()); return !mFoundExpressionToSplit; } return true; } -bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node) +bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { if (node->getOp() == EOpComma) { @@ -93,12 +91,19 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod // execution order. if (mFoundExpressionToSplit && mInsideSequenceOperator == 1) { - // Move the left side operand into a separate statement in the parent block. + // Move all operands of the sequence operation except the last one into separate + // statements in the parent block. TIntermSequence insertions; - insertions.push_back(node->getLeft()); + for (auto *sequenceChild : *node->getSequence()) + { + if (sequenceChild != node->getSequence()->back()) + { + insertions.push_back(sequenceChild); + } + } insertStatementsInParentBlock(insertions); - // Replace the comma node with its right side operand. - queueReplacement(node, node->getRight(), OriginalNode::IS_DROPPED); + // Replace the sequence with its last operand + queueReplacement(node, node->getSequence()->back(), OriginalNode::IS_DROPPED); } mInsideSequenceOperator--; } @@ -111,15 +116,14 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod if (mInsideSequenceOperator > 0 && visit == PreVisit) { // Detect expressions that need to be simplified - mFoundExpressionToSplit = - mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere()); + mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode()); return !mFoundExpressionToSplit; } return true; } -bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node) +bool SplitSequenceOperatorTraverser::visitSelection(Visit visit, TIntermSelection *node) { if (mFoundExpressionToSplit) return false; @@ -154,5 +158,3 @@ void SplitSequenceOperator(TIntermNode *root, traverser.updateTree(); } while (traverser.foundExpressionToSplit()); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SplitSequenceOperator.h b/gfx/angle/src/compiler/translator/SplitSequenceOperator.h index 6df9d458e..4a46fe36c 100755 --- a/gfx/angle/src/compiler/translator/SplitSequenceOperator.h +++ b/gfx/angle/src/compiler/translator/SplitSequenceOperator.h @@ -12,9 +12,6 @@ #ifndef COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ #define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ -namespace sh -{ - class TIntermNode; class TSymbolTable; @@ -24,6 +21,4 @@ void SplitSequenceOperator(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion); -} // namespace sh - #endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_ diff --git a/gfx/angle/src/compiler/translator/SymbolTable.cpp b/gfx/angle/src/compiler/translator/SymbolTable.cpp index 188f810e3..059c5c76a 100755 --- a/gfx/angle/src/compiler/translator/SymbolTable.cpp +++ b/gfx/angle/src/compiler/translator/SymbolTable.cpp @@ -19,38 +19,15 @@ #include <stdio.h> #include <algorithm> -namespace sh -{ - int TSymbolTable::uniqueIdCounter = 0; -TSymbol::TSymbol(const TString *n) : uniqueId(TSymbolTable::nextUniqueId()), name(n) -{ -} - // // Functions have buried pointers to delete. // TFunction::~TFunction() { - clearParameters(); -} - -void TFunction::clearParameters() -{ for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) delete (*i).type; - parameters.clear(); - mangledName = nullptr; -} - -void TFunction::swapParameters(const TFunction ¶metersSource) -{ - clearParameters(); - for (auto parameter : parametersSource.parameters) - { - addParameter(parameter); - } } const TString *TFunction::buildMangledName() const @@ -76,6 +53,8 @@ TSymbolTableLevel::~TSymbolTableLevel() bool TSymbolTableLevel::insert(TSymbol *symbol) { + symbol->setUniqueId(TSymbolTable::nextUniqueId()); + // returning true means symbol was added to the table tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); @@ -84,6 +63,8 @@ bool TSymbolTableLevel::insert(TSymbol *symbol) bool TSymbolTableLevel::insertUnmangled(TFunction *function) { + function->setUniqueId(TSymbolTable::nextUniqueId()); + // returning true means symbol was added to the table tInsertResult result = level.insert(tLevelPair(function->getName(), function)); @@ -126,12 +107,6 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, return symbol; } -TSymbol *TSymbolTable::findGlobal(const TString &name) const -{ - ASSERT(table.size() > GLOBAL_LEVEL); - return table[GLOBAL_LEVEL]->find(name); -} - TSymbol *TSymbolTable::findBuiltIn( const TString &name, int shaderVersion) const { @@ -258,43 +233,6 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); } - else if (IsGImage(ptype1->getBasicType())) - { - insertUnmangledBuiltIn(name); - - const TType *floatType = TCache::getType(EbtFloat, 4); - const TType *intType = TCache::getType(EbtInt, 4); - const TType *unsignedType = TCache::getType(EbtUInt, 4); - - const TType *floatImage = - TCache::getType(convertGImageToFloatImage(ptype1->getBasicType())); - const TType *intImage = TCache::getType(convertGImageToIntImage(ptype1->getBasicType())); - const TType *unsignedImage = - TCache::getType(convertGImageToUnsignedImage(ptype1->getBasicType())); - - // GLSL ES 3.10, Revision 4, 8.12 Image Functions - if (rvalue->getBasicType() == EbtGVec4) - { - // imageLoad - insertBuiltIn(level, floatType, name, floatImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, intType, name, intImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, unsignedType, name, unsignedImage, ptype2, ptype3, ptype4, ptype5); - } - else if (rvalue->getBasicType() == EbtVoid) - { - // imageStore - insertBuiltIn(level, rvalue, name, floatImage, ptype2, floatType, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, intImage, ptype2, intType, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, unsignedType, ptype4, ptype5); - } - else - { - // imageSize - insertBuiltIn(level, rvalue, name, floatImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, intImage, ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5); - } - } else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3)) { ASSERT(!ptype4 && !ptype5); @@ -367,5 +305,3 @@ TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const } return prec; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/SymbolTable.h b/gfx/angle/src/compiler/translator/SymbolTable.h index 7c4d3aab3..60e0b9929 100755 --- a/gfx/angle/src/compiler/translator/SymbolTable.h +++ b/gfx/angle/src/compiler/translator/SymbolTable.h @@ -38,16 +38,16 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" -namespace sh -{ - // Symbol base class. (Can build functions or variables out of these...) class TSymbol : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); - TSymbol(const TString *n); - + TSymbol(const TString *n) + : uniqueId(0), + name(n) + { + } virtual ~TSymbol() { // don't delete name, it's from the pool @@ -69,6 +69,10 @@ class TSymbol : angle::NonCopyable { return false; } + void setUniqueId(int id) + { + uniqueId = id; + } int getUniqueId() const { return uniqueId; @@ -83,7 +87,7 @@ class TSymbol : angle::NonCopyable } private: - const int uniqueId; + int uniqueId; // For real comparing during code generation const TString *name; TString extension; }; @@ -225,8 +229,6 @@ class TFunction : public TSymbol mangledName = nullptr; } - void swapParameters(const TFunction ¶metersSource); - const TString &getMangledName() const override { if (mangledName == nullptr) @@ -260,8 +262,6 @@ class TFunction : public TSymbol } private: - void clearParameters(); - const TString *buildMangledName() const; typedef TVector<TConstParameter> TParamList; @@ -459,11 +459,8 @@ class TSymbolTable : angle::NonCopyable TSymbol *find(const TString &name, int shaderVersion, bool *builtIn = NULL, bool *sameScope = NULL) const; - - TSymbol *findGlobal(const TString &name) const; - TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; - + TSymbolTableLevel *getOuterLevel() { assert(currentLevel() >= 1); @@ -474,15 +471,15 @@ class TSymbolTable : angle::NonCopyable bool setDefaultPrecision(const TPublicType &type, TPrecision prec) { - if (!SupportsPrecision(type.getBasicType())) + if (!SupportsPrecision(type.type)) return false; - if (type.getBasicType() == EbtUInt) + if (type.type == EbtUInt) return false; // ESSL 3.00.4 section 4.5.4 if (type.isAggregate()) return false; // Not allowed to set for aggregate types int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; // Uses map operator [], overwrites the current value - (*precisionStack[indexOfLastElement])[type.getBasicType()] = prec; + (*precisionStack[indexOfLastElement])[type.type] = prec; return true; } @@ -544,6 +541,4 @@ class TSymbolTable : angle::NonCopyable static int uniqueIdCounter; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ diff --git a/gfx/angle/src/compiler/translator/TextureFunctionHLSL.cpp b/gfx/angle/src/compiler/translator/TextureFunctionHLSL.cpp index 33d098531..6580f258d 100755 --- a/gfx/angle/src/compiler/translator/TextureFunctionHLSL.cpp +++ b/gfx/angle/src/compiler/translator/TextureFunctionHLSL.cpp @@ -393,22 +393,41 @@ void OutputTextureFunctionArgumentList(TInfoSinkBase &out, { switch (textureFunction.sampler) { + case EbtSampler2D: + out << ", int2 offset"; + break; case EbtSampler3D: - case EbtISampler3D: - case EbtUSampler3D: out << ", int3 offset"; break; - case EbtSampler2D: case EbtSampler2DArray: + out << ", int2 offset"; + break; case EbtISampler2D: + out << ", int2 offset"; + break; + case EbtISampler3D: + out << ", int3 offset"; + break; case EbtISampler2DArray: + out << ", int2 offset"; + break; case EbtUSampler2D: + out << ", int2 offset"; + break; + case EbtUSampler3D: + out << ", int3 offset"; + break; case EbtUSampler2DArray: + out << ", int2 offset"; + break; case EbtSampler2DShadow: + out << ", int2 offset"; + break; case EbtSampler2DArrayShadow: - case EbtSamplerExternalOES: out << ", int2 offset"; break; + case EbtSamplerExternalOES: + out << ", int2 offset"; default: UNREACHABLE(); } @@ -1094,8 +1113,32 @@ const char *TextureFunctionHLSL::TextureFunction::getReturnType() const bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const { - return std::tie(sampler, coords, proj, offset, method) < - std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method); + if (sampler < rhs.sampler) + return true; + if (sampler > rhs.sampler) + return false; + + if (coords < rhs.coords) + return true; + if (coords > rhs.coords) + return false; + + if (!proj && rhs.proj) + return true; + if (proj && !rhs.proj) + return false; + + if (!offset && rhs.offset) + return true; + if (offset && !rhs.offset) + return false; + + if (method < rhs.method) + return true; + if (method > rhs.method) + return false; + + return false; } TString TextureFunctionHLSL::useTextureFunction(const TString &name, diff --git a/gfx/angle/src/compiler/translator/TranslatorESSL.cpp b/gfx/angle/src/compiler/translator/TranslatorESSL.cpp index 43bce74cc..fef176857 100755 --- a/gfx/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/gfx/angle/src/compiler/translator/TranslatorESSL.cpp @@ -6,20 +6,26 @@ #include "compiler/translator/TranslatorESSL.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" #include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/RecordConstantPrecision.h" #include "compiler/translator/OutputESSL.h" #include "angle_gl.h" -namespace sh -{ - TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) : TCompiler(type, spec, SH_ESSL_OUTPUT) { } -void TranslatorESSL::translate(TIntermNode *root, ShCompileOptions compileOptions) +void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) +{ + if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS) + { + InitBuiltInFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); + } +} + +void TranslatorESSL::translate(TIntermNode *root, int compileOptions) { TInfoSinkBase& sink = getInfoSink().obj; @@ -81,8 +87,7 @@ void TranslatorESSL::translate(TIntermNode *root, ShCompileOptions compileOption // Write translated shader. TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), - getSymbolTable(), getShaderType(), shaderVer, precisionEmulation, - compileOptions); + getSymbolTable(), shaderVer, precisionEmulation); root->traverse(&outputESSL); } @@ -111,5 +116,3 @@ void TranslatorESSL::writeExtensionBehavior() { } } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/TranslatorESSL.h b/gfx/angle/src/compiler/translator/TranslatorESSL.h index b7b46a65e..0fbc47de5 100755 --- a/gfx/angle/src/compiler/translator/TranslatorESSL.h +++ b/gfx/angle/src/compiler/translator/TranslatorESSL.h @@ -9,22 +9,19 @@ #include "compiler/translator/Compiler.h" -namespace sh -{ - class TranslatorESSL : public TCompiler { public: TranslatorESSL(sh::GLenum type, ShShaderSpec spec); protected: - void translate(TIntermNode *root, ShCompileOptions compileOptions) override; + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override; + + void translate(TIntermNode *root, int compileOptions) override; bool shouldFlattenPragmaStdglInvariantAll() override; private: void writeExtensionBehavior(); }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_ diff --git a/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp b/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp index 1d6582b02..0ee96f590 100755 --- a/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/gfx/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -11,36 +11,26 @@ #include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/ExtensionGLSL.h" #include "compiler/translator/OutputGLSL.h" -#include "compiler/translator/RewriteTexelFetchOffset.h" #include "compiler/translator/VersionGLSL.h" -namespace sh -{ - TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : TCompiler(type, spec, output) { } -void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) +void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) { - if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION) - { - InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); - } - - if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) + if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS) { - InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion()); + InitBuiltInFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); } int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType()); InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion); } -void TranslatorGLSL::translate(TIntermNode *root, ShCompileOptions compileOptions) +void TranslatorGLSL::translate(TIntermNode *root, int compileOptions) { TInfoSinkBase& sink = getInfoSink().obj; @@ -60,7 +50,7 @@ void TranslatorGLSL::translate(TIntermNode *root, ShCompileOptions compileOption // variables that are actually used, to avoid affecting the behavior of the shader. if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) && getPragma().stdgl.invariantAll) { - ASSERT(wereVariablesCollected()); + collectVariables(root); switch (getShaderType()) { @@ -85,11 +75,6 @@ void TranslatorGLSL::translate(TIntermNode *root, ShCompileOptions compileOption } } - if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) - { - sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); - } - bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; if (precisionEmulation) @@ -188,9 +173,13 @@ void TranslatorGLSL::translate(TIntermNode *root, ShCompileOptions compileOption } // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), - getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(), - compileOptions); + TOutputGLSL outputGLSL(sink, + getArrayIndexClampingStrategy(), + getHashFunction(), + getNameMap(), + getSymbolTable(), + getShaderVersion(), + getOutputType()); root->traverse(&outputGLSL); } @@ -201,12 +190,6 @@ bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll() return IsGLSL130OrNewer(getOutputType()); } -bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions) -{ - return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) || - TCompiler::shouldCollectVariables(compileOptions); -} - void TranslatorGLSL::writeVersion(TIntermNode *root) { TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); @@ -294,5 +277,3 @@ void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtin sink << "invariant " << builtinVaryingName << ";\n"; } } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/TranslatorGLSL.h b/gfx/angle/src/compiler/translator/TranslatorGLSL.h index d6f694824..91df58868 100755 --- a/gfx/angle/src/compiler/translator/TranslatorGLSL.h +++ b/gfx/angle/src/compiler/translator/TranslatorGLSL.h @@ -9,21 +9,16 @@ #include "compiler/translator/Compiler.h" -namespace sh -{ - class TranslatorGLSL : public TCompiler { public: TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); protected: - void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, - ShCompileOptions compileOptions) override; + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override; - void translate(TIntermNode *root, ShCompileOptions compileOptions) override; + void translate(TIntermNode *root, int compileOptions) override; bool shouldFlattenPragmaStdglInvariantAll() override; - bool shouldCollectVariables(ShCompileOptions compileOptions) override; private: void writeVersion(TIntermNode *root); @@ -31,6 +26,4 @@ class TranslatorGLSL : public TCompiler void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName); }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ diff --git a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp index 7ef1d4e36..6721d8942 100755 --- a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -8,7 +8,6 @@ #include "compiler/translator/AddDefaultReturnStatements.h" #include "compiler/translator/ArrayReturnValueToOutParameter.h" -#include "compiler/translator/BreakVariableAliasingInInnerLoops.h" #include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/ExpandIntegerPowExpressions.h" #include "compiler/translator/IntermNodePatternMatcher.h" @@ -16,7 +15,6 @@ #include "compiler/translator/RemoveDynamicIndexing.h" #include "compiler/translator/RewriteElseBlocks.h" #include "compiler/translator/RewriteTexelFetchOffset.h" -#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" #include "compiler/translator/SeparateArrayInitialization.h" #include "compiler/translator/SeparateDeclarations.h" #include "compiler/translator/SeparateExpressionsReturningArrays.h" @@ -24,15 +22,12 @@ #include "compiler/translator/SplitSequenceOperator.h" #include "compiler/translator/UnfoldShortCircuitToIf.h" -namespace sh -{ - TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : TCompiler(type, spec, output) { } -void TranslatorHLSL::translate(TIntermNode *root, ShCompileOptions compileOptions) +void TranslatorHLSL::translate(TIntermNode *root, int compileOptions) { const ShBuiltInResources &resources = getResources(); int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; @@ -80,12 +75,6 @@ void TranslatorHLSL::translate(TIntermNode *root, ShCompileOptions compileOption sh::RewriteElseBlocks(root, getTemporaryIndex()); } - // Work around an HLSL compiler frontend aliasing optimization bug. - // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed - // in the next release of d3dcompiler.dll, it would be nice to detect the DLL - // version and only apply the workaround if it is too old. - sh::BreakVariableAliasingInInnerLoops(root); - bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; @@ -105,13 +94,8 @@ void TranslatorHLSL::translate(TIntermNode *root, ShCompileOptions compileOption if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0) { - sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion()); - } - - if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) && - getShaderType() == GL_VERTEX_SHADER) - { - sh::RewriteUnaryMinusOperatorInt(root); + sh::RewriteTexelFetchOffset(root, getTemporaryIndex(), getSymbolTable(), + getShaderVersion()); } sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(), @@ -144,5 +128,3 @@ const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap { return &mUniformRegisterMap; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/TranslatorHLSL.h b/gfx/angle/src/compiler/translator/TranslatorHLSL.h index 3bf64b2e6..f96c18dff 100755 --- a/gfx/angle/src/compiler/translator/TranslatorHLSL.h +++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.h @@ -9,9 +9,6 @@ #include "compiler/translator/Compiler.h" -namespace sh -{ - class TranslatorHLSL : public TCompiler { public: @@ -24,16 +21,14 @@ class TranslatorHLSL : public TCompiler const std::map<std::string, unsigned int> *getUniformRegisterMap() const; protected: - void translate(TIntermNode *root, ShCompileOptions compileOptions) override; + void translate(TIntermNode *root, int compileOptions) override; bool shouldFlattenPragmaStdglInvariantAll() override; // collectVariables needs to be run always so registers can be assigned. - bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; } + bool shouldCollectVariables(int compileOptions) override { return true; } std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/Types.cpp b/gfx/angle/src/compiler/translator/Types.cpp index af79d3eea..be1f9822c 100755 --- a/gfx/angle/src/compiler/translator/Types.cpp +++ b/gfx/angle/src/compiler/translator/Types.cpp @@ -11,86 +11,49 @@ #include "compiler/translator/Types.h" #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" #include <algorithm> #include <climits> -namespace sh -{ - const char* getBasicString(TBasicType t) { switch (t) { - case EbtVoid: return "void"; - case EbtFloat: return "float"; - case EbtInt: return "int"; - case EbtUInt: return "uint"; - case EbtBool: return "bool"; - case EbtSampler2D: return "sampler2D"; - case EbtSampler3D: return "sampler3D"; - case EbtSamplerCube: return "samplerCube"; - case EbtSamplerExternalOES: return "samplerExternalOES"; - case EbtSampler2DRect: return "sampler2DRect"; - case EbtSampler2DArray: return "sampler2DArray"; - case EbtISampler2D: return "isampler2D"; - case EbtISampler3D: return "isampler3D"; - case EbtISamplerCube: return "isamplerCube"; - case EbtISampler2DArray: return "isampler2DArray"; - case EbtUSampler2D: return "usampler2D"; - case EbtUSampler3D: return "usampler3D"; - case EbtUSamplerCube: return "usamplerCube"; - case EbtUSampler2DArray: return "usampler2DArray"; - case EbtSampler2DShadow: return "sampler2DShadow"; - case EbtSamplerCubeShadow: return "samplerCubeShadow"; - case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; - case EbtStruct: return "structure"; - case EbtInterfaceBlock: return "interface block"; - case EbtImage2D: - return "image2D"; - case EbtIImage2D: - return "iimage2D"; - case EbtUImage2D: - return "uimage2D"; - case EbtImage3D: - return "image3D"; - case EbtIImage3D: - return "iimage3D"; - case EbtUImage3D: - return "uimage3D"; - case EbtImage2DArray: - return "image2DArray"; - case EbtIImage2DArray: - return "iimage2DArray"; - case EbtUImage2DArray: - return "uimage2DArray"; - case EbtImageCube: - return "imageCube"; - case EbtIImageCube: - return "iimageCube"; - case EbtUImageCube: - return "uimageCube"; - default: UNREACHABLE(); return "unknown type"; + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtUInt: return "uint"; break; + case EbtBool: return "bool"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSampler3D: return "sampler3D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSamplerExternalOES: return "samplerExternalOES"; break; + case EbtSampler2DRect: return "sampler2DRect"; break; + case EbtSampler2DArray: return "sampler2DArray"; break; + case EbtISampler2D: return "isampler2D"; break; + case EbtISampler3D: return "isampler3D"; break; + case EbtISamplerCube: return "isamplerCube"; break; + case EbtISampler2DArray: return "isampler2DArray"; break; + case EbtUSampler2D: return "usampler2D"; break; + case EbtUSampler3D: return "usampler3D"; break; + case EbtUSamplerCube: return "usamplerCube"; break; + case EbtUSampler2DArray: return "usampler2DArray"; break; + case EbtSampler2DShadow: return "sampler2DShadow"; break; + case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; + case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; + case EbtStruct: return "structure"; break; + case EbtInterfaceBlock: return "interface block"; break; + default: UNREACHABLE(); return "unknown type"; } } TType::TType(const TPublicType &p) - : type(p.getBasicType()), - precision(p.precision), - qualifier(p.qualifier), - invariant(p.invariant), - memoryQualifier(p.memoryQualifier), - layoutQualifier(p.layoutQualifier), - primarySize(p.getPrimarySize()), - secondarySize(p.getSecondarySize()), - array(p.array), - arraySize(p.arraySize), - interfaceBlock(0), - structure(0) + : type(p.type), precision(p.precision), qualifier(p.qualifier), invariant(p.invariant), + layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), + array(p.array), arraySize(p.arraySize), interfaceBlock(0), structure(0) { - if (p.getUserDef()) - structure = p.getUserDef()->getStruct(); + if (p.userDef) + structure = p.userDef->getStruct(); } bool TStructure::equals(const TStructure &other) const @@ -311,42 +274,6 @@ TString TType::buildMangledName() const case EbtSampler2DArrayShadow: mangledName += "s2as"; break; - case EbtImage2D: - mangledName += "im2"; - break; - case EbtIImage2D: - mangledName += "iim2"; - break; - case EbtUImage2D: - mangledName += "uim2"; - break; - case EbtImage3D: - mangledName += "im3"; - break; - case EbtIImage3D: - mangledName += "iim3"; - break; - case EbtUImage3D: - mangledName += "uim3"; - break; - case EbtImage2DArray: - mangledName += "im2a"; - break; - case EbtIImage2DArray: - mangledName += "iim2a"; - break; - case EbtUImage2DArray: - mangledName += "uim2a"; - break; - case EbtImageCube: - mangledName += "imc"; - break; - case EbtIImageCube: - mangledName += "iimc"; - break; - case EbtUImageCube: - mangledName += "uimc"; - break; case EbtStruct: mangledName += structure->mangledName(); break; @@ -391,9 +318,6 @@ size_t TType::getObjectSize() const if (isArray()) { - if (totalSize == 0) - return 0; - size_t currentArraySize = getArraySize(); if (currentArraySize > INT_MAX / totalSize) totalSize = INT_MAX; @@ -404,14 +328,6 @@ size_t TType::getObjectSize() const return totalSize; } -TStructure::TStructure(const TString *name, TFieldList *fields) - : TFieldListCollection(name, fields), - mDeepestNesting(0), - mUniqueId(TSymbolTable::nextUniqueId()), - mAtGlobalScope(false) -{ -} - bool TStructure::containsArrays() const { for (size_t i = 0; i < mFields->size(); ++i) @@ -445,17 +361,6 @@ bool TStructure::containsSamplers() const return false; } -bool TStructure::containsImages() const -{ - for (size_t i = 0; i < mFields->size(); ++i) - { - const TType *fieldType = (*mFields)[i]->type(); - if (IsImage(fieldType->getBasicType()) || fieldType->isStructureContainingImages()) - return true; - } - return false; -} - void TStructure::createSamplerSymbols(const TString &structName, const TString &structAPIName, const unsigned int arrayOfStructsSize, @@ -560,5 +465,3 @@ int TStructure::calculateDeepestNesting() const maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); return 1 + maxNesting; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/Types.h b/gfx/angle/src/compiler/translator/Types.h index fc26d5f59..2a85e010c 100755 --- a/gfx/angle/src/compiler/translator/Types.h +++ b/gfx/angle/src/compiler/translator/Types.h @@ -13,9 +13,6 @@ #include "compiler/translator/BaseTypes.h" #include "compiler/translator/Common.h" -namespace sh -{ - struct TPublicType; class TType; class TSymbol; @@ -106,7 +103,13 @@ class TStructure : public TFieldListCollection { public: POOL_ALLOCATOR_NEW_DELETE(); - TStructure(const TString *name, TFieldList *fields); + TStructure(const TString *name, TFieldList *fields) + : TFieldListCollection(name, fields), + mDeepestNesting(0), + mUniqueId(0), + mAtGlobalScope(false) + { + } int deepestNesting() const { @@ -117,7 +120,6 @@ class TStructure : public TFieldListCollection bool containsArrays() const; bool containsType(TBasicType t) const; bool containsSamplers() const; - bool containsImages() const; void createSamplerSymbols(const TString &structName, const TString &structAPIName, @@ -233,18 +235,10 @@ class TType public: POOL_ALLOCATOR_NEW_DELETE(); TType() - : type(EbtVoid), - precision(EbpUndefined), - qualifier(EvqGlobal), - invariant(false), - memoryQualifier(TMemoryQualifier::create()), + : type(EbtVoid), precision(EbpUndefined), qualifier(EvqGlobal), invariant(false), layoutQualifier(TLayoutQualifier::create()), - primarySize(0), - secondarySize(0), - array(false), - arraySize(0), - interfaceBlock(nullptr), - structure(nullptr) + primarySize(0), secondarySize(0), array(false), arraySize(0), + interfaceBlock(nullptr), structure(nullptr) { } explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1) @@ -252,7 +246,6 @@ class TType precision(EbpUndefined), qualifier(EvqGlobal), invariant(false), - memoryQualifier(TMemoryQualifier::create()), layoutQualifier(TLayoutQualifier::create()), primarySize(ps), secondarySize(ss), @@ -262,24 +255,12 @@ class TType structure(0) { } - TType(TBasicType t, - TPrecision p, - TQualifier q = EvqTemporary, - unsigned char ps = 1, - unsigned char ss = 1, - bool a = false) - : type(t), - precision(p), - qualifier(q), - invariant(false), - memoryQualifier(TMemoryQualifier::create()), + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, + unsigned char ps = 1, unsigned char ss = 1, bool a = false) + : type(t), precision(p), qualifier(q), invariant(false), layoutQualifier(TLayoutQualifier::create()), - primarySize(ps), - secondarySize(ss), - array(a), - arraySize(0), - interfaceBlock(0), - structure(0) + primarySize(ps), secondarySize(ss), array(a), arraySize(0), + interfaceBlock(0), structure(0) { } explicit TType(const TPublicType &p); @@ -288,7 +269,6 @@ class TType precision(p), qualifier(EvqTemporary), invariant(false), - memoryQualifier(TMemoryQualifier::create()), layoutQualifier(TLayoutQualifier::create()), primarySize(1), secondarySize(1), @@ -298,22 +278,12 @@ class TType structure(userDef) { } - TType(TInterfaceBlock *interfaceBlockIn, - TQualifier qualifierIn, - TLayoutQualifier layoutQualifierIn, - int arraySizeIn) - : type(EbtInterfaceBlock), - precision(EbpUndefined), - qualifier(qualifierIn), - invariant(false), - memoryQualifier(TMemoryQualifier::create()), - layoutQualifier(layoutQualifierIn), - primarySize(1), - secondarySize(1), - array(arraySizeIn > 0), - arraySize(arraySizeIn), - interfaceBlock(interfaceBlockIn), - structure(0) + TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn, + TLayoutQualifier layoutQualifierIn, int arraySizeIn) + : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), + invariant(false), layoutQualifier(layoutQualifierIn), + primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn), + interfaceBlock(interfaceBlockIn), structure(0) { } @@ -358,9 +328,6 @@ class TType void setInvariant(bool i) { invariant = i; } - TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } - void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } - TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; @@ -538,16 +505,16 @@ class TType const char *getBasicString() const { - return sh::getBasicString(type); + return ::getBasicString(type); } const char *getPrecisionString() const { - return sh::getPrecisionString(precision); + return ::getPrecisionString(precision); } const char *getQualifierString() const { - return sh::getQualifierString(qualifier); + return ::getQualifierString(qualifier); } const char *getBuiltInTypeNameString() const; @@ -586,11 +553,6 @@ class TType return structure ? structure->containsSamplers() : false; } - bool isStructureContainingImages() const - { - return structure ? structure->containsImages() : false; - } - void createSamplerSymbols(const TString &structName, const TString &structAPIName, const unsigned int arrayOfStructsSize, @@ -617,7 +579,6 @@ class TType TPrecision precision; TQualifier qualifier; bool invariant; - TMemoryQualifier memoryQualifier; TLayoutQualifier layoutQualifier; unsigned char primarySize; // size of vector or cols matrix unsigned char secondarySize; // rows of a matrix @@ -633,25 +594,44 @@ class TType mutable TString mangled; }; -// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the -// grammar -struct TTypeSpecifierNonArray +// +// This is a workaround for a problem with the yacc stack, It can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. Pointers +// could be used, but also trying to avoid lots of memory management overhead. +// +// Not as bad as it looks, there is no actual assumption that the fields +// match up or are name the same or anything like that. +// +struct TPublicType { TBasicType type; + TLayoutQualifier layoutQualifier; + TQualifier qualifier; + bool invariant; + TPrecision precision; unsigned char primarySize; // size of vector or cols of matrix unsigned char secondarySize; // rows of matrix + bool array; + int arraySize; TType *userDef; TSourceLoc line; // true if the type was defined by a struct specifier rather than a reference to a type name. bool isStructSpecifier; - void initialize(TBasicType bt, const TSourceLoc &ln) + void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln) { type = bt; + layoutQualifier = TLayoutQualifier::create(); + qualifier = q; + invariant = false; + precision = EbpUndefined; primarySize = 1; secondarySize = 1; - userDef = nullptr; + array = false; + arraySize = 0; + userDef = 0; line = ln; isStructSpecifier = false; } @@ -661,113 +641,79 @@ struct TTypeSpecifierNonArray primarySize = size; } - void setMatrix(unsigned char columns, unsigned char rows) + void setMatrix(unsigned char c, unsigned char r) { - ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4); - primarySize = columns; - secondarySize = rows; + ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4); + primarySize = c; + secondarySize = r; } - bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } - - bool isVector() const { return primarySize > 1 && secondarySize == 1; } -}; - -// -// This is a workaround for a problem with the yacc stack, It can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. Pointers -// could be used, but also trying to avoid lots of memory management overhead. -// -// Not as bad as it looks, there is no actual assumption that the fields -// match up or are name the same or anything like that. -// -struct TPublicType -{ - TTypeSpecifierNonArray typeSpecifierNonArray; - TLayoutQualifier layoutQualifier; - TMemoryQualifier memoryQualifier; - TQualifier qualifier; - bool invariant; - TPrecision precision; - bool array; - int arraySize; - - void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q) + bool isUnsizedArray() const { - typeSpecifierNonArray = typeSpecifier; - layoutQualifier = TLayoutQualifier::create(); - memoryQualifier = TMemoryQualifier::create(); - qualifier = q; - invariant = false; - precision = EbpUndefined; - array = false; - arraySize = 0; + return array && arraySize == 0; } - - void initializeBasicType(TBasicType basicType) + void setArraySize(int s) { - typeSpecifierNonArray.type = basicType; - typeSpecifierNonArray.primarySize = 1; - typeSpecifierNonArray.secondarySize = 1; - layoutQualifier = TLayoutQualifier::create(); - memoryQualifier = TMemoryQualifier::create(); - qualifier = EvqTemporary; - invariant = false; - precision = EbpUndefined; - array = false; - arraySize = 0; + array = true; + arraySize = s; + } + void clearArrayness() + { + array = false; + arraySize = 0; } - - TBasicType getBasicType() const { return typeSpecifierNonArray.type; } - void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; } - - unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; } - unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; } - - const TType *getUserDef() const { return typeSpecifierNonArray.userDef; } - const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; } - - bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; } bool isStructureContainingArrays() const { - if (!typeSpecifierNonArray.userDef) + if (!userDef) { return false; } - return typeSpecifierNonArray.userDef->isStructureContainingArrays(); + return userDef->isStructureContainingArrays(); } bool isStructureContainingType(TBasicType t) const { - if (!typeSpecifierNonArray.userDef) + if (!userDef) { return false; } - return typeSpecifierNonArray.userDef->isStructureContainingType(t); + return userDef->isStructureContainingType(t); } - bool isUnsizedArray() const { return array && arraySize == 0; } - void setArraySize(int s) + bool isMatrix() const { - array = true; - arraySize = s; + return primarySize > 1 && secondarySize > 1; } - void clearArrayness() + + bool isVector() const { - array = false; - arraySize = 0; + return primarySize > 1 && secondarySize == 1; + } + + int getCols() const + { + ASSERT(isMatrix()); + return primarySize; + } + + int getRows() const + { + ASSERT(isMatrix()); + return secondarySize; + } + + int getNominalSize() const + { + return primarySize; } bool isAggregate() const { - return array || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector(); + return array || isMatrix() || isVector(); } }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_TYPES_H_ diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp index b6a355a13..3ef555fc8 100755 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp @@ -6,37 +6,36 @@ #include "compiler/translator/UnfoldShortCircuitAST.h" -namespace sh -{ - namespace { // "x || y" is equivalent to "x ? true : y". -TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y) +TIntermSelection *UnfoldOR(TIntermTyped *x, TIntermTyped *y) { + const TType boolType(EbtBool, EbpUndefined); TConstantUnion *u = new TConstantUnion; u->setBConst(true); TIntermConstantUnion *trueNode = new TIntermConstantUnion( u, TType(EbtBool, EbpUndefined, EvqConst, 1)); - return new TIntermTernary(x, trueNode, y); + return new TIntermSelection(x, trueNode, y, boolType); } // "x && y" is equivalent to "x ? y : false". -TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y) +TIntermSelection *UnfoldAND(TIntermTyped *x, TIntermTyped *y) { + const TType boolType(EbtBool, EbpUndefined); TConstantUnion *u = new TConstantUnion; u->setBConst(false); TIntermConstantUnion *falseNode = new TIntermConstantUnion( u, TType(EbtBool, EbpUndefined, EvqConst, 1)); - return new TIntermTernary(x, y, falseNode); + return new TIntermSelection(x, y, falseNode, boolType); } } // namespace anonymous bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) { - TIntermTernary *replacement = nullptr; + TIntermSelection *replacement = NULL; switch (node->getOp()) { @@ -55,5 +54,3 @@ bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) } return true; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h index ac18bbf99..b92a4e915 100755 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -13,9 +13,6 @@ #include "common/angleutils.h" #include "compiler/translator/IntermNode.h" -namespace sh -{ - // This traverser identifies all the short circuit binary nodes that need to // be replaced, and creates the corresponding replacement nodes. However, // the actual replacements happen after the traverse through updateTree(). @@ -31,6 +28,4 @@ class UnfoldShortCircuitAST : public TIntermTraverser bool visitBinary(Visit visit, TIntermBinary *) override; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp index 22fa54287..4f32d6a7f 100755 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp @@ -13,9 +13,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNodePatternMatcher.h" -namespace sh -{ - namespace { @@ -26,7 +23,7 @@ class UnfoldShortCircuitTraverser : public TIntermTraverser UnfoldShortCircuitTraverser(); bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; void nextIteration(); bool foundShortCircuit() const { return mFoundShortCircuit; } @@ -78,12 +75,13 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) ASSERT(node->getLeft()->getType() == boolType); insertions.push_back(createTempInitDeclaration(node->getLeft())); - TIntermBlock *assignRightBlock = new TIntermBlock(); + TIntermAggregate *assignRightBlock = new TIntermAggregate(EOpSequence); ASSERT(node->getRight()->getType() == boolType); assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight())); - TIntermUnary *notTempSymbol = new TIntermUnary(EOpLogicalNot, createTempSymbol(boolType)); - TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr); + TIntermUnary *notTempSymbol = new TIntermUnary(EOpLogicalNot, boolType); + notTempSymbol->setOperand(createTempSymbol(boolType)); + TIntermSelection *ifNode = new TIntermSelection(notTempSymbol, assignRightBlock, nullptr); insertions.push_back(ifNode); insertStatementsInParentBlock(insertions); @@ -102,12 +100,12 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) ASSERT(node->getLeft()->getType() == boolType); insertions.push_back(createTempInitDeclaration(node->getLeft())); - TIntermBlock *assignRightBlock = new TIntermBlock(); + TIntermAggregate *assignRightBlock = new TIntermAggregate(EOpSequence); ASSERT(node->getRight()->getType() == boolType); assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight())); - TIntermIfElse *ifNode = - new TIntermIfElse(createTempSymbol(boolType), assignRightBlock, nullptr); + TIntermSelection *ifNode = + new TIntermSelection(createTempSymbol(boolType), assignRightBlock, nullptr); insertions.push_back(ifNode); insertStatementsInParentBlock(insertions); @@ -121,7 +119,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) } } -bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node) +bool UnfoldShortCircuitTraverser::visitSelection(Visit visit, TIntermSelection *node) { if (mFoundShortCircuit) return false; @@ -134,22 +132,26 @@ bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node mFoundShortCircuit = true; + ASSERT(node->usesTernaryOperator()); + // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" TIntermSequence insertions; - TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType()); + TIntermSymbol *tempSymbol = createTempSymbol(node->getType()); + TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration); + tempDeclaration->getSequence()->push_back(tempSymbol); insertions.push_back(tempDeclaration); - TIntermBlock *trueBlock = new TIntermBlock(); - TIntermBinary *trueAssignment = createTempAssignment(node->getTrueExpression()); + TIntermAggregate *trueBlock = new TIntermAggregate(EOpSequence); + TIntermBinary *trueAssignment = createTempAssignment(node->getTrueBlock()->getAsTyped()); trueBlock->getSequence()->push_back(trueAssignment); - TIntermBlock *falseBlock = new TIntermBlock(); - TIntermBinary *falseAssignment = createTempAssignment(node->getFalseExpression()); + TIntermAggregate *falseBlock = new TIntermAggregate(EOpSequence); + TIntermBinary *falseAssignment = createTempAssignment(node->getFalseBlock()->getAsTyped()); falseBlock->getSequence()->push_back(falseAssignment); - TIntermIfElse *ifNode = - new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock); + TIntermSelection *ifNode = + new TIntermSelection(node->getCondition()->getAsTyped(), trueBlock, falseBlock); insertions.push_back(ifNode); insertStatementsInParentBlock(insertions); @@ -183,5 +185,3 @@ void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex) } while (traverser.foundShortCircuit()); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.h b/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.h index 24ff289a3..0fe37b714 100755 --- a/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.h +++ b/gfx/angle/src/compiler/translator/UnfoldShortCircuitToIf.h @@ -11,11 +11,8 @@ #ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ #define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ -namespace sh -{ class TIntermNode; void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex); -} // namespace sh #endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ diff --git a/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp deleted file mode 100644 index 390e2b092..000000000 --- a/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at -// the beginning of main. This is to work around a Mac driver that treats unused standard/shared -// uniform blocks as inactive. - -#include "compiler/translator/UseInterfaceBlockFields.h" - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/util.h" - -namespace sh -{ - -namespace -{ - -class UseUniformBlockMembers : public TIntermTraverser -{ - public: - UseUniformBlockMembers(const InterfaceBlockList &blocks, const TSymbolTable &symbolTable) - : TIntermTraverser(true, false, false), - mBlocks(blocks), - mSymbolTable(symbolTable), - mCodeInserted(false) - { - ASSERT(mSymbolTable.atGlobalLevel()); - } - - protected: - bool visitAggregate(Visit visit, TIntermAggregate *node) override { return !mCodeInserted; } - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; - - private: - void insertUseCode(TIntermSequence *sequence); - void AddFieldUseStatements(const ShaderVariable &var, TIntermSequence *sequence); - - const InterfaceBlockList &mBlocks; - const TSymbolTable &mSymbolTable; - bool mCodeInserted; -}; - -bool UseUniformBlockMembers::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - ASSERT(visit == PreVisit); - if (node->getFunctionSymbolInfo()->isMain()) - { - TIntermBlock *body = node->getBody(); - ASSERT(body); - insertUseCode(body->getSequence()); - mCodeInserted = true; - return false; - } - return !mCodeInserted; -} - -void UseUniformBlockMembers::AddFieldUseStatements(const ShaderVariable &var, - TIntermSequence *sequence) -{ - TString name = TString(var.name.c_str()); - if (var.isArray()) - { - size_t pos = name.find_last_of('['); - if (pos != TString::npos) - { - name = name.substr(0, pos); - } - } - const TType *type; - TType basicType; - if (var.isStruct()) - { - TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); - ASSERT(structInfo); - const TType &structType = structInfo->getType(); - type = &structType; - } - else - { - basicType = sh::GetShaderVariableBasicType(var); - type = &basicType; - } - ASSERT(type); - - TIntermSymbol *symbol = new TIntermSymbol(0, name, *type); - if (var.isArray()) - { - for (unsigned int i = 0; i < var.arraySize; ++i) - { - TIntermBinary *element = - new TIntermBinary(EOpIndexDirect, symbol, TIntermTyped::CreateIndexNode(i)); - sequence->insert(sequence->begin(), element); - } - } - else - { - sequence->insert(sequence->begin(), symbol); - } -} - -void UseUniformBlockMembers::insertUseCode(TIntermSequence *sequence) -{ - for (const auto &block : mBlocks) - { - if (block.instanceName.empty()) - { - for (const auto &var : block.fields) - { - AddFieldUseStatements(var, sequence); - } - } - else if (block.arraySize > 0) - { - TString name = TString(block.instanceName.c_str()); - TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); - ASSERT(ubInfo); - TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, ubInfo->getType()); - for (unsigned int i = 0; i < block.arraySize; ++i) - { - TIntermBinary *instanceSymbol = new TIntermBinary(EOpIndexDirect, arraySymbol, - TIntermTyped::CreateIndexNode(i)); - for (unsigned int j = 0; j < block.fields.size(); ++j) - { - TIntermBinary *element = - new TIntermBinary(EOpIndexDirectInterfaceBlock, instanceSymbol, - TIntermTyped::CreateIndexNode(j)); - sequence->insert(sequence->begin(), element); - } - } - } - else - { - TString name = TString(block.instanceName.c_str()); - TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); - ASSERT(ubInfo); - TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, ubInfo->getType()); - for (unsigned int i = 0; i < block.fields.size(); ++i) - { - TIntermBinary *element = new TIntermBinary( - EOpIndexDirectInterfaceBlock, blockSymbol, TIntermTyped::CreateIndexNode(i)); - - sequence->insert(sequence->begin(), element); - } - } - } -} - -} // namespace anonymous - -void UseInterfaceBlockFields(TIntermNode *root, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable) -{ - UseUniformBlockMembers useUniformBlock(blocks, symbolTable); - root->traverse(&useUniformBlock); -} - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.h b/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.h deleted file mode 100644 index a789bb7e9..000000000 --- a/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UseInterfaceBlockFields.h: insert statements to reference all members in InterfaceBlock list at -// the beginning of main. This is to work around a Mac driver that treats unused standard/shared -// uniform blocks as inactive. - -#ifndef COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ -#define COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ - -#include <GLSLANG/ShaderLang.h> - -class TIntermNode; -namespace sh -{ - -class TSymbolTable; - -using InterfaceBlockList = std::vector<sh::InterfaceBlock>; - -void UseInterfaceBlockFields(TIntermNode *root, - const InterfaceBlockList &blocks, - const TSymbolTable &symbolTable); - -} // namespace sh - -#endif // COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_ diff --git a/gfx/angle/src/compiler/translator/UtilsHLSL.cpp b/gfx/angle/src/compiler/translator/UtilsHLSL.cpp index 221d5d9b5..b3a065f19 100755 --- a/gfx/angle/src/compiler/translator/UtilsHLSL.cpp +++ b/gfx/angle/src/compiler/translator/UtilsHLSL.cpp @@ -173,8 +173,6 @@ TString TextureTypeSuffix(const TBasicType type) return "Cube_int4_"; case EbtUSamplerCube: return "Cube_uint4_"; - case EbtSamplerExternalOES: - return "_External"; default: // All other types are identified by their group suffix return TextureGroupSuffix(type); diff --git a/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.cpp b/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.cpp index d5b1b3be4..2461b6a43 100755 --- a/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.cpp +++ b/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.cpp @@ -8,9 +8,6 @@ #include "compiler/translator/ParseContext.h" -namespace sh -{ - namespace { @@ -113,4 +110,3 @@ bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *c return validate.isValid(); } -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.h b/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.h index 89b4b1176..c3d2a47eb 100755 --- a/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.h +++ b/gfx/angle/src/compiler/translator/ValidateGlobalInitializer.h @@ -7,15 +7,10 @@ #ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ #define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ -namespace sh -{ - class TIntermTyped; class TParseContext; // Returns true if the initializer is valid. bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning); -} // namespace sh - #endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ diff --git a/gfx/angle/src/compiler/translator/ValidateLimitations.cpp b/gfx/angle/src/compiler/translator/ValidateLimitations.cpp index 75a0c5156..ba8cdd0aa 100755 --- a/gfx/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/gfx/angle/src/compiler/translator/ValidateLimitations.cpp @@ -10,9 +10,6 @@ #include "compiler/translator/ParseContext.h" #include "angle_gl.h" -namespace sh -{ - namespace { @@ -216,8 +213,8 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node) // init-declaration has the form: // type-specifier identifier = constant-expression // - TIntermDeclaration *decl = init->getAsDeclarationNode(); - if (decl == nullptr) + TIntermAggregate *decl = init->getAsAggregate(); + if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { error(init->getLine(), "Invalid init declaration", "for"); return -1; @@ -426,8 +423,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate *node) bool valid = true; TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; - TSymbol *symbol = symbolTable.find(node->getFunctionSymbolInfo()->getName(), - GetGlobalParseContext()->getShaderVersion()); + TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->getShaderVersion()); ASSERT(symbol && symbol->isFunction()); TFunction *function = static_cast<TFunction *>(symbol); for (ParamIndex::const_iterator i = pIndex.begin(); @@ -499,4 +495,3 @@ bool ValidateLimitations::validateIndexing(TIntermBinary *node) return valid; } -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ValidateLimitations.h b/gfx/angle/src/compiler/translator/ValidateLimitations.h index 4c84f9db7..666e38ff5 100755 --- a/gfx/angle/src/compiler/translator/ValidateLimitations.h +++ b/gfx/angle/src/compiler/translator/ValidateLimitations.h @@ -10,9 +10,6 @@ #include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" -namespace sh -{ - class TInfoSinkBase; // Traverses intermediate tree to ensure that the shader does not exceed the @@ -63,6 +60,4 @@ class ValidateLimitations : public TIntermTraverser bool mValidateInnerLoops; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/gfx/angle/src/compiler/translator/ValidateMaxParameters.cpp b/gfx/angle/src/compiler/translator/ValidateMaxParameters.cpp index f97f7a907..00b3c9b45 100755 --- a/gfx/angle/src/compiler/translator/ValidateMaxParameters.cpp +++ b/gfx/angle/src/compiler/translator/ValidateMaxParameters.cpp @@ -7,9 +7,6 @@ #include "compiler/translator/ValidateMaxParameters.h" -namespace sh -{ - ValidateMaxParameters::ValidateMaxParameters(unsigned int maxParameters) : TIntermTraverser(true, false, false), mMaxParameters(maxParameters), mValid(true) { @@ -36,5 +33,3 @@ bool ValidateMaxParameters::validate(TIntermNode *root, unsigned int maxParamete root->traverse(&argsTraverser); return argsTraverser.mValid; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ValidateMaxParameters.h b/gfx/angle/src/compiler/translator/ValidateMaxParameters.h index fdd0b8d09..87916afef 100755 --- a/gfx/angle/src/compiler/translator/ValidateMaxParameters.h +++ b/gfx/angle/src/compiler/translator/ValidateMaxParameters.h @@ -10,9 +10,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ - class ValidateMaxParameters : public TIntermTraverser { public: @@ -29,6 +26,4 @@ class ValidateMaxParameters : public TIntermTraverser bool mValid; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_ diff --git a/gfx/angle/src/compiler/translator/ValidateOutputs.cpp b/gfx/angle/src/compiler/translator/ValidateOutputs.cpp index e48da8a79..9f5f8f577 100755 --- a/gfx/angle/src/compiler/translator/ValidateOutputs.cpp +++ b/gfx/angle/src/compiler/translator/ValidateOutputs.cpp @@ -9,9 +9,6 @@ #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/ParseContext.h" -namespace sh -{ - namespace { void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason) @@ -109,5 +106,3 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const } return errorCount; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ValidateOutputs.h b/gfx/angle/src/compiler/translator/ValidateOutputs.h index 0788f4ed6..0122ca25f 100755 --- a/gfx/angle/src/compiler/translator/ValidateOutputs.h +++ b/gfx/angle/src/compiler/translator/ValidateOutputs.h @@ -12,9 +12,6 @@ #include <set> -namespace sh -{ - class TInfoSinkBase; class ValidateOutputs : public TIntermTraverser @@ -36,6 +33,4 @@ class ValidateOutputs : public TIntermTraverser std::set<std::string> mVisitedSymbols; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/gfx/angle/src/compiler/translator/ValidateSwitch.cpp b/gfx/angle/src/compiler/translator/ValidateSwitch.cpp index 9bcd8f5fe..9a4ed3363 100755 --- a/gfx/angle/src/compiler/translator/ValidateSwitch.cpp +++ b/gfx/angle/src/compiler/translator/ValidateSwitch.cpp @@ -8,13 +8,8 @@ #include "compiler/translator/ParseContext.h" -namespace sh -{ - -bool ValidateSwitch::validate(TBasicType switchType, - TParseContext *context, - TIntermBlock *statementList, - const TSourceLoc &loc) +bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc) { ValidateSwitch validate(switchType, context); ASSERT(statementList); @@ -64,19 +59,11 @@ bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) { if (!mFirstCaseFound) mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitTernary(Visit, TIntermTernary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; mLastStatementWasCase = false; return true; } -bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *) +bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) { if (visit == PreVisit) ++mControlFlowDepth; @@ -211,5 +198,3 @@ bool ValidateSwitch::validateInternal(const TSourceLoc &loc) return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/ValidateSwitch.h b/gfx/angle/src/compiler/translator/ValidateSwitch.h index feffbc03c..ddbefc561 100755 --- a/gfx/angle/src/compiler/translator/ValidateSwitch.h +++ b/gfx/angle/src/compiler/translator/ValidateSwitch.h @@ -9,8 +9,6 @@ #include "compiler/translator/IntermNode.h" -namespace sh -{ class TParseContext; class ValidateSwitch : public TIntermTraverser @@ -18,17 +16,14 @@ class ValidateSwitch : public TIntermTraverser public: // Check for errors and output messages any remaining errors on the context. // Returns true if there are no errors. - static bool validate(TBasicType switchType, - TParseContext *context, - TIntermBlock *statementList, - const TSourceLoc &loc); + static bool validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc); void visitSymbol(TIntermSymbol *) override; void visitConstantUnion(TIntermConstantUnion *) override; bool visitBinary(Visit, TIntermBinary *) override; bool visitUnary(Visit, TIntermUnary *) override; - bool visitTernary(Visit, TIntermTernary *) override; - bool visitIfElse(Visit visit, TIntermIfElse *) override; + bool visitSelection(Visit visit, TIntermSelection *) override; bool visitSwitch(Visit, TIntermSwitch *) override; bool visitCase(Visit, TIntermCase *node) override; bool visitAggregate(Visit, TIntermAggregate *) override; @@ -54,6 +49,4 @@ class ValidateSwitch : public TIntermTraverser bool mDuplicateCases; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/gfx/angle/src/compiler/translator/VariableInfo.cpp b/gfx/angle/src/compiler/translator/VariableInfo.cpp index 07fe12e5d..7e1e5cd82 100755 --- a/gfx/angle/src/compiler/translator/VariableInfo.cpp +++ b/gfx/angle/src/compiler/translator/VariableInfo.cpp @@ -559,43 +559,54 @@ void CollectVariables::visitInfoList(const TIntermSequence &sequence, } } -bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node) +bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) { - const TIntermSequence &sequence = *(node->getSequence()); - ASSERT(!sequence.empty()); + bool visitChildren = true; - const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); - TQualifier qualifier = typedNode.getQualifier(); - - if (typedNode.getBasicType() == EbtInterfaceBlock) + switch (node->getOp()) { - visitInfoList(sequence, mInterfaceBlocks); - return false; - } - else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut || - qualifier == EvqUniform || IsVarying(qualifier)) - { - switch (qualifier) + case EOpDeclaration: { - case EvqAttribute: - case EvqVertexIn: - visitInfoList(sequence, mAttribs); - break; - case EvqFragmentOut: - visitInfoList(sequence, mOutputVariables); - break; - case EvqUniform: - visitInfoList(sequence, mUniforms); - break; - default: - visitInfoList(sequence, mVaryings); - break; - } + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); - return false; + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); + TQualifier qualifier = typedNode.getQualifier(); + + if (typedNode.getBasicType() == EbtInterfaceBlock) + { + visitInfoList(sequence, mInterfaceBlocks); + visitChildren = false; + } + else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || + qualifier == EvqFragmentOut || qualifier == EvqUniform || + IsVarying(qualifier)) + { + switch (qualifier) + { + case EvqAttribute: + case EvqVertexIn: + visitInfoList(sequence, mAttribs); + break; + case EvqFragmentOut: + visitInfoList(sequence, mOutputVariables); + break; + case EvqUniform: + visitInfoList(sequence, mUniforms); + break; + default: + visitInfoList(sequence, mVaryings); + break; + } + + visitChildren = false; + } + break; + } + default: break; } - return true; + return visitChildren; } bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) diff --git a/gfx/angle/src/compiler/translator/VariableInfo.h b/gfx/angle/src/compiler/translator/VariableInfo.h index 6b2115656..f79035d38 100755 --- a/gfx/angle/src/compiler/translator/VariableInfo.h +++ b/gfx/angle/src/compiler/translator/VariableInfo.h @@ -31,7 +31,7 @@ class CollectVariables : public TIntermTraverser const TExtensionBehavior &extensionBehavior); void visitSymbol(TIntermSymbol *symbol) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; private: diff --git a/gfx/angle/src/compiler/translator/VersionGLSL.cpp b/gfx/angle/src/compiler/translator/VersionGLSL.cpp index 9e593ac76..c8718daa1 100755 --- a/gfx/angle/src/compiler/translator/VersionGLSL.cpp +++ b/gfx/angle/src/compiler/translator/VersionGLSL.cpp @@ -6,9 +6,6 @@ #include "compiler/translator/VersionGLSL.h" -namespace sh -{ - int ShaderOutputTypeToGLSLVersion(ShShaderOutput output) { switch (output) @@ -65,22 +62,25 @@ void TVersionGLSL::visitSymbol(TIntermSymbol *node) } } -bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node) -{ - const TIntermSequence &sequence = *(node->getSequence()); - if (sequence.front()->getAsTyped()->getType().isInvariant()) - { - ensureVersionIsAtLeast(GLSL_VERSION_120); - } - return true; -} - bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) { bool visitChildren = true; switch (node->getOp()) { + case EOpSequence: + // We need to visit sequence children to get to global or inner scope. + visitChildren = true; + break; + case EOpDeclaration: + { + const TIntermSequence &sequence = *(node->getSequence()); + if (sequence.front()->getAsTyped()->getType().isInvariant()) + { + ensureVersionIsAtLeast(GLSL_VERSION_120); + } + break; + } case EOpInvariantDeclaration: ensureVersionIsAtLeast(GLSL_VERSION_120); break; @@ -138,4 +138,3 @@ void TVersionGLSL::ensureVersionIsAtLeast(int version) mVersion = std::max(version, mVersion); } -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/VersionGLSL.h b/gfx/angle/src/compiler/translator/VersionGLSL.h index 380349be0..c41069d42 100755 --- a/gfx/angle/src/compiler/translator/VersionGLSL.h +++ b/gfx/angle/src/compiler/translator/VersionGLSL.h @@ -11,9 +11,6 @@ #include "compiler/translator/Pragma.h" -namespace sh -{ - static const int GLSL_VERSION_110 = 110; static const int GLSL_VERSION_120 = 120; static const int GLSL_VERSION_130 = 130; @@ -61,7 +58,6 @@ class TVersionGLSL : public TIntermTraverser void visitSymbol(TIntermSymbol *) override; bool visitAggregate(Visit, TIntermAggregate *) override; - bool visitDeclaration(Visit, TIntermDeclaration *node) override; private: void ensureVersionIsAtLeast(int version); @@ -69,6 +65,4 @@ class TVersionGLSL : public TIntermTraverser int mVersion; }; -} // namespace sh - #endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_ diff --git a/gfx/angle/src/compiler/translator/blocklayout.h b/gfx/angle/src/compiler/translator/blocklayout.h index 298a72c92..dd5fe0737 100755 --- a/gfx/angle/src/compiler/translator/blocklayout.h +++ b/gfx/angle/src/compiler/translator/blocklayout.h @@ -24,7 +24,7 @@ struct Uniform; struct Varying; struct InterfaceBlock; -struct BlockMemberInfo +struct COMPILER_EXPORT BlockMemberInfo { BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {} @@ -46,7 +46,7 @@ struct BlockMemberInfo bool isRowMajorMatrix; }; -class BlockLayoutEncoder +class COMPILER_EXPORT BlockLayoutEncoder { public: BlockLayoutEncoder(); @@ -77,7 +77,7 @@ class BlockLayoutEncoder // Block layout according to the std140 block layout // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification -class Std140BlockEncoder : public BlockLayoutEncoder +class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder { public: Std140BlockEncoder(); diff --git a/gfx/angle/src/compiler/translator/blocklayoutHLSL.h b/gfx/angle/src/compiler/translator/blocklayoutHLSL.h index 8d98847bd..c61cb1ae5 100755 --- a/gfx/angle/src/compiler/translator/blocklayoutHLSL.h +++ b/gfx/angle/src/compiler/translator/blocklayoutHLSL.h @@ -24,7 +24,7 @@ namespace sh // The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED // for everything else (D3D10+ constant blocks and all attributes/varyings). -class HLSLBlockEncoder : public BlockLayoutEncoder +class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder { public: enum HLSLBlockEncoderStrategy @@ -54,8 +54,9 @@ class HLSLBlockEncoder : public BlockLayoutEncoder // This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder // class to count the number of used registers in a struct (which are individually packed according to the same rules). -unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices); -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); +COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices); +COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); + } #endif // COMMON_BLOCKLAYOUTHLSL_H_ diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.cpp b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.cpp new file mode 100644 index 000000000..4dee0dbd2 --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraphBuilder.h" + +TDependencyGraph::TDependencyGraph(TIntermNode* intermNode) +{ + TDependencyGraphBuilder::build(intermNode, this); +} + +TDependencyGraph::~TDependencyGraph() +{ + for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter) + { + TGraphNode* node = *iter; + delete node; + } +} + +TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall, + int argumentNumber) +{ + TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber); + mAllNodes.push_back(argument); + return argument; +} + +TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall) +{ + TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall); + mAllNodes.push_back(functionCall); + if (functionCall->getIntermFunctionCall()->isUserDefined()) + mUserDefinedFunctionCalls.push_back(functionCall); + return functionCall; +} + +TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol) +{ + TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId()); + + TGraphSymbol* symbol = NULL; + + if (iter != mSymbolIdMap.end()) { + TSymbolIdPair pair = *iter; + symbol = pair.second; + } else { + symbol = new TGraphSymbol(intermSymbol); + mAllNodes.push_back(symbol); + + TSymbolIdPair pair(intermSymbol->getId(), symbol); + mSymbolIdMap.insert(pair); + + // We save all sampler symbols in a collection, so we can start graph traversals from them quickly. + if (IsSampler(intermSymbol->getBasicType())) + mSamplerSymbols.push_back(symbol); + } + + return symbol; +} + +TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection) +{ + TGraphSelection* selection = new TGraphSelection(intermSelection); + mAllNodes.push_back(selection); + return selection; +} + +TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop) +{ + TGraphLoop* loop = new TGraphLoop(intermLoop); + mAllNodes.push_back(loop); + return loop; +} + +TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp) +{ + TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp); + mAllNodes.push_back(logicalOp); + return logicalOp; +} + +const char* TGraphLogicalOp::getOpString() const +{ + const char* opString = NULL; + switch (getIntermLogicalOp()->getOp()) { + case EOpLogicalAnd: opString = "and"; break; + case EOpLogicalOr: opString = "or"; break; + default: opString = "unknown"; break; + } + return opString; +} diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h new file mode 100644 index 000000000..2f7f7b9ab --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -0,0 +1,199 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ + +#include "compiler/translator/IntermNode.h" + +#include <set> +#include <stack> + +class TGraphNode; +class TGraphParentNode; +class TGraphArgument; +class TGraphFunctionCall; +class TGraphSymbol; +class TGraphSelection; +class TGraphLoop; +class TGraphLogicalOp; +class TDependencyGraphTraverser; +class TDependencyGraphOutput; + +typedef std::set<TGraphNode*> TGraphNodeSet; +typedef std::vector<TGraphNode*> TGraphNodeVector; +typedef std::vector<TGraphSymbol*> TGraphSymbolVector; +typedef std::vector<TGraphFunctionCall*> TFunctionCallVector; + +// +// Base class for all dependency graph nodes. +// +class TGraphNode { +public: + TGraphNode(TIntermNode* node) : intermNode(node) {} + virtual ~TGraphNode() {} + virtual void traverse(TDependencyGraphTraverser* graphTraverser); +protected: + TIntermNode* intermNode; +}; + +// +// Base class for dependency graph nodes that may have children. +// +class TGraphParentNode : public TGraphNode { +public: + TGraphParentNode(TIntermNode* node) : TGraphNode(node) {} + ~TGraphParentNode() override {} + void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); } + void traverse(TDependencyGraphTraverser *graphTraverser) override; + +private: + TGraphNodeSet mDependentNodes; +}; + +// +// Handle function call arguments. +// +class TGraphArgument : public TGraphParentNode { +public: + TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber) + : TGraphParentNode(intermFunctionCall) + , mArgumentNumber(argumentNumber) {} + ~TGraphArgument() override {} + const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } + int getArgumentNumber() const { return mArgumentNumber; } + void traverse(TDependencyGraphTraverser *graphTraverser) override; + +private: + int mArgumentNumber; +}; + +// +// Handle function calls. +// +class TGraphFunctionCall : public TGraphParentNode { +public: + TGraphFunctionCall(TIntermAggregate* intermFunctionCall) + : TGraphParentNode(intermFunctionCall) {} + ~TGraphFunctionCall() override {} + const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); } + void traverse(TDependencyGraphTraverser *graphTraverser) override; +}; + +// +// Handle symbols. +// +class TGraphSymbol : public TGraphParentNode { +public: + TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {} + ~TGraphSymbol() override {} + const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); } + void traverse(TDependencyGraphTraverser *graphTraverser) override; +}; + +// +// Handle if statements and ternary operators. +// +class TGraphSelection : public TGraphNode { +public: + TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {} + ~TGraphSelection() override {} + const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); } + void traverse(TDependencyGraphTraverser *graphTraverser) override; +}; + +// +// Handle for, do-while, and while loops. +// +class TGraphLoop : public TGraphNode { +public: + TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {} + ~TGraphLoop() override {} + const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); } + void traverse(TDependencyGraphTraverser *graphTraverser) override; +}; + +// +// Handle logical and, or. +// +class TGraphLogicalOp : public TGraphNode { +public: + TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {} + ~TGraphLogicalOp() override {} + const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); } + const char* getOpString() const; + void traverse(TDependencyGraphTraverser *graphTraverser) override; +}; + +// +// A dependency graph of symbols, function calls, conditions etc. +// +// This class provides an interface to the entry points of the dependency graph. +// +// Dependency graph nodes should be created by using one of the provided "create..." methods. +// This class (and nobody else) manages the memory of the created nodes. +// Nodes may not be removed after being added, so all created nodes will exist while the +// TDependencyGraph instance exists. +// +class TDependencyGraph { +public: + TDependencyGraph(TIntermNode* intermNode); + ~TDependencyGraph(); + const TGraphNodeVector &allNodes() const { return mAllNodes; } + const TGraphSymbolVector &samplerSymbols() const { return mSamplerSymbols; } + const TFunctionCallVector &userDefinedFunctionCalls() const + { + return mUserDefinedFunctionCalls; + } + + TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber); + TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall); + TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol); + TGraphSelection* createSelection(TIntermSelection* intermSelection); + TGraphLoop* createLoop(TIntermLoop* intermLoop); + TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp); +private: + typedef TMap<int, TGraphSymbol*> TSymbolIdMap; + typedef std::pair<int, TGraphSymbol*> TSymbolIdPair; + + TGraphNodeVector mAllNodes; + TGraphSymbolVector mSamplerSymbols; + TFunctionCallVector mUserDefinedFunctionCalls; + TSymbolIdMap mSymbolIdMap; +}; + +// +// For traversing the dependency graph. Users should derive from this, +// put their traversal specific data in it, and then pass it to a +// traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// +class TDependencyGraphTraverser : angle::NonCopyable { +public: + TDependencyGraphTraverser() : mDepth(0) {} + virtual ~TDependencyGraphTraverser() {} + + virtual void visitSymbol(TGraphSymbol* symbol) {}; + virtual void visitArgument(TGraphArgument* selection) {}; + virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {}; + virtual void visitSelection(TGraphSelection* selection) {}; + virtual void visitLoop(TGraphLoop* loop) {}; + virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {}; + + int getDepth() const { return mDepth; } + void incrementDepth() { ++mDepth; } + void decrementDepth() { --mDepth; } + + void clearVisited() { mVisited.clear(); } + void markVisited(TGraphNode* node) { mVisited.insert(node); } + bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); } +private: + int mDepth; + TGraphNodeSet mVisited; +}; + +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp new file mode 100644 index 000000000..1aeb822d5 --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp @@ -0,0 +1,255 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraphBuilder.h" + +void TDependencyGraphBuilder::build(TIntermNode *node, TDependencyGraph *graph) +{ + TDependencyGraphBuilder builder(graph); + builder.build(node); +} + +bool TDependencyGraphBuilder::visitAggregate( + Visit visit, TIntermAggregate *intermAggregate) +{ + switch (intermAggregate->getOp()) + { + case EOpFunction: + visitFunctionDefinition(intermAggregate); + break; + case EOpFunctionCall: + visitFunctionCall(intermAggregate); + break; + default: + visitAggregateChildren(intermAggregate); + break; + } + return false; +} + +void TDependencyGraphBuilder::visitFunctionDefinition( + TIntermAggregate *intermAggregate) +{ + // Currently, we do not support user defined functions. + if (intermAggregate->getName() != "main(") + return; + + visitAggregateChildren(intermAggregate); +} + +// Takes an expression like "f(x)" and creates a dependency graph like +// "x -> argument 0 -> function call". +void TDependencyGraphBuilder::visitFunctionCall( + TIntermAggregate *intermFunctionCall) +{ + TGraphFunctionCall *functionCall = + mGraph->createFunctionCall(intermFunctionCall); + + // Run through the function call arguments. + int argumentNumber = 0; + TIntermSequence *intermArguments = intermFunctionCall->getSequence(); + for (TIntermSequence::const_iterator iter = intermArguments->begin(); + iter != intermArguments->end(); + ++iter, ++argumentNumber) + { + TNodeSetMaintainer nodeSetMaintainer(this); + + TIntermNode *intermArgument = *iter; + intermArgument->traverse(this); + + if (TParentNodeSet *argumentNodes = mNodeSets.getTopSet()) + { + TGraphArgument *argument = mGraph->createArgument( + intermFunctionCall, argumentNumber); + connectMultipleNodesToSingleNode(argumentNodes, argument); + argument->addDependentNode(functionCall); + } + } + + // Push the leftmost symbol of this function call into the current set of + // dependent symbols to represent the result of this function call. + // Thus, an expression like "y = f(x)" will yield a dependency graph like + // "x -> argument 0 -> function call -> y". + // This line essentially passes the function call node back up to an earlier + // visitAssignment call, which will create the connection "function call -> y". + mNodeSets.insertIntoTopSet(functionCall); +} + +void TDependencyGraphBuilder::visitAggregateChildren( + TIntermAggregate *intermAggregate) +{ + TIntermSequence *sequence = intermAggregate->getSequence(); + for (TIntermSequence::const_iterator iter = sequence->begin(); + iter != sequence->end(); ++iter) + { + TIntermNode *intermChild = *iter; + intermChild->traverse(this); + } +} + +void TDependencyGraphBuilder::visitSymbol(TIntermSymbol *intermSymbol) +{ + // Push this symbol into the set of dependent symbols for the current + // assignment or condition that we are traversing. + TGraphSymbol *symbol = mGraph->getOrCreateSymbol(intermSymbol); + mNodeSets.insertIntoTopSet(symbol); + + // If this symbol is the current leftmost symbol under an assignment, replace + // the previous leftmost symbol with this symbol. + if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) + { + mLeftmostSymbols.pop(); + mLeftmostSymbols.push(symbol); + } +} + +bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary *intermBinary) +{ + TOperator op = intermBinary->getOp(); + if (op == EOpInitialize || intermBinary->isAssignment()) + visitAssignment(intermBinary); + else if (op == EOpLogicalAnd || op == EOpLogicalOr) + visitLogicalOp(intermBinary); + else + visitBinaryChildren(intermBinary); + + return false; +} + +void TDependencyGraphBuilder::visitAssignment(TIntermBinary *intermAssignment) +{ + TIntermTyped *intermLeft = intermAssignment->getLeft(); + if (!intermLeft) + return; + + TGraphSymbol *leftmostSymbol = NULL; + + { + TNodeSetMaintainer nodeSetMaintainer(this); + + { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree); + intermLeft->traverse(this); + leftmostSymbol = mLeftmostSymbols.top(); + + // After traversing the left subtree of this assignment, we should + // have found a real leftmost symbol, and the leftmost symbol should + // not be a placeholder. + ASSERT(leftmostSymbol != &mLeftSubtree); + ASSERT(leftmostSymbol != &mRightSubtree); + } + + if (TIntermTyped *intermRight = intermAssignment->getRight()) + { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); + intermRight->traverse(this); + } + + if (TParentNodeSet *assignmentNodes = mNodeSets.getTopSet()) + connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol); + } + + // Push the leftmost symbol of this assignment into the current set of dependent + // symbols to represent the result of this assignment. + // An expression like "a = (b = c)" will yield a dependency graph like + // "c -> b -> a". + // This line essentially passes the leftmost symbol of the nested assignment + // ("b" in this example) back up to the earlier visitAssignment call for the + // outer assignment, which will create the connection "b -> a". + mNodeSets.insertIntoTopSet(leftmostSymbol); +} + +void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary *intermLogicalOp) +{ + if (TIntermTyped *intermLeft = intermLogicalOp->getLeft()) + { + TNodeSetPropagatingMaintainer nodeSetMaintainer(this); + + intermLeft->traverse(this); + if (TParentNodeSet *leftNodes = mNodeSets.getTopSet()) + { + TGraphLogicalOp *logicalOp = mGraph->createLogicalOp(intermLogicalOp); + connectMultipleNodesToSingleNode(leftNodes, logicalOp); + } + } + + if (TIntermTyped *intermRight = intermLogicalOp->getRight()) + { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); + intermRight->traverse(this); + } +} + +void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary *intermBinary) +{ + if (TIntermTyped *intermLeft = intermBinary->getLeft()) + intermLeft->traverse(this); + + if (TIntermTyped *intermRight = intermBinary->getRight()) + { + TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); + intermRight->traverse(this); + } +} + +bool TDependencyGraphBuilder::visitSelection( + Visit visit, TIntermSelection *intermSelection) +{ + if (TIntermNode *intermCondition = intermSelection->getCondition()) + { + TNodeSetMaintainer nodeSetMaintainer(this); + + intermCondition->traverse(this); + if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet()) + { + TGraphSelection *selection = mGraph->createSelection(intermSelection); + connectMultipleNodesToSingleNode(conditionNodes, selection); + } + } + + if (TIntermNode *intermTrueBlock = intermSelection->getTrueBlock()) + intermTrueBlock->traverse(this); + + if (TIntermNode *intermFalseBlock = intermSelection->getFalseBlock()) + intermFalseBlock->traverse(this); + + return false; +} + +bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop *intermLoop) +{ + if (TIntermTyped *intermCondition = intermLoop->getCondition()) + { + TNodeSetMaintainer nodeSetMaintainer(this); + + intermCondition->traverse(this); + if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet()) + { + TGraphLoop *loop = mGraph->createLoop(intermLoop); + connectMultipleNodesToSingleNode(conditionNodes, loop); + } + } + + if (TIntermNode* intermBody = intermLoop->getBody()) + intermBody->traverse(this); + + if (TIntermTyped *intermExpression = intermLoop->getExpression()) + intermExpression->traverse(this); + + return false; +} + + +void TDependencyGraphBuilder::connectMultipleNodesToSingleNode( + TParentNodeSet *nodes, TGraphNode *node) const +{ + for (TParentNodeSet::const_iterator iter = nodes->begin(); + iter != nodes->end(); ++iter) + { + TGraphParentNode *currentNode = *iter; + currentNode->addDependentNode(node); + } +} diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h new file mode 100644 index 000000000..c7b54f66b --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -0,0 +1,199 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ + +#include "compiler/translator/depgraph/DependencyGraph.h" + +// +// Creates a dependency graph of symbols, function calls, conditions etc. by +// traversing a intermediate tree. +// +class TDependencyGraphBuilder : public TIntermTraverser +{ + public: + static void build(TIntermNode *node, TDependencyGraph *graph); + + void visitSymbol(TIntermSymbol *) override; + bool visitBinary(Visit visit, TIntermBinary *) override; + bool visitSelection(Visit visit, TIntermSelection *) override; + bool visitAggregate(Visit visit, TIntermAggregate *) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + + private: + typedef std::stack<TGraphSymbol *> TSymbolStack; + typedef std::set<TGraphParentNode *> TParentNodeSet; + + // + // For collecting the dependent nodes of assignments, conditions, etc. + // while traversing the intermediate tree. + // + // This data structure is stack of sets. Each set contains dependency graph + // parent nodes. + // + class TNodeSetStack + { + public: + TNodeSetStack() {}; + ~TNodeSetStack() { clear(); } + + // This should only be called after a pushSet. + // Returns NULL if the top set is empty. + TParentNodeSet *getTopSet() const + { + ASSERT(!mNodeSets.empty()); + TParentNodeSet *topSet = mNodeSets.top(); + return !topSet->empty() ? topSet : NULL; + } + + void pushSet() { mNodeSets.push(new TParentNodeSet()); } + void popSet() + { + ASSERT(!mNodeSets.empty()); + delete mNodeSets.top(); + mNodeSets.pop(); + } + + // Pops the top set and adds its contents to the new top set. + // This should only be called after a pushSet. + // If there is no set below the top set, the top set is just deleted. + void popSetIntoNext() + { + ASSERT(!mNodeSets.empty()); + TParentNodeSet *oldTopSet = mNodeSets.top(); + mNodeSets.pop(); + + if (!mNodeSets.empty()) + { + TParentNodeSet *newTopSet = mNodeSets.top(); + newTopSet->insert(oldTopSet->begin(), oldTopSet->end()); + } + + delete oldTopSet; + } + + // Does nothing if there is no top set. + // This can be called when there is no top set if we are visiting + // symbols that are not under an assignment or condition. + // We don't need to track those symbols. + void insertIntoTopSet(TGraphParentNode *node) + { + if (mNodeSets.empty()) + return; + + mNodeSets.top()->insert(node); + } + + void clear() + { + while (!mNodeSets.empty()) + popSet(); + } + + private: + typedef std::stack<TParentNodeSet *> TParentNodeSetStack; + + TParentNodeSetStack mNodeSets; + }; + + // + // An instance of this class pushes a new node set when instantiated. + // When the instance goes out of scope, it and pops the node set. + // + class TNodeSetMaintainer : angle::NonCopyable + { + public: + TNodeSetMaintainer(TDependencyGraphBuilder *factory) + : mSets(factory->mNodeSets) + { + mSets.pushSet(); + } + ~TNodeSetMaintainer() { mSets.popSet(); } + protected: + TNodeSetStack &mSets; + }; + + // + // An instance of this class pushes a new node set when instantiated. + // When the instance goes out of scope, it and pops the top node set and adds + // its contents to the new top node set. + // + class TNodeSetPropagatingMaintainer : angle::NonCopyable + { + public: + TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory) + : mSets(factory->mNodeSets) + { + mSets.pushSet(); + } + ~TNodeSetPropagatingMaintainer() { mSets.popSetIntoNext(); } + protected: + TNodeSetStack &mSets; + }; + + // + // An instance of this class keeps track of the leftmost symbol while we're + // exploring an assignment. + // It will push the placeholder symbol kLeftSubtree when instantiated under a + // left subtree, and kRightSubtree under a right subtree. + // When it goes out of scope, it will pop the leftmost symbol at the top of the + // scope. + // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with + // a real symbol. + // kRightSubtree will never be replaced by a real symbol because we are tracking + // the leftmost symbol. + // + class TLeftmostSymbolMaintainer : angle::NonCopyable + { + public: + TLeftmostSymbolMaintainer( + TDependencyGraphBuilder *factory, TGraphSymbol &subtree) + : mLeftmostSymbols(factory->mLeftmostSymbols) + { + mNeedsPlaceholderSymbol = + mLeftmostSymbols.empty() || mLeftmostSymbols.top() != &subtree; + if (mNeedsPlaceholderSymbol) + mLeftmostSymbols.push(&subtree); + } + + ~TLeftmostSymbolMaintainer() + { + if (mNeedsPlaceholderSymbol) + mLeftmostSymbols.pop(); + } + + protected: + TSymbolStack& mLeftmostSymbols; + bool mNeedsPlaceholderSymbol; + }; + + TDependencyGraphBuilder(TDependencyGraph *graph) + : TIntermTraverser(true, false, false), + mLeftSubtree(NULL), + mRightSubtree(NULL), + mGraph(graph) {} + void build(TIntermNode *intermNode) { intermNode->traverse(this); } + + void connectMultipleNodesToSingleNode( + TParentNodeSet *nodes, TGraphNode *node) const; + + void visitAssignment(TIntermBinary *); + void visitLogicalOp(TIntermBinary *); + void visitBinaryChildren(TIntermBinary *); + void visitFunctionDefinition(TIntermAggregate *); + void visitFunctionCall(TIntermAggregate *intermFunctionCall); + void visitAggregateChildren(TIntermAggregate *); + + TGraphSymbol mLeftSubtree; + TGraphSymbol mRightSubtree; + + TDependencyGraph *mGraph; + TNodeSetStack mNodeSets; + TSymbolStack mLeftmostSymbols; +}; + +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp new file mode 100644 index 000000000..32a2f3014 --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraphOutput.h" + +void TDependencyGraphOutput::outputIndentation() +{ + for (int i = 0; i < getDepth(); ++i) + mSink << " "; +} + +void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter) +{ + outputIndentation(); + mSink << "argument " << parameter->getArgumentNumber() << " of call to " + << parameter->getIntermFunctionCall()->getName() << "\n"; +} + +void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall) +{ + outputIndentation(); + mSink << "function call " << functionCall->getIntermFunctionCall()->getName() << "\n"; +} + +void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol) +{ + outputIndentation(); + mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: " + << symbol->getIntermSymbol()->getId() << ")\n"; +} + +void TDependencyGraphOutput::visitSelection(TGraphSelection* selection) +{ + outputIndentation(); + mSink << "selection\n"; +} + +void TDependencyGraphOutput::visitLoop(TGraphLoop* loop) +{ + outputIndentation(); + mSink << "loop condition\n"; +} + +void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp) +{ + outputIndentation(); + mSink << "logical " << logicalOp->getOpString() << "\n"; +} + +void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph) +{ + mSink << "\n"; + + for (auto symbol : graph.allNodes()) + { + mSink << "--- Dependency graph spanning tree ---\n"; + clearVisited(); + symbol->traverse(this); + mSink << "\n"; + } +} diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h new file mode 100644 index 000000000..b201e0a67 --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h @@ -0,0 +1,31 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ + +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/InfoSink.h" + +class TDependencyGraphOutput : public TDependencyGraphTraverser +{ + public: + TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {} + void visitSymbol(TGraphSymbol* symbol) override; + void visitArgument(TGraphArgument* parameter) override; + void visitFunctionCall(TGraphFunctionCall* functionCall) override; + void visitSelection(TGraphSelection* selection) override; + void visitLoop(TGraphLoop* loop) override; + void visitLogicalOp(TGraphLogicalOp* logicalOp) override; + + void outputAllSpanningTrees(TDependencyGraph& graph); + private: + void outputIndentation(); + + TInfoSinkBase& mSink; +}; + +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ diff --git a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp new file mode 100644 index 000000000..197fde97e --- /dev/null +++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/depgraph/DependencyGraph.h" + +// These methods do a breadth-first traversal through the graph and mark visited nodes. + +void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->markVisited(this); +} + +void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser) +{ + TGraphNode::traverse(graphTraverser); + + graphTraverser->incrementDepth(); + + // Visit the parent node's children. + for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin(); + iter != mDependentNodes.end(); + ++iter) + { + TGraphNode* node = *iter; + if (!graphTraverser->isVisited(node)) + node->traverse(graphTraverser); + } + + graphTraverser->decrementDepth(); +} + +void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitArgument(this); + TGraphParentNode::traverse(graphTraverser); +} + +void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitFunctionCall(this); + TGraphParentNode::traverse(graphTraverser); +} + +void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitSymbol(this); + TGraphParentNode::traverse(graphTraverser); +} + +void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitSelection(this); + TGraphNode::traverse(graphTraverser); +} + +void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitLoop(this); + TGraphNode::traverse(graphTraverser); +} + +void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser) +{ + graphTraverser->visitLogicalOp(this); + TGraphNode::traverse(graphTraverser); +} diff --git a/gfx/angle/src/compiler/translator/glslang.h b/gfx/angle/src/compiler/translator/glslang.h index aaa5dd119..0555e96d4 100755 --- a/gfx/angle/src/compiler/translator/glslang.h +++ b/gfx/angle/src/compiler/translator/glslang.h @@ -7,18 +7,14 @@ #ifndef COMPILER_TRANSLATOR_GLSLANG_H_ #define COMPILER_TRANSLATOR_GLSLANG_H_ -namespace sh -{ class TParseContext; -} - -extern int glslang_initialize(sh::TParseContext *context); -extern int glslang_finalize(sh::TParseContext *context); +extern int glslang_initialize(TParseContext* context); +extern int glslang_finalize(TParseContext* context); extern int glslang_scan(size_t count, - const char *const string[], + const char* const string[], const int length[], - sh::TParseContext *context); -extern int glslang_parse(sh::TParseContext *context); + TParseContext* context); +extern int glslang_parse(TParseContext* context); #endif // COMPILER_TRANSLATOR_GLSLANG_H_ diff --git a/gfx/angle/src/compiler/translator/glslang.l b/gfx/angle/src/compiler/translator/glslang.l index a30f2c33e..7fe289302 100755 --- a/gfx/angle/src/compiler/translator/glslang.l +++ b/gfx/angle/src/compiler/translator/glslang.l @@ -22,8 +22,6 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). // This file is auto-generated by generate_parser.sh. DO NOT EDIT! -/* clang-format off */ - // Ignore errors in auto-generated code. #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" @@ -46,9 +44,6 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #include "compiler/preprocessor/Token.h" #include "compiler/translator/util.h" #include "compiler/translator/length_limits.h" - -using namespace sh; - #include "glslang_tab.h" /* windows only pragma */ @@ -76,8 +71,6 @@ static int reserved_word(yyscan_t yyscanner); static int ES2_reserved_ES3_keyword(TParseContext *context, int token); static int ES2_keyword_ES3_reserved(TParseContext *context, int token); static int ES2_ident_ES3_keyword(TParseContext *context, int token); -static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); -static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); static int uint_constant(TParseContext *context); static int int_constant(TParseContext *context); static int float_constant(yyscan_t yyscanner); @@ -194,25 +187,11 @@ O [0-7] "layout" { return ES2_ident_ES3_keyword(context, LAYOUT); } -"image2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); } -"iimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); } -"uimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); } -"image2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); } -"iimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); } -"uimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); } -"image3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); } -"uimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); } -"iimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); } -"iimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); } -"uimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); } -"imageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); } -"readonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); } -"writeonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); } -"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); } -"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); } -"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); } - /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ +"coherent" | +"restrict" | +"readonly" | +"writeonly" | "resource" | "atomic_uint" | "noperspective" | @@ -225,11 +204,23 @@ O [0-7] "filter" | "image1D" | +"image2D" | +"image3D" | +"imageCube" | "iimage1D" | +"iimage2D" | +"iimage3D" | +"iimageCube" | "uimage1D" | +"uimage2D" | +"uimage3D" | +"uimageCube" | "image1DArray" | +"image2DArray" | "iimage1DArray" | +"iimage2DArray" | "uimage1DArray" | +"uimage2DArray" | "image1DShadow" | "image2DShadow" | "image1DArrayShadow" | @@ -287,6 +278,7 @@ O [0-7] "inline" | "noinline" | +"volatile" | "public" | "static" | "extern" | @@ -471,24 +463,6 @@ int ES2_keyword_ES3_reserved(TParseContext *context, int token) return token; } -int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - else if (context->getShaderVersion() == 300) - { - return reserved_word(yyscanner); - } - - return token; -} - int ES2_ident_ES3_keyword(TParseContext *context, int token) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); @@ -504,18 +478,6 @@ int ES2_ident_ES3_keyword(TParseContext *context, int token) return token; } -int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 310) - { - return reserved_word(yyscanner); - } - - return token; -} - int uint_constant(TParseContext *context) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); @@ -617,7 +579,8 @@ int glslang_scan(size_t count, const char* const string[], const int length[], if (context->getFragmentPrecisionHigh()) preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); + preprocessor->setMaxTokenSize(GetGlobalMaxTokenSize(context->getShaderSpec())); return 0; } + diff --git a/gfx/angle/src/compiler/translator/glslang.y b/gfx/angle/src/compiler/translator/glslang.y index c15dd9d6e..8604d8eb6 100755 --- a/gfx/angle/src/compiler/translator/glslang.y +++ b/gfx/angle/src/compiler/translator/glslang.y @@ -46,8 +46,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #define YYENABLE_NLS 0 -using namespace sh; - %} %expect 1 /* One shift reduce conflict because of if | else */ %parse-param {TParseContext* context} @@ -74,27 +72,22 @@ using namespace sh; struct { TOperator op; union { - TIntermNode *intermNode; + TIntermNode* intermNode; TIntermNodePair nodePair; - TIntermTyped *intermTypedNode; - TIntermAggregate *intermAggregate; - TIntermBlock *intermBlock; - TIntermDeclaration *intermDeclaration; - TIntermSwitch *intermSwitch; - TIntermCase *intermCase; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + TIntermSwitch* intermSwitch; + TIntermCase* intermCase; }; union { - TTypeSpecifierNonArray typeSpecifierNonArray; TPublicType type; TPrecision precision; TLayoutQualifier layoutQualifier; TQualifier qualifier; - TFunction *function; + TFunction* function; TParameter param; - TField *field; - TFieldList *fieldList; - TQualifierWrapperBase *qualifierWrapper; - TTypeQualifierBuilder *typeQualifierBuilder; + TField* field; + TFieldList* fieldList; }; } interm; } @@ -169,14 +162,11 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons %token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING %token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3 %token <lex> CENTROID FLAT SMOOTH -%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE %token <lex> STRUCT VOID_TYPE WHILE %token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY %token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY %token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY %token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW -%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY -%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE %token <lex> LAYOUT %token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT @@ -202,9 +192,9 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons %type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression %type <interm.intermTypedNode> function_call initializer condition conditionopt -%type <interm.intermBlock> translation_unit -%type <interm.intermNode> function_definition statement simple_statement -%type <interm.intermBlock> statement_list compound_statement compound_statement_no_new_scope +%type <interm.intermNode> translation_unit function_definition +%type <interm.intermNode> statement simple_statement +%type <interm.intermAggregate> statement_list compound_statement compound_statement_no_new_scope %type <interm.intermNode> declaration_statement selection_statement expression_statement %type <interm.intermNode> declaration external_declaration %type <interm.intermNode> for_init_statement @@ -215,18 +205,13 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons %type <interm> single_declaration init_declarator_list %type <interm> parameter_declaration parameter_declarator parameter_type_specifier -%type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id - -%type <interm.type> fully_specified_type type_specifier +%type <interm.qualifier> parameter_qualifier parameter_type_qualifier +%type <interm.layoutQualifier> layout_qualifier layout_qualifier_id_list layout_qualifier_id %type <interm.precision> precision_qualifier -%type <interm.layoutQualifier> layout_qualifier -%type <interm.qualifier> interpolation_qualifier -%type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier -%type <interm.typeQualifierBuilder> type_qualifier - -%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier -%type <interm.type> type_specifier_no_prec +%type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier +%type <interm.type> type_specifier_no_prec type_specifier_nonarray +%type <interm.type> struct_specifier %type <interm.field> struct_declarator %type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list %type <interm.function> function_header function_declarator function_identifier @@ -358,7 +343,7 @@ function_call_header_with_parameters const TType *type = new TType($2->getType()); $1->addParameter(TConstParameter(type)); $$.function = $1; - $$.nodePair.node1 = TIntermediate::MakeAggregate($2, @2); + $$.nodePair.node1 = context->intermediate.makeAggregate($2, @2); } | function_call_header_with_parameters COMMA assignment_expression { const TType *type = new TType($3->getType()); @@ -609,43 +594,41 @@ declaration $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1); } | init_declarator_list SEMICOLON { - $$ = $1.intermDeclaration; + TIntermAggregate *aggNode = $1.intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + $$ = aggNode; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) { context->error(@1, "precision is not supported in fragment shader", "highp"); } if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { - context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.getBasicType())); + context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type)); } $$ = 0; } | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, NULL, @$, NULL, @$); + ES3_OR_NEWER(getQualifierString($1.qualifier), @1, "interface blocks"); + $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, NULL, @$, NULL, @$); } | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, NULL, @$); + ES3_OR_NEWER(getQualifierString($1.qualifier), @1, "interface blocks"); + $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, NULL, @$); } | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON { - ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks"); - $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, $7, @6); + ES3_OR_NEWER(getQualifierString($1.qualifier), @1, "interface blocks"); + $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, $7, @6); } | type_qualifier SEMICOLON { - context->parseGlobalLayoutQualifier(*$1); + context->parseGlobalLayoutQualifier($1); $$ = 0; } - | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant - { - $$ = context->parseInvariantDeclaration(*$1, @2, $2.string, $2.symbol); - } ; function_prototype : function_declarator RIGHT_PAREN { $$.function = context->parseFunctionDeclarator(@2, $1); - context->exitFunctionDeclaration(); } ; @@ -692,14 +675,13 @@ function_header $$ = context->parseFunctionHeader($1, $2.string, @2); context->symbolTable.push(); - context->enterFunctionDeclaration(); } ; parameter_declarator // Type + name : type_specifier identifier { - if ($1.getBasicType() == EbtVoid) { + if ($1.type == EbtVoid) { context->error(@2, "illegal use of type 'void'", $2.string->c_str()); } context->checkIsNotReserved(@2, *$2.string); @@ -731,21 +713,41 @@ parameter_declaration // // Type + name // - : type_qualifier parameter_declarator { + : parameter_type_qualifier parameter_qualifier parameter_declarator { + $$ = $3; + context->checkIsParameterQualifierValid(@3, $1, $2, $$.param.type); + } + | parameter_qualifier parameter_declarator { $$ = $2; - context->checkIsParameterQualifierValid(@2, *$1, $2.param.type); + context->checkOutParameterIsNotSampler(@2, $1, *$2.param.type); + context->checkIsParameterQualifierValid(@2, EvqTemporary, $1, $$.param.type); } - | parameter_declarator { - $$ = $1; - $$.param.type->setQualifier(EvqIn); + // + // Only type + // + | parameter_type_qualifier parameter_qualifier parameter_type_specifier { + $$ = $3; + context->checkIsParameterQualifierValid(@3, $1, $2, $$.param.type); } - | type_qualifier parameter_type_specifier { + | parameter_qualifier parameter_type_specifier { $$ = $2; - context->checkIsParameterQualifierValid(@2, *$1, $2.param.type); + context->checkOutParameterIsNotSampler(@2, $1, *$2.param.type); + context->checkIsParameterQualifierValid(@2, EvqTemporary, $1, $$.param.type); } - | parameter_type_specifier { - $$ = $1; - $$.param.type->setQualifier(EvqIn); + ; + +parameter_qualifier + : /* empty */ { + $$ = EvqIn; + } + | IN_QUAL { + $$ = EvqIn; + } + | OUT_QUAL { + $$ = EvqOut; + } + | INOUT_QUAL { + $$ = EvqInOut; } ; @@ -762,209 +764,209 @@ init_declarator_list } | init_declarator_list COMMA identifier { $$ = $1; - context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration); + $$.intermAggregate = context->parseDeclarator($$.type, $1.intermAggregate, @3, *$3.string); } | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { $$ = $1; - context->parseArrayDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration); + $$.intermAggregate = context->parseArrayDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5); } | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { ES3_OR_NEWER("[]", @3, "implicitly sized array"); $$ = $1; - context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, nullptr, @6, $7, $$.intermDeclaration); + $$.intermAggregate = context->parseArrayInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, nullptr, @6, $7); } | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { ES3_OR_NEWER("=", @7, "first-class arrays (array initializer)"); $$ = $1; - context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, $5, @7, $8, $$.intermDeclaration); + $$.intermAggregate = context->parseArrayInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5, @7, $8); } | init_declarator_list COMMA identifier EQUAL initializer { $$ = $1; - context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration); + $$.intermAggregate = context->parseInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5); } ; single_declaration : fully_specified_type { $$.type = $1; - $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, ""); + $$.intermAggregate = context->parseSingleDeclaration($$.type, @1, ""); } | fully_specified_type identifier { $$.type = $1; - $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string); + $$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string); } | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4); + $$.intermAggregate = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4); } | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { ES3_OR_NEWER("[]", @3, "implicitly sized array"); $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, nullptr, @5, $6); + $$.intermAggregate = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, nullptr, @5, $6); } | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { ES3_OR_NEWER("=", @6, "first-class arrays (array initializer)"); $$.type = $1; - $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, $4, @6, $7); + $$.intermAggregate = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, $4, @6, $7); } | fully_specified_type identifier EQUAL initializer { $$.type = $1; - $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); + $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); + } + | INVARIANT IDENTIFIER { + // $$.type is not used in invariant declarations. + $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol); } ; fully_specified_type : type_specifier { - context->addFullySpecifiedType(&$1); $$ = $1; + + if ($1.array) { + ES3_OR_NEWER("[]", @1, "first-class-array"); + if (context->getShaderVersion() != 300) { + $1.clearArrayness(); + } + } } - | type_qualifier type_specifier { - $$ = context->addFullySpecifiedType(*$1, $2); + | type_qualifier type_specifier { + $$ = context->addFullySpecifiedType($1.qualifier, $1.invariant, $1.layoutQualifier, $2); } ; interpolation_qualifier : SMOOTH { - $$ = EvqSmooth; + $$.qualifier = EvqSmooth; } | FLAT { - $$ = EvqFlat; + $$.qualifier = EvqFlat; } ; -type_qualifier - : single_type_qualifier { - $$ = context->createTypeQualifierBuilder(@1); - $$->appendQualifier($1); - } - | type_qualifier single_type_qualifier { - $$ = $1; - $$->appendQualifier($2); - } - ; - -invariant_qualifier - : INVARIANT { - // empty +parameter_type_qualifier + : CONST_QUAL { + $$ = EvqConst; } ; -single_type_qualifier - : storage_qualifier { - context->checkLocalVariableConstStorageQualifier(*$1); - $$ = $1; - } - | layout_qualifier { - context->checkIsAtGlobalLevel(@1, "layout"); - $$ = new TLayoutQualifierWrapper($1, @1); - } - | precision_qualifier { - $$ = new TPrecisionQualifierWrapper($1, @1); - } - | interpolation_qualifier { - $$ = new TInterpolationQualifierWrapper($1, @1); - } - | invariant_qualifier { - context->checkIsAtGlobalLevel(@1, "invariant"); - $$ = new TInvariantQualifierWrapper(@1); - } - ; - - -storage_qualifier - : - ATTRIBUTE { +type_qualifier + : ATTRIBUTE { VERTEX_ONLY("attribute", @1); ES2_ONLY("attribute", @1); context->checkIsAtGlobalLevel(@1, "attribute"); - $$ = new TStorageQualifierWrapper(EvqAttribute, @1); + $$.setBasic(EbtVoid, EvqAttribute, @1); } | VARYING { ES2_ONLY("varying", @1); context->checkIsAtGlobalLevel(@1, "varying"); if (context->getShaderType() == GL_VERTEX_SHADER) - $$ = new TStorageQualifierWrapper(EvqVaryingOut, @1); + $$.setBasic(EbtVoid, EvqVaryingOut, @1); else - $$ = new TStorageQualifierWrapper(EvqVaryingIn, @1); + $$.setBasic(EbtVoid, EvqVaryingIn, @1); } - | CONST_QUAL { - $$ = new TStorageQualifierWrapper(EvqConst, @1); + | INVARIANT VARYING { + ES2_ONLY("varying", @1); + context->checkIsAtGlobalLevel(@1, "invariant varying"); + if (context->getShaderType() == GL_VERTEX_SHADER) + $$.setBasic(EbtVoid, EvqVaryingOut, @1); + else + $$.setBasic(EbtVoid, EvqVaryingIn, @1); + $$.invariant = true; } - | IN_QUAL { - if (context->declaringFunction()) + | storage_qualifier { + if ($1.qualifier != EvqConst && !context->symbolTable.atGlobalLevel()) { - $$ = new TStorageQualifierWrapper(EvqIn, @1); + context->error(@1, "Local variables can only use the const storage qualifier.", getQualifierString($1.qualifier)); } - else if (context->getShaderType() == GL_FRAGMENT_SHADER) + $$.setBasic(EbtVoid, $1.qualifier, @1); + } + | interpolation_qualifier storage_qualifier { + $$ = context->joinInterpolationQualifiers(@1, $1.qualifier, @2, $2.qualifier); + } + | interpolation_qualifier { + context->error(@1, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString($1.qualifier)); + + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtVoid, qual, @1); + } + | layout_qualifier { + $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.layoutQualifier = $1; + } + | layout_qualifier storage_qualifier { + $$.setBasic(EbtVoid, $2.qualifier, @2); + $$.layoutQualifier = $1; + } + | INVARIANT storage_qualifier { + context->checkInvariantIsOutVariableES3($2.qualifier, @1); + $$.setBasic(EbtVoid, $2.qualifier, @2); + $$.invariant = true; + } + | INVARIANT interpolation_qualifier storage_qualifier { + context->checkInvariantIsOutVariableES3($3.qualifier, @1); + $$ = context->joinInterpolationQualifiers(@2, $2.qualifier, @3, $3.qualifier); + $$.invariant = true; + } + ; + +storage_qualifier + : CONST_QUAL { + $$.qualifier = EvqConst; + } + | IN_QUAL { + if (context->getShaderType() == GL_FRAGMENT_SHADER) { ES3_OR_NEWER("in", @1, "storage qualifier"); - $$ = new TStorageQualifierWrapper(EvqFragmentIn, @1); + $$.qualifier = EvqFragmentIn; } else if (context->getShaderType() == GL_VERTEX_SHADER) { ES3_OR_NEWER("in", @1, "storage qualifier"); - $$ = new TStorageQualifierWrapper(EvqVertexIn, @1); + $$.qualifier = EvqVertexIn; } else { - $$ = new TStorageQualifierWrapper(EvqComputeIn, @1); + $$.qualifier = EvqComputeIn; } } | OUT_QUAL { - if (context->declaringFunction()) - { - $$ = new TStorageQualifierWrapper(EvqOut, @1); - } - else - { - ES3_OR_NEWER("out", @1, "storage qualifier"); - NON_COMPUTE_ONLY("out", @1); - if (context->getShaderType() == GL_FRAGMENT_SHADER) - { - $$ = new TStorageQualifierWrapper(EvqFragmentOut, @1); - } - else - { - $$ = new TStorageQualifierWrapper(EvqVertexOut, @1); - } - } + ES3_OR_NEWER("out", @1, "storage qualifier"); + NON_COMPUTE_ONLY("out", @1); + $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; } - | INOUT_QUAL { - if (!context->declaringFunction()) - { - context->error(@1, "invalid inout qualifier", "'inout' can be only used with function parameters"); - } - $$ = new TStorageQualifierWrapper(EvqInOut, @1); + | CENTROID IN_QUAL { + ES3_OR_NEWER("centroid in", @1, "storage qualifier"); + FRAG_ONLY("centroid in", @1); + $$.qualifier = EvqCentroidIn; } - | CENTROID { - ES3_OR_NEWER("centroid", @1, "storage qualifier"); - $$ = new TStorageQualifierWrapper(EvqCentroid, @1); + | CENTROID OUT_QUAL { + ES3_OR_NEWER("centroid out", @1, "storage qualifier"); + VERTEX_ONLY("centroid out", @1); + $$.qualifier = EvqCentroidOut; } | UNIFORM { context->checkIsAtGlobalLevel(@1, "uniform"); - $$ = new TStorageQualifierWrapper(EvqUniform, @1); - } - | READONLY { - $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1); - } - | WRITEONLY { - $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1); - } - | COHERENT { - $$ = new TMemoryQualifierWrapper(EvqCoherent, @1); - } - | RESTRICT { - $$ = new TMemoryQualifierWrapper(EvqRestrict, @1); - } - | VOLATILE { - $$ = new TMemoryQualifierWrapper(EvqVolatile, @1); + $$.qualifier = EvqUniform; } ; type_specifier : type_specifier_no_prec { $$ = $1; - $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType()); + + if ($$.precision == EbpUndefined) { + $$.precision = context->symbolTable.getDefaultPrecision($1.type); + context->checkPrecisionSpecified(@1, $$.precision, $1.type); + } + } + | precision_qualifier type_specifier_no_prec { + $$ = $2; + $$.precision = $1; + + if (!SupportsPrecision($2.type)) { + context->error(@1, "illegal type for precision qualifier", getBasicString($2.type)); + } } ; @@ -1010,16 +1012,17 @@ layout_qualifier_id type_specifier_no_prec : type_specifier_nonarray { - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); + $$ = $1; } | type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET { ES3_OR_NEWER("[]", @2, "implicitly sized array"); - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); + $$ = $1; $$.setArraySize(0); } | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { - $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - if (context->checkIsValidTypeForArray(@2, $$)) + $$ = $1; + + if (context->checkIsValidTypeForArray(@2, $1)) { unsigned int size = context->checkIsValidArraySize(@2, $3); $$.setArraySize(size); @@ -1029,200 +1032,208 @@ type_specifier_no_prec type_specifier_nonarray : VOID_TYPE { - $$.initialize(EbtVoid, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtVoid, qual, @1); } | FLOAT_TYPE { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); } | INT_TYPE { - $$.initialize(EbtInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); } | UINT_TYPE { - $$.initialize(EbtUInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); } | BOOL_TYPE { - $$.initialize(EbtBool, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); } | VEC2 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2); } | VEC3 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3); } | VEC4 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4); } | BVEC2 { - $$.initialize(EbtBool, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(2); } | BVEC3 { - $$.initialize(EbtBool, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(3); } | BVEC4 { - $$.initialize(EbtBool, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(4); } | IVEC2 { - $$.initialize(EbtInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(2); } | IVEC3 { - $$.initialize(EbtInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(3); } | IVEC4 { - $$.initialize(EbtInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(4); } | UVEC2 { - $$.initialize(EbtUInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); $$.setAggregate(2); } | UVEC3 { - $$.initialize(EbtUInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); $$.setAggregate(3); } | UVEC4 { - $$.initialize(EbtUInt, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); $$.setAggregate(4); } | MATRIX2 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(2, 2); } | MATRIX3 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(3, 3); } | MATRIX4 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(4, 4); } | MATRIX2x3 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(2, 3); } | MATRIX3x2 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(3, 2); } | MATRIX2x4 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(2, 4); } | MATRIX4x2 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(4, 2); } | MATRIX3x4 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(3, 4); } | MATRIX4x3 { - $$.initialize(EbtFloat, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); $$.setMatrix(4, 3); } | SAMPLER2D { - $$.initialize(EbtSampler2D, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2D, qual, @1); } | SAMPLER3D { - $$.initialize(EbtSampler3D, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler3D, qual, @1); } | SAMPLERCUBE { - $$.initialize(EbtSamplerCube, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerCube, qual, @1); } | SAMPLER2DARRAY { - $$.initialize(EbtSampler2DArray, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DArray, qual, @1); } | ISAMPLER2D { - $$.initialize(EbtISampler2D, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISampler2D, qual, @1); } | ISAMPLER3D { - $$.initialize(EbtISampler3D, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISampler3D, qual, @1); } | ISAMPLERCUBE { - $$.initialize(EbtISamplerCube, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISamplerCube, qual, @1); } | ISAMPLER2DARRAY { - $$.initialize(EbtISampler2DArray, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISampler2DArray, qual, @1); } | USAMPLER2D { - $$.initialize(EbtUSampler2D, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSampler2D, qual, @1); } | USAMPLER3D { - $$.initialize(EbtUSampler3D, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSampler3D, qual, @1); } | USAMPLERCUBE { - $$.initialize(EbtUSamplerCube, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSamplerCube, qual, @1); } | USAMPLER2DARRAY { - $$.initialize(EbtUSampler2DArray, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSampler2DArray, qual, @1); } | SAMPLER2DSHADOW { - $$.initialize(EbtSampler2DShadow, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DShadow, qual, @1); } | SAMPLERCUBESHADOW { - $$.initialize(EbtSamplerCubeShadow, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerCubeShadow, qual, @1); } | SAMPLER2DARRAYSHADOW { - $$.initialize(EbtSampler2DArrayShadow, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DArrayShadow, qual, @1); } | SAMPLER_EXTERNAL_OES { if (!context->supportsExtension("GL_OES_EGL_image_external") && !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) { context->error(@1, "unsupported type", "samplerExternalOES"); } - $$.initialize(EbtSamplerExternalOES, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerExternalOES, qual, @1); } | SAMPLER2DRECT { if (!context->supportsExtension("GL_ARB_texture_rectangle")) { context->error(@1, "unsupported type", "sampler2DRect"); } - $$.initialize(EbtSampler2DRect, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DRect, qual, @1); } | struct_specifier { $$ = $1; - } - | IMAGE2D { - $$.initialize(EbtImage2D, @1); - } - | IIMAGE2D { - $$.initialize(EbtIImage2D, @1); - } - | UIMAGE2D { - $$.initialize(EbtUImage2D, @1); - } - | IMAGE3D { - $$.initialize(EbtImage3D, @1); - } - | IIMAGE3D { - $$.initialize(EbtIImage3D, @1); - } - | UIMAGE3D { - $$.initialize(EbtUImage3D, @1); - } - | IMAGE2DARRAY { - $$.initialize(EbtImage2DArray, @1); - } - | IIMAGE2DARRAY { - $$.initialize(EbtIImage2DArray, @1); - } - | UIMAGE2DARRAY { - $$.initialize(EbtUImage2DArray, @1); - } - | IMAGECUBE { - $$.initialize(EbtImageCube, @1); - } - | IIMAGECUBE { - $$.initialize(EbtIImageCube, @1); - } - | UIMAGECUBE { - $$.initialize(EbtUImageCube, @1); + $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } | TYPE_NAME { // @@ -1230,7 +1241,8 @@ type_specifier_nonarray // type. // TType& structure = static_cast<TVariable*>($1.symbol)->getType(); - $$.initialize(EbtStruct, @1); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtStruct, qual, @1); $$.userDef = &structure; } ; @@ -1268,7 +1280,9 @@ struct_declaration } | type_qualifier type_specifier struct_declarator_list SEMICOLON { // ES3 Only, but errors should be handled elsewhere - $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3); + $2.qualifier = $1.qualifier; + $2.layoutQualifier = $1.layoutQualifier; + $$ = context->addStructDeclaratorList($2, $3); } ; @@ -1329,6 +1343,7 @@ compound_statement : LEFT_BRACE RIGHT_BRACE { $$ = 0; } | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { if ($3 != 0) { + $3->setOp(EOpSequence); $3->setLine(@$); } $$ = $3; @@ -1352,6 +1367,7 @@ compound_statement_no_new_scope } | LEFT_BRACE statement_list RIGHT_BRACE { if ($2) { + $2->setOp(EOpSequence); $2->setLine(@$); } $$ = $2; @@ -1360,13 +1376,10 @@ compound_statement_no_new_scope statement_list : statement { - $$ = new TIntermBlock(); - $$->setLine(@$); - $$->appendStatement($1); + $$ = context->intermediate.makeAggregate($1, @$); } | statement_list statement { - $$ = $1; - $$->appendStatement($2); + $$ = context->intermediate.growAggregate($1, $2, @$); } ; @@ -1378,7 +1391,7 @@ expression_statement selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { context->checkIsScalarBool(@1, $3); - $$ = context->intermediate.addIfElse($3, $5, @1); + $$ = context->intermediate.addSelection($3, $5, @1); } ; @@ -1416,10 +1429,10 @@ condition context->checkIsScalarBool($1->getLine(), $1); } | fully_specified_type identifier EQUAL initializer { - TIntermBinary *initNode = nullptr; + TIntermNode *intermNode; context->checkIsScalarBool(@2, $1); - if (!context->executeInitializer(@2, *$2.string, $1, $4, &initNode)) + if (!context->executeInitializer(@2, *$2.string, $1, $4, &intermNode)) $$ = $4; else { $$ = 0; @@ -1498,13 +1511,12 @@ jump_statement translation_unit : external_declaration { - $$ = new TIntermBlock(); - $$->setLine(@$); - $$->appendStatement($1); + $$ = $1; context->setTreeRoot($$); } | translation_unit external_declaration { - $$->appendStatement($2); + $$ = context->intermediate.growAggregate($1, $2, @$); + context->setTreeRoot($$); } ; @@ -1519,7 +1531,7 @@ external_declaration function_definition : function_prototype { - context->parseFunctionDefinitionHeader(@1, &($1.function), &$1.intermAggregate); + context->parseFunctionPrototype(@1, $1.function, &$1.intermAggregate); } compound_statement_no_new_scope { $$ = context->addFunctionDefinition(*($1.function), $1.intermAggregate, $3, @1); diff --git a/gfx/angle/src/compiler/translator/glslang_lex.cpp b/gfx/angle/src/compiler/translator/glslang_lex.cpp index 2dcc1bc0f..8ad7b1464 100755 --- a/gfx/angle/src/compiler/translator/glslang_lex.cpp +++ b/gfx/angle/src/compiler/translator/glslang_lex.cpp @@ -1,3 +1,4 @@ +#line 17 "./glslang.l" // // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -6,8 +7,6 @@ // This file is auto-generated by generate_parser.sh. DO NOT EDIT! -/* clang-format off */ - // Ignore errors in auto-generated code. #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" @@ -25,7 +24,7 @@ -#line 30 "./glslang_lex.cpp" +#line 28 "./glslang_lex.cpp" #define YY_INT_ALIGNED short int @@ -221,7 +220,7 @@ typedef size_t yy_size_t; #define YY_LESS_LINENO(n) \ do { \ yy_size_t yyl;\ - for ( yyl = n; yyl < static_cast<yy_site_t>(yyleng); ++yyl )\ + for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) @@ -396,7 +395,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); */ #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; @@ -429,7 +428,7 @@ static yyconst flex_int16_t yy_accept[820] = 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 199, 203, 235, 0, 189, 185, 0, 188, 182, - 0, 184, 178, 195, 196, 177, 137, 177, 177, 177, + 0, 184, 178, 195, 196, 177, 136, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 13, 177, 177, 177, 177, 177, 177, 177, 177, 177, @@ -441,67 +440,67 @@ static yyconst flex_int16_t yy_accept[820] = 177, 177, 177, 177, 177, 177, 177, 177, 0, 186, 0, 185, 187, 181, 177, 177, 177, 30, 177, 177, 18, 174, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 16, 140, 177, 177, 177, 177, 21, 177, - 177, 144, 155, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 16, 139, 177, 177, 177, 177, 21, 177, + 177, 143, 155, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 152, 4, 35, 36, 37, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 143, 31, 177, 177, 28, 177, + 177, 177, 177, 177, 142, 31, 177, 177, 28, 177, 177, 177, 177, 177, 177, 177, 47, 48, 49, 29, 177, 177, 177, 177, 177, 177, 10, 53, 54, 55, - 177, 138, 177, 177, 7, 177, 177, 177, 177, 164, + 177, 137, 177, 177, 7, 177, 177, 177, 177, 164, 165, 166, 177, 32, 177, 156, 26, 167, 168, 169, 2, 161, 162, 163, 177, 177, 177, 25, 159, 177, 177, 177, 50, 51, 52, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 99, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 86, 177, 177, 177, 177, 177, 177, 177, 153, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 139, 177, 177, 176, - 56, 57, 58, 177, 177, 14, 177, 104, 177, 177, - 177, 177, 102, 177, 177, 177, 154, 149, 105, 177, - 177, 177, 177, 177, 177, 145, 177, 177, 177, 78, + 177, 177, 177, 177, 177, 177, 138, 177, 177, 176, + 56, 57, 58, 177, 177, 14, 177, 91, 177, 177, + 177, 177, 89, 177, 177, 177, 154, 149, 92, 177, + 177, 177, 177, 177, 177, 144, 177, 177, 177, 78, 38, 41, 43, 42, 39, 45, 44, 46, 40, 177, - 177, 177, 177, 160, 136, 177, 177, 147, 177, 177, - 177, 34, 100, 173, 22, 148, 77, 177, 158, 17, + 177, 177, 177, 160, 135, 177, 177, 147, 177, 177, + 177, 34, 87, 173, 22, 148, 77, 177, 158, 17, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 19, 33, 177, 177, 177, 177, - 177, 177, 106, 79, 85, 177, 177, 177, 177, 177, + 177, 177, 93, 94, 95, 177, 177, 177, 177, 177, 3, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 141, 177, 177, 177, 177, 177, 8, 177, - 177, 9, 177, 177, 177, 177, 20, 93, 11, 150, - 107, 80, 87, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 146, 177, 177, 177, 91, - 96, 94, 177, 177, 177, 177, 177, 177, 177, 142, - 108, 81, 86, 177, 177, 157, 177, 95, 177, 177, + 177, 177, 140, 177, 177, 177, 177, 177, 8, 177, + 177, 9, 177, 177, 177, 177, 20, 79, 11, 150, + 97, 98, 99, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 145, 177, 177, 177, 81, + 83, 80, 177, 177, 177, 177, 177, 177, 177, 141, + 101, 102, 103, 177, 177, 157, 177, 146, 177, 177, 6, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 90, 151, 1, 177, 177, 177, 177, 177, 175, 177, + 96, 151, 1, 177, 177, 177, 177, 177, 175, 177, - 103, 5, 170, 59, 62, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 177, 177, 92, 177, - 177, 177, 177, 88, 177, 177, 177, 177, 177, 121, + 90, 5, 170, 59, 62, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 82, 177, + 177, 177, 177, 100, 177, 177, 177, 177, 177, 120, 66, 67, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 101, 177, 177, 177, 89, - 123, 70, 71, 177, 177, 97, 177, 177, 177, 177, - 177, 177, 177, 116, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 130, 177, 177, 177, 177, 60, + 177, 177, 177, 177, 177, 88, 177, 177, 177, 104, + 122, 70, 71, 177, 177, 84, 177, 177, 177, 177, + 177, 177, 177, 115, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 129, 177, 177, 177, 177, 60, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 117, 109, 177, 82, 177, 177, 177, 131, + 177, 177, 116, 105, 177, 106, 177, 177, 177, 130, 177, 177, 68, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 118, 177, 177, 132, - 177, 177, 72, 110, 83, 177, 112, 177, 113, 177, - 177, 177, 177, 177, 98, 177, 177, 177, 177, 64, - 177, 63, 127, 177, 177, 111, 84, 177, 177, 177, - 177, 177, 177, 177, 177, 177, 177, 125, 128, 119, + 177, 177, 177, 177, 177, 177, 117, 177, 177, 131, + 177, 177, 72, 107, 108, 177, 111, 177, 112, 177, + 177, 177, 177, 177, 85, 177, 177, 177, 177, 64, + 177, 63, 126, 177, 177, 109, 110, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 124, 127, 118, 177, 65, 177, 177, 177, 177, 177, 177, 177, 177, - 126, 129, 177, 177, 122, 69, 177, 177, 171, 177, - 177, 177, 74, 177, 177, 124, 73, 177, 177, 177, - 177, 177, 177, 133, 177, 177, 177, 177, 177, 177, + 125, 128, 177, 177, 121, 69, 177, 177, 171, 177, + 177, 177, 74, 177, 177, 123, 73, 177, 177, 177, + 177, 177, 177, 132, 177, 177, 177, 177, 177, 177, - 134, 177, 177, 177, 75, 177, 135, 114, 115, 177, - 177, 177, 61, 177, 177, 172, 120, 76, 0 + 133, 177, 177, 177, 75, 177, 134, 113, 114, 177, + 177, 177, 61, 177, 177, 172, 119, 76, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -1028,9 +1027,6 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #include "compiler/preprocessor/Token.h" #include "compiler/translator/util.h" #include "compiler/translator/length_limits.h" - -using namespace sh; - #include "glslang_tab.h" /* windows only pragma */ @@ -1058,8 +1054,6 @@ static int reserved_word(yyscan_t yyscanner); static int ES2_reserved_ES3_keyword(TParseContext *context, int token); static int ES2_keyword_ES3_reserved(TParseContext *context, int token); static int ES2_ident_ES3_keyword(TParseContext *context, int token); -static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); -static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token); static int uint_constant(TParseContext *context); static int int_constant(TParseContext *context); static int float_constant(yyscan_t yyscanner); @@ -1374,7 +1368,7 @@ yy_find_action: if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { yy_size_t yyl; - for ( yyl = 0; yyl < static_cast<yy_size_t>(yyleng); ++yyl ) + for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) do{ yylineno++; @@ -1706,75 +1700,24 @@ case 78: YY_RULE_SETUP { return ES2_ident_ES3_keyword(context, LAYOUT); } YY_BREAK +/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ case 79: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); } - YY_BREAK case 80: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); } - YY_BREAK case 81: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); } - YY_BREAK case 82: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); } - YY_BREAK case 83: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); } - YY_BREAK case 84: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); } - YY_BREAK case 85: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); } - YY_BREAK case 86: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); } - YY_BREAK case 87: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); } - YY_BREAK case 88: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); } - YY_BREAK case 89: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); } - YY_BREAK case 90: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); } - YY_BREAK case 91: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); } - YY_BREAK case 92: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); } - YY_BREAK case 93: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); } - YY_BREAK case 94: -YY_RULE_SETUP -{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); } - YY_BREAK case 95: -YY_RULE_SETUP -{ return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); } - YY_BREAK -/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ case 96: case 97: case 98: @@ -1814,7 +1757,6 @@ case 131: case 132: case 133: case 134: -case 135: YY_RULE_SETUP { if (context->getShaderVersion() < 300) { @@ -1825,7 +1767,7 @@ YY_RULE_SETUP } YY_BREAK /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */ -case 136: +case 135: YY_RULE_SETUP { if (context->getShaderVersion() >= 300) @@ -1838,6 +1780,7 @@ YY_RULE_SETUP } YY_BREAK /* Reserved keywords */ +case 136: case 137: case 138: case 139: @@ -2338,7 +2281,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { - int num_to_read = + yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) @@ -2374,7 +2317,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - static_cast<int>(number_to_move) - 1; + number_to_move - 1; } @@ -2382,10 +2325,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ - size_t result = 0; YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - result, num_to_read ); - yyg->yy_n_chars = static_cast<int>(result); + yyg->yy_n_chars, num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } @@ -2826,7 +2767,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner) /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; - num_to_alloc = static_cast<int>(yyg->yy_buffer_stack_max + grow_size); + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) @@ -2860,7 +2801,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscann if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - b->yy_buf_size = static_cast<int>(size) - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; @@ -2909,7 +2850,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i ) + for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; @@ -3360,24 +3301,6 @@ int ES2_keyword_ES3_reserved(TParseContext *context, int token) return token; } -int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 300) - { - yylval->lex.string = NewPoolTString(yytext); - return check_type(yyscanner); - } - else if (context->getShaderVersion() == 300) - { - return reserved_word(yyscanner); - } - - return token; -} - int ES2_ident_ES3_keyword(TParseContext *context, int token) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); @@ -3393,18 +3316,6 @@ int ES2_ident_ES3_keyword(TParseContext *context, int token) return token; } -int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token) -{ - yyscan_t yyscanner = (yyscan_t) context->getScanner(); - - if (context->getShaderVersion() < 310) - { - return reserved_word(yyscanner); - } - - return token; -} - int uint_constant(TParseContext *context) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); @@ -3506,7 +3417,7 @@ int glslang_scan(size_t count, const char* const string[], const int length[], if (context->getFragmentPrecisionHigh()) preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec())); + preprocessor->setMaxTokenSize(GetGlobalMaxTokenSize(context->getShaderSpec())); return 0; } diff --git a/gfx/angle/src/compiler/translator/glslang_tab.cpp b/gfx/angle/src/compiler/translator/glslang_tab.cpp index 63a3371dc..ada392497 100755 --- a/gfx/angle/src/compiler/translator/glslang_tab.cpp +++ b/gfx/angle/src/compiler/translator/glslang_tab.cpp @@ -96,8 +96,6 @@ #define YYENABLE_NLS 0 -using namespace sh; - @@ -192,97 +190,80 @@ extern int yydebug; CENTROID = 306, FLAT = 307, SMOOTH = 308, - READONLY = 309, - WRITEONLY = 310, - COHERENT = 311, - RESTRICT = 312, - VOLATILE = 313, - STRUCT = 314, - VOID_TYPE = 315, - WHILE = 316, - SAMPLER2D = 317, - SAMPLERCUBE = 318, - SAMPLER_EXTERNAL_OES = 319, - SAMPLER2DRECT = 320, - SAMPLER2DARRAY = 321, - ISAMPLER2D = 322, - ISAMPLER3D = 323, - ISAMPLERCUBE = 324, - ISAMPLER2DARRAY = 325, - USAMPLER2D = 326, - USAMPLER3D = 327, - USAMPLERCUBE = 328, - USAMPLER2DARRAY = 329, - SAMPLER3D = 330, - SAMPLER3DRECT = 331, - SAMPLER2DSHADOW = 332, - SAMPLERCUBESHADOW = 333, - SAMPLER2DARRAYSHADOW = 334, - IMAGE2D = 335, - IIMAGE2D = 336, - UIMAGE2D = 337, - IMAGE3D = 338, - IIMAGE3D = 339, - UIMAGE3D = 340, - IMAGE2DARRAY = 341, - IIMAGE2DARRAY = 342, - UIMAGE2DARRAY = 343, - IMAGECUBE = 344, - IIMAGECUBE = 345, - UIMAGECUBE = 346, - LAYOUT = 347, - IDENTIFIER = 348, - TYPE_NAME = 349, - FLOATCONSTANT = 350, - INTCONSTANT = 351, - UINTCONSTANT = 352, - BOOLCONSTANT = 353, - FIELD_SELECTION = 354, - LEFT_OP = 355, - RIGHT_OP = 356, - INC_OP = 357, - DEC_OP = 358, - LE_OP = 359, - GE_OP = 360, - EQ_OP = 361, - NE_OP = 362, - AND_OP = 363, - OR_OP = 364, - XOR_OP = 365, - MUL_ASSIGN = 366, - DIV_ASSIGN = 367, - ADD_ASSIGN = 368, - MOD_ASSIGN = 369, - LEFT_ASSIGN = 370, - RIGHT_ASSIGN = 371, - AND_ASSIGN = 372, - XOR_ASSIGN = 373, - OR_ASSIGN = 374, - SUB_ASSIGN = 375, - LEFT_PAREN = 376, - RIGHT_PAREN = 377, - LEFT_BRACKET = 378, - RIGHT_BRACKET = 379, - LEFT_BRACE = 380, - RIGHT_BRACE = 381, - DOT = 382, - COMMA = 383, - COLON = 384, - EQUAL = 385, - SEMICOLON = 386, - BANG = 387, - DASH = 388, - TILDE = 389, - PLUS = 390, - STAR = 391, - SLASH = 392, - PERCENT = 393, - LEFT_ANGLE = 394, - RIGHT_ANGLE = 395, - VERTICAL_BAR = 396, - CARET = 397, - AMPERSAND = 398, - QUESTION = 399 + STRUCT = 309, + VOID_TYPE = 310, + WHILE = 311, + SAMPLER2D = 312, + SAMPLERCUBE = 313, + SAMPLER_EXTERNAL_OES = 314, + SAMPLER2DRECT = 315, + SAMPLER2DARRAY = 316, + ISAMPLER2D = 317, + ISAMPLER3D = 318, + ISAMPLERCUBE = 319, + ISAMPLER2DARRAY = 320, + USAMPLER2D = 321, + USAMPLER3D = 322, + USAMPLERCUBE = 323, + USAMPLER2DARRAY = 324, + SAMPLER3D = 325, + SAMPLER3DRECT = 326, + SAMPLER2DSHADOW = 327, + SAMPLERCUBESHADOW = 328, + SAMPLER2DARRAYSHADOW = 329, + LAYOUT = 330, + IDENTIFIER = 331, + TYPE_NAME = 332, + FLOATCONSTANT = 333, + INTCONSTANT = 334, + UINTCONSTANT = 335, + BOOLCONSTANT = 336, + FIELD_SELECTION = 337, + LEFT_OP = 338, + RIGHT_OP = 339, + INC_OP = 340, + DEC_OP = 341, + LE_OP = 342, + GE_OP = 343, + EQ_OP = 344, + NE_OP = 345, + AND_OP = 346, + OR_OP = 347, + XOR_OP = 348, + MUL_ASSIGN = 349, + DIV_ASSIGN = 350, + ADD_ASSIGN = 351, + MOD_ASSIGN = 352, + LEFT_ASSIGN = 353, + RIGHT_ASSIGN = 354, + AND_ASSIGN = 355, + XOR_ASSIGN = 356, + OR_ASSIGN = 357, + SUB_ASSIGN = 358, + LEFT_PAREN = 359, + RIGHT_PAREN = 360, + LEFT_BRACKET = 361, + RIGHT_BRACKET = 362, + LEFT_BRACE = 363, + RIGHT_BRACE = 364, + DOT = 365, + COMMA = 366, + COLON = 367, + EQUAL = 368, + SEMICOLON = 369, + BANG = 370, + DASH = 371, + TILDE = 372, + PLUS = 373, + STAR = 374, + SLASH = 375, + PERCENT = 376, + LEFT_ANGLE = 377, + RIGHT_ANGLE = 378, + VERTICAL_BAR = 379, + CARET = 380, + AMPERSAND = 381, + QUESTION = 382 }; #endif @@ -306,27 +287,22 @@ union YYSTYPE struct { TOperator op; union { - TIntermNode *intermNode; + TIntermNode* intermNode; TIntermNodePair nodePair; - TIntermTyped *intermTypedNode; - TIntermAggregate *intermAggregate; - TIntermBlock *intermBlock; - TIntermDeclaration *intermDeclaration; - TIntermSwitch *intermSwitch; - TIntermCase *intermCase; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + TIntermSwitch* intermSwitch; + TIntermCase* intermCase; }; union { - TTypeSpecifierNonArray typeSpecifierNonArray; TPublicType type; TPrecision precision; TLayoutQualifier layoutQualifier; TQualifier qualifier; - TFunction *function; + TFunction* function; TParameter param; - TField *field; - TFieldList *fieldList; - TQualifierWrapperBase *qualifierWrapper; - TTypeQualifierBuilder *typeQualifierBuilder; + TField* field; + TFieldList* fieldList; }; } interm; @@ -664,23 +640,23 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 126 +#define YYFINAL 116 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 2825 +#define YYLAST 2516 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 145 +#define YYNTOKENS 128 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 94 /* YYNRULES -- Number of rules. */ -#define YYNRULES 286 +#define YYNRULES 275 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 422 +#define YYNSTATES 417 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 399 +#define YYMAXUTOK 382 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -727,43 +703,41 @@ static const yytype_uint8 yytranslate[] = 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144 + 125, 126, 127 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 243, 243, 244, 247, 257, 260, 265, 270, 275, - 280, 286, 289, 292, 295, 298, 301, 307, 314, 325, - 329, 337, 340, 346, 350, 357, 363, 372, 380, 386, - 392, 401, 404, 407, 410, 420, 421, 422, 423, 431, - 432, 435, 438, 445, 446, 449, 455, 456, 460, 467, - 468, 471, 474, 477, 483, 484, 487, 493, 494, 501, - 502, 509, 510, 517, 518, 524, 525, 531, 532, 538, - 539, 545, 546, 553, 554, 555, 556, 560, 561, 562, - 566, 570, 574, 578, 585, 588, 594, 601, 608, 611, - 614, 623, 627, 631, 635, 639, 646, 653, 656, 663, - 671, 691, 701, 709, 734, 738, 742, 746, 753, 760, - 763, 767, 771, 776, 781, 788, 792, 796, 800, 805, - 810, 817, 821, 827, 830, 836, 840, 847, 853, 857, - 861, 864, 867, 876, 882, 890, 893, 913, 932, 939, - 943, 947, 950, 953, 956, 959, 965, 972, 975, 978, - 984, 991, 994, 1000, 1003, 1006, 1012, 1015, 1020, 1031, - 1034, 1037, 1040, 1043, 1046, 1050, 1054, 1058, 1062, 1066, - 1070, 1074, 1078, 1082, 1086, 1090, 1094, 1098, 1102, 1106, - 1110, 1114, 1118, 1122, 1126, 1130, 1133, 1136, 1139, 1142, - 1145, 1148, 1151, 1154, 1157, 1160, 1163, 1166, 1169, 1172, - 1175, 1182, 1188, 1191, 1194, 1197, 1200, 1203, 1206, 1209, - 1212, 1215, 1218, 1221, 1224, 1227, 1239, 1239, 1242, 1242, - 1248, 1251, 1266, 1269, 1276, 1280, 1286, 1292, 1304, 1308, - 1312, 1313, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1329, - 1330, 1330, 1330, 1339, 1340, 1344, 1344, 1345, 1345, 1350, - 1353, 1362, 1367, 1374, 1375, 1379, 1386, 1390, 1397, 1397, - 1404, 1407, 1414, 1418, 1431, 1431, 1436, 1436, 1442, 1442, - 1450, 1453, 1459, 1462, 1468, 1472, 1479, 1482, 1485, 1488, - 1491, 1500, 1506, 1512, 1515, 1521, 1521 + 0, 228, 228, 229, 232, 242, 245, 250, 255, 260, + 265, 271, 274, 277, 280, 283, 286, 292, 299, 310, + 314, 322, 325, 331, 335, 342, 348, 357, 365, 371, + 377, 386, 389, 392, 395, 405, 406, 407, 408, 416, + 417, 420, 423, 430, 431, 434, 440, 441, 445, 452, + 453, 456, 459, 462, 468, 469, 472, 478, 479, 486, + 487, 494, 495, 502, 503, 509, 510, 516, 517, 523, + 524, 530, 531, 538, 539, 540, 541, 545, 546, 547, + 551, 555, 559, 563, 570, 573, 579, 586, 593, 596, + 602, 611, 615, 619, 623, 630, 636, 639, 646, 654, + 674, 683, 691, 716, 720, 728, 732, 740, 743, 746, + 749, 755, 762, 765, 769, 773, 778, 783, 790, 794, + 798, 802, 807, 812, 816, 823, 833, 839, 842, 848, + 854, 860, 868, 877, 884, 887, 893, 897, 901, 906, + 914, 917, 933, 938, 943, 948, 955, 963, 974, 977, + 980, 986, 993, 996, 1002, 1005, 1008, 1014, 1017, 1022, + 1034, 1038, 1042, 1046, 1050, 1054, 1059, 1064, 1069, 1074, + 1079, 1084, 1089, 1094, 1099, 1104, 1109, 1114, 1119, 1124, + 1129, 1134, 1139, 1144, 1149, 1154, 1159, 1163, 1167, 1171, + 1175, 1179, 1183, 1187, 1191, 1195, 1199, 1203, 1207, 1211, + 1215, 1219, 1227, 1234, 1238, 1251, 1251, 1254, 1254, 1260, + 1263, 1278, 1281, 1290, 1294, 1300, 1306, 1318, 1322, 1326, + 1327, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1343, 1344, + 1344, 1344, 1354, 1355, 1359, 1359, 1360, 1360, 1365, 1368, + 1378, 1381, 1387, 1388, 1392, 1399, 1403, 1410, 1410, 1417, + 1420, 1427, 1431, 1444, 1444, 1449, 1449, 1455, 1455, 1463, + 1466, 1472, 1475, 1481, 1485, 1492, 1495, 1498, 1501, 1504, + 1513, 1517, 1524, 1527, 1533, 1533 }; #endif @@ -780,28 +754,24 @@ static const char *const yytname[] = "IVEC4", "VEC2", "VEC3", "VEC4", "UVEC2", "UVEC3", "UVEC4", "MATRIX2", "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM", "VARYING", "MATRIX2x3", "MATRIX3x2", "MATRIX2x4", "MATRIX4x2", - "MATRIX3x4", "MATRIX4x3", "CENTROID", "FLAT", "SMOOTH", "READONLY", - "WRITEONLY", "COHERENT", "RESTRICT", "VOLATILE", "STRUCT", "VOID_TYPE", - "WHILE", "SAMPLER2D", "SAMPLERCUBE", "SAMPLER_EXTERNAL_OES", + "MATRIX3x4", "MATRIX4x3", "CENTROID", "FLAT", "SMOOTH", "STRUCT", + "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE", "SAMPLER_EXTERNAL_OES", "SAMPLER2DRECT", "SAMPLER2DARRAY", "ISAMPLER2D", "ISAMPLER3D", "ISAMPLERCUBE", "ISAMPLER2DARRAY", "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER2DARRAY", "SAMPLER3D", "SAMPLER3DRECT", - "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW", "SAMPLER2DARRAYSHADOW", - "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D", "IIMAGE3D", "UIMAGE3D", - "IMAGE2DARRAY", "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBE", - "IIMAGECUBE", "UIMAGECUBE", "LAYOUT", "IDENTIFIER", "TYPE_NAME", - "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", - "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", - "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", - "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", - "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", - "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", - "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", - "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", - "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION", - "$accept", "identifier", "variable_identifier", "primary_expression", - "postfix_expression", "integer_expression", "function_call", - "function_call_or_method", "function_call_generic", + "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW", "SAMPLER2DARRAYSHADOW", "LAYOUT", + "IDENTIFIER", "TYPE_NAME", "FLOATCONSTANT", "INTCONSTANT", + "UINTCONSTANT", "BOOLCONSTANT", "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", + "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", + "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", + "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET", + "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON", + "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH", + "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", + "AMPERSAND", "QUESTION", "$accept", "identifier", "variable_identifier", + "primary_expression", "postfix_expression", "integer_expression", + "function_call", "function_call_or_method", "function_call_generic", "function_call_header_no_parameters", "function_call_header_with_parameters", "function_call_header", "function_identifier", "unary_expression", "unary_operator", @@ -814,10 +784,10 @@ static const char *const yytname[] = "constant_expression", "enter_struct", "declaration", "function_prototype", "function_declarator", "function_header_with_parameters", "function_header", - "parameter_declarator", "parameter_declaration", + "parameter_declarator", "parameter_declaration", "parameter_qualifier", "parameter_type_specifier", "init_declarator_list", "single_declaration", - "fully_specified_type", "interpolation_qualifier", "type_qualifier", - "invariant_qualifier", "single_type_qualifier", "storage_qualifier", + "fully_specified_type", "interpolation_qualifier", + "parameter_type_qualifier", "type_qualifier", "storage_qualifier", "type_specifier", "precision_qualifier", "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id", "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier", @@ -852,18 +822,16 @@ static const yytype_uint16 yytoknum[] = 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399 + 375, 376, 377, 378, 379, 380, 381, 382 }; # endif -#define YYPACT_NINF -363 +#define YYPACT_NINF -361 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-363))) + (!!((Yystate) == (-361))) -#define YYTABLE_NINF -246 +#define YYTABLE_NINF -235 #define yytable_value_is_error(Yytable_value) \ 0 @@ -872,49 +840,48 @@ static const yytype_uint16 yytoknum[] = STATE-NUM. */ static const yytype_int16 yypact[] = { - 2469, -363, -363, -363, -363, 101, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -68, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, -363, -88, -363, -363, - -77, -35, -13, 2561, -51, -363, 27, -363, 1301, -363, - -363, -363, -363, -363, -363, -363, 12, -363, 2377, -363, - -363, 2731, -363, -363, -363, 15, 49, -363, 22, -363, - 2561, -363, -363, -363, 2561, 51, 51, -363, 16, -103, - -87, -363, 2561, -363, -363, 1388, -363, -363, 20, 2561, - -363, 19, -82, -363, 408, -363, -363, -363, -363, 39, - -91, -363, 1503, 1845, -363, -363, 2561, 51, 2071, -363, - 47, -363, -363, -363, -363, -363, 1845, 1845, 1845, -363, - -363, -363, -363, -363, -363, -363, -41, -363, -363, -363, - 55, -55, 1957, 59, -363, 1845, -5, -90, 64, -81, - -42, 33, 45, 48, 78, 80, -93, -363, 71, -363, - -363, 2173, 2561, 70, -363, 49, 57, 63, -363, 79, - 81, 68, 1618, 83, 1845, 72, 84, 82, -363, -363, - 41, -363, -363, -36, -363, -77, 85, -363, -363, -363, - -363, 541, -363, -363, -363, -363, -363, -363, 1845, 1730, - 1845, 77, 88, -363, -363, 51, 86, -34, -363, -78, - -363, -363, -363, -50, -363, -363, 1845, 2646, -363, -363, - 1845, 92, -363, -363, -363, 1845, 1845, 1845, 1845, 1845, - 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, 1845, - 1845, 1845, 1845, 1845, 1845, -363, -363, 2275, -363, -363, - -363, -363, -363, 90, -363, 1845, -363, -363, -29, 1845, - 87, -363, -363, -363, 674, -363, -363, -363, -363, -363, - -363, -363, -363, -363, -363, -363, 1845, 1845, -363, -363, - -363, 93, 89, 94, -363, 1845, 95, -1, 1845, 51, - -363, -94, -363, -363, 96, 98, -363, 102, -363, -363, - -363, -363, -363, -5, -5, -90, -90, 64, 64, 64, - 64, -81, -81, -42, 33, 45, 48, 78, 80, 44, - -363, 161, 22, 940, 1073, -47, -363, -37, -363, 1187, - 674, -363, -363, -363, 1845, 103, -363, 1845, -363, 100, - -363, 1845, -363, -363, 1845, 107, -363, -363, -363, -363, - 1187, 90, -363, 98, 51, 2561, 109, 106, -363, 1845, - -363, -363, 111, -363, 1845, -363, 105, 116, 222, -363, - 115, 112, 807, -363, -363, 110, -32, 1845, 807, 90, - -363, 1845, -363, -363, -363, -363, 113, 98, -363, -363, - -363, -363 + 2154, 224, -361, -361, -361, 130, -361, -361, -361, -361, + -361, -361, -361, -361, -361, -361, -361, -361, -361, -361, + -361, -361, -361, -361, -361, -361, -361, -361, -361, -361, + -361, -361, -361, -361, -361, -361, -361, 145, -361, -361, + -46, -361, -361, -361, -361, -361, -361, -361, -361, -361, + -361, -361, -361, -361, -361, -361, -361, -361, -361, -82, + -361, -361, -68, -41, -45, 9, 7, -361, 117, 16, + 1173, -361, -361, 2439, 16, -361, -9, -361, 2079, -361, + -361, -361, -361, 16, -361, 2439, -361, -361, -361, -361, + -361, -31, 23, -361, 11, -361, 63, -361, -361, -361, + -361, -361, 2303, 168, 120, -361, 13, -66, -361, 31, + -361, 2229, -361, -361, -361, 1243, -361, -361, -361, 56, + 2229, -361, 17, -50, -361, 401, -361, -361, -361, -361, + 120, 2303, -18, -361, 1341, 1632, -361, 179, 2303, 120, + 1824, -361, 70, -361, -361, -361, -361, -361, 1632, 1632, + 1632, -361, -361, -361, -361, -361, -361, -361, 22, -361, + -361, -361, 101, -29, 1727, 114, -361, 1632, 96, -97, + 128, -54, 111, 118, 102, 115, 154, 153, -69, -361, + 140, -361, -361, 1909, 2229, 124, -361, 23, 134, 136, + -361, 147, 149, 143, 1439, 155, 1632, 148, 157, 160, + -361, -361, 184, -361, -361, 52, -361, -68, 158, -361, + -361, -361, -361, 517, -361, -361, -361, -361, -361, -361, + 166, -361, -361, 1534, 1632, 150, 159, -361, -361, 120, + 167, 61, -361, -62, -361, -361, -361, -5, -361, -361, + 1632, 2371, -361, -361, 1632, 185, -361, -361, -361, 1632, + 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, + 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, 1632, -361, + -361, 1994, -361, -361, -361, -361, -361, 181, -361, 1632, + -361, -361, 67, 1632, 180, -361, -361, -361, 633, -361, + -361, -361, -361, -361, -361, -361, -361, -361, -361, -361, + 1632, 1632, -361, -361, -361, 1632, 178, 186, -361, 1632, + 182, 68, 1632, 120, -361, -71, -361, -361, 187, 188, + -361, 192, -361, -361, -361, -361, -361, 96, 96, -97, + -97, 128, 128, 128, 128, -54, -54, 111, 118, 102, + 115, 154, 153, 113, -361, 242, 11, 865, 981, 4, + -361, 18, -361, 1078, 633, -361, -361, 194, 1632, 189, + -361, 1632, -361, 196, -361, 1632, -361, -361, 1632, 200, + -361, -361, -361, -361, 1078, 181, -361, 188, 120, 2303, + 201, 198, -361, -361, 1632, -361, -361, 202, -361, 1632, + -361, 191, 203, 293, -361, 204, 205, 749, -361, -361, + 197, 60, 1632, 749, 181, -361, 1632, -361, -361, -361, + -361, 199, 188, -361, -361, -361, -361 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -922,79 +889,78 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_uint16 yydefact[] = { - 0, 127, 147, 148, 149, 0, 133, 135, 163, 160, - 161, 162, 167, 168, 169, 170, 171, 172, 164, 165, - 166, 173, 174, 175, 176, 177, 178, 136, 137, 138, - 140, 134, 179, 180, 181, 182, 183, 184, 139, 124, - 123, 141, 142, 143, 144, 145, 0, 159, 185, 187, - 200, 201, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 186, 197, 198, 199, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 0, 215, 284, - 285, 0, 98, 97, 0, 109, 115, 131, 0, 132, - 125, 128, 121, 130, 129, 146, 156, 202, 0, 281, - 283, 0, 2, 3, 218, 0, 0, 88, 0, 96, - 0, 105, 99, 107, 0, 108, 0, 89, 2, 116, - 0, 94, 0, 126, 122, 0, 1, 282, 0, 0, - 216, 153, 0, 151, 0, 286, 100, 104, 106, 102, - 110, 101, 0, 0, 87, 95, 0, 0, 0, 220, - 4, 8, 6, 7, 9, 30, 0, 0, 0, 157, - 37, 36, 38, 35, 5, 11, 31, 13, 18, 19, - 0, 0, 24, 0, 39, 0, 43, 46, 49, 54, - 57, 59, 61, 63, 65, 67, 69, 86, 0, 28, - 90, 0, 0, 0, 150, 0, 0, 0, 266, 0, - 0, 0, 0, 0, 0, 0, 0, 240, 249, 253, - 39, 71, 84, 0, 229, 0, 146, 232, 251, 231, - 230, 0, 233, 234, 235, 236, 237, 238, 0, 0, - 0, 0, 0, 228, 120, 0, 226, 0, 224, 0, - 221, 32, 33, 0, 15, 16, 0, 0, 22, 21, - 0, 159, 25, 27, 34, 0, 0, 0, 0, 0, + 0, 0, 148, 149, 150, 0, 130, 140, 164, 161, + 162, 163, 168, 169, 170, 171, 172, 173, 165, 166, + 167, 174, 175, 176, 177, 178, 179, 141, 142, 145, + 131, 180, 181, 182, 183, 184, 185, 0, 128, 127, + 0, 160, 186, 188, 201, 202, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 187, 198, 199, 200, 0, + 204, 273, 274, 0, 97, 107, 0, 112, 118, 135, + 0, 133, 125, 0, 136, 146, 157, 203, 0, 270, + 272, 132, 124, 0, 138, 0, 143, 144, 2, 3, + 207, 0, 0, 88, 0, 95, 107, 129, 108, 109, + 110, 98, 0, 107, 0, 89, 2, 119, 134, 0, + 94, 0, 126, 147, 137, 0, 1, 271, 139, 0, + 0, 205, 154, 0, 152, 0, 275, 99, 104, 106, + 111, 0, 113, 100, 0, 0, 87, 0, 0, 0, + 0, 209, 4, 8, 6, 7, 9, 30, 0, 0, + 0, 158, 37, 36, 38, 35, 5, 11, 31, 13, + 18, 19, 0, 0, 24, 0, 39, 0, 43, 46, + 49, 54, 57, 59, 61, 63, 65, 67, 69, 86, + 0, 28, 90, 0, 0, 0, 151, 0, 0, 0, + 255, 0, 0, 0, 0, 0, 0, 0, 0, 229, + 238, 242, 39, 71, 84, 0, 218, 0, 146, 221, + 240, 220, 219, 0, 222, 223, 224, 225, 226, 227, + 101, 103, 105, 0, 0, 0, 0, 217, 123, 0, + 215, 0, 213, 0, 210, 32, 33, 0, 15, 16, + 0, 0, 22, 21, 0, 160, 25, 27, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 158, 219, 0, 154, 155, - 152, 277, 276, 247, 268, 0, 280, 278, 0, 0, - 0, 261, 264, 239, 0, 74, 75, 77, 76, 79, - 80, 81, 82, 83, 78, 73, 0, 0, 254, 250, - 252, 0, 0, 0, 114, 0, 117, 0, 0, 0, - 222, 0, 91, 10, 0, 17, 29, 14, 20, 26, - 40, 41, 42, 45, 44, 47, 48, 52, 53, 50, - 51, 55, 56, 58, 60, 62, 64, 66, 68, 0, - 217, 0, 0, 0, 0, 0, 279, 0, 260, 0, - 241, 72, 85, 103, 0, 111, 118, 0, 223, 0, - 225, 0, 92, 12, 0, 0, 246, 248, 271, 270, - 273, 247, 258, 262, 0, 0, 0, 0, 112, 0, - 119, 227, 0, 70, 0, 272, 0, 0, 257, 255, - 0, 0, 0, 242, 113, 0, 0, 274, 0, 247, - 259, 0, 244, 265, 243, 93, 0, 275, 269, 256, - 263, 267 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, + 208, 0, 155, 156, 153, 266, 265, 236, 257, 0, + 269, 267, 0, 0, 0, 250, 253, 228, 0, 74, + 75, 77, 76, 79, 80, 81, 82, 83, 78, 73, + 0, 0, 243, 239, 241, 0, 0, 0, 117, 0, + 120, 0, 0, 0, 211, 0, 91, 10, 0, 17, + 29, 14, 20, 26, 40, 41, 42, 45, 44, 47, + 48, 52, 53, 50, 51, 55, 56, 58, 60, 62, + 64, 66, 68, 0, 206, 0, 0, 0, 0, 0, + 268, 0, 249, 0, 230, 72, 85, 0, 0, 114, + 121, 0, 212, 0, 214, 0, 92, 12, 0, 0, + 235, 237, 260, 259, 262, 236, 247, 251, 0, 0, + 0, 0, 102, 115, 0, 122, 216, 0, 70, 0, + 261, 0, 0, 246, 244, 0, 0, 0, 231, 116, + 0, 0, 263, 0, 236, 248, 0, 233, 254, 232, + 93, 0, 264, 258, 245, 252, 256 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -363, -45, -363, -363, -363, -363, -363, -363, -4, -363, - -363, -363, -363, 54, -363, -84, -79, -139, -83, -23, - -22, -21, -18, -17, -16, -363, -120, -137, -363, -146, - -125, -363, 18, 21, -363, -363, -363, 136, 146, 145, - -363, -363, -328, -363, -74, -363, -86, -363, -80, 255, - -363, -363, 67, 0, -363, -363, -363, -363, -116, -141, - 28, -54, -226, -85, -210, -339, -136, -363, -363, -142, - -362, -363, -363, -98, -27, -76, -363, -363, -363, -363, - -363, -112, -363, -363, -363, -363, -363, -363, -363, -363, - -363, 172, -363, -363 + -361, -39, -361, -361, -361, -361, -361, -361, 73, -361, + -361, -361, -361, -107, -361, -15, -20, -67, -19, 53, + 54, 55, 51, 57, 58, -361, -110, -132, -361, -146, + -125, -361, 6, 12, -361, -361, -361, 190, 228, 217, + 195, -361, -361, -336, 25, -361, -104, 27, -57, 322, + -361, -361, 141, 0, -361, -361, -361, -361, -109, -130, + 100, 19, -185, -17, -193, -310, -65, -361, -361, -70, + -360, -361, -361, -92, 46, -13, -361, -361, -361, -361, + -361, -38, -361, -361, -361, -361, -361, -361, -361, -361, + -361, 259, -361, -361 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 236, 164, 165, 166, 324, 167, 168, 169, 170, - 171, 172, 173, 210, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 211, 212, 306, 213, - 188, 122, 214, 215, 81, 82, 83, 111, 112, 113, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 132, 133, 189, 96, 97, 192, 129, 148, 149, - 237, 238, 234, 217, 218, 219, 220, 294, 387, 413, - 351, 352, 353, 414, 221, 222, 223, 399, 224, 400, - 225, 386, 226, 359, 283, 354, 380, 396, 397, 227, - 98, 99, 100, 108 + -1, 230, 156, 157, 158, 318, 159, 160, 161, 162, + 163, 164, 165, 202, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 203, 204, 300, 205, + 180, 111, 206, 207, 63, 64, 65, 128, 101, 102, + 129, 66, 67, 68, 69, 103, 70, 71, 72, 73, + 74, 123, 124, 181, 76, 77, 184, 120, 140, 141, + 231, 232, 228, 209, 210, 211, 212, 288, 381, 408, + 345, 346, 347, 409, 213, 214, 215, 394, 216, 395, + 217, 380, 218, 353, 277, 348, 374, 391, 392, 219, + 78, 79, 80, 94 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -1002,576 +968,514 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 95, 105, 123, 115, 314, 187, 233, 240, 124, 114, - 135, 310, 243, 191, 377, 321, 273, 232, 79, 398, - 142, 80, 187, 262, 263, 102, 103, 143, 123, 371, - 115, 384, 229, 106, 115, 252, 114, 372, 144, 230, - 194, 119, 147, 258, 145, 259, 195, 419, 146, 147, - 240, 274, 384, 322, 107, 146, 288, 104, 264, 265, - 123, 244, 245, 412, 266, 267, 235, 249, 147, 412, - 139, 140, 323, 250, 146, 381, 277, 116, 307, 290, - 117, 307, 246, 95, 187, 382, 247, 109, 95, 366, - 416, 307, 307, 233, 319, 308, 307, 320, 95, 307, - 325, 128, 356, 311, 313, 2, 3, 4, 187, 187, - 95, 147, 147, 329, 95, 110, 79, 146, 146, 80, - 118, 103, 95, 337, 338, 339, 340, 319, 349, 95, - 368, 255, 256, 257, 216, 125, 240, 141, 388, 355, - 130, 390, 131, 357, 102, 103, 95, 134, 95, 193, - 310, 190, 295, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 228, 404, 260, 261, 278, 279, -29, 361, - 362, 305, 307, 374, 333, 334, 268, 248, 233, 174, - 253, 335, 336, 341, 342, 420, 271, 269, 281, 270, - 272, 95, 95, 369, 282, 275, 174, 147, 187, 286, - 284, 291, 285, 146, 289, 292, -28, 315, 293, 318, - 241, 242, 316, 383, -23, -245, 358, 363, 365, 364, - 373, 216, 375, -30, 391, 367, 307, 233, 394, 254, - 233, 402, 403, 389, 383, 405, 407, 393, 408, 409, - 207, 415, 411, 328, 421, 343, 392, 344, 406, 345, - 137, 187, 233, 346, 376, 347, 136, 348, 174, 138, - 101, 417, 280, 317, 410, 370, 418, 360, 395, 378, - 127, 0, 0, 0, 233, 0, 0, 95, 379, 0, - 0, 0, 174, 174, 0, 385, 0, 0, 0, 0, - 0, 0, 0, 0, 216, 0, 0, 0, 0, 123, - 0, 0, 0, 0, 0, 124, 385, 0, 0, 330, - 331, 332, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 174, 174, 174, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 401, + 75, 91, 126, 227, 237, 179, 61, 138, 166, 226, + 234, 183, 62, 112, 315, 393, 138, 378, 97, 252, + 304, 253, 92, 267, 179, 7, 83, 166, 84, 107, + 88, 89, 246, 256, 257, 365, 138, 371, 378, 308, + 134, 235, 236, 366, 414, 130, 93, 135, 282, 98, + 99, 100, 316, 234, 139, 186, 27, 28, 268, 29, + 248, 187, 90, 139, 95, 132, 96, 37, 258, 259, + 75, 284, 97, 113, 130, 271, 243, 121, 75, 138, + 138, 229, 244, 139, 61, 119, 179, 407, 223, 166, + 62, 220, 227, 407, 319, 224, 108, 115, 307, 122, + 317, 114, 75, 98, 99, 100, 301, 238, 239, 375, + 118, 75, 323, 179, -96, 301, 166, 133, 104, 125, + 75, 105, 343, 376, 360, 208, 139, 139, 240, 301, + 185, 75, 241, 349, 2, 3, 4, 351, 75, 136, + 75, 234, 324, 325, 326, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 304, 83, 301, 84, 411, 302, 138, 355, 356, + 182, 301, 313, 383, -29, 314, 385, 227, 301, 313, + 357, 350, 362, 75, 75, 86, 87, 363, 7, 331, + 332, 333, 334, 106, 89, 179, 88, 89, 166, 399, + 260, 261, 179, 272, 273, 166, 242, 377, 98, 99, + 100, 254, 255, 208, 139, 249, 250, 251, 247, 27, + 28, 415, 29, 81, 301, 368, 227, 263, 377, 227, + 37, 38, 39, 7, 329, 330, 388, 327, 328, 264, + 387, 335, 336, 401, 262, 265, 266, 269, 275, 379, + 276, 278, 227, 279, 370, 179, 412, 280, 166, 283, + 285, 286, -28, 309, 27, 28, 310, 29, 81, 287, + 379, 75, 305, 312, 227, 37, 38, 39, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 208, -234, + -23, 358, 352, 359, 367, 361, -30, 299, 369, 301, + 82, 382, 384, 386, 389, 402, 397, 398, 403, 400, + 404, 410, 199, 416, 322, 337, 340, 338, 406, 339, + 131, 221, 112, 341, 127, 342, 222, 85, 274, 311, + 405, 372, 364, 413, 354, 373, 390, 117, 0, 396, + 0, 0, 0, 0, 0, 0, 0, 208, 208, 0, + 0, 0, 0, 208, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 216, 216, 0, 0, 0, 0, 216, - 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, - 216, 0, 0, 0, 0, 95, 0, 0, 0, 0, + 0, 0, 0, 0, 208, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 216, 0, 0, 0, 0, 0, 216, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 196, 197, 198, 174, 199, 200, 201, 202, - 203, 204, 205, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 206, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 0, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 150, 78, 151, 152, 153, 154, 155, 0, 0, - 156, 157, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, - 0, 0, 0, 207, 208, 0, 0, 0, 0, 209, - 160, 161, 162, 163, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 196, 197, 198, 0, 199, - 200, 201, 202, 203, 204, 205, 12, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, + 0, 0, 0, 208, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 188, 189, 190, 0, 191, + 192, 193, 194, 195, 196, 197, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 206, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 0, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 150, 78, 151, 152, 153, 154, - 155, 0, 0, 156, 157, 0, 0, 0, 0, 0, + 26, 27, 28, 0, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 198, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 0, 56, 57, 58, 59, 142, 60, 143, + 144, 145, 146, 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 158, 0, 0, 0, 207, 309, 0, 0, - 0, 0, 209, 160, 161, 162, 163, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 196, 197, - 198, 0, 199, 200, 201, 202, 203, 204, 205, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 206, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 150, 78, 151, - 152, 153, 154, 155, 0, 0, 156, 157, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 158, 0, 0, 0, 207, - 0, 0, 0, 0, 0, 209, 160, 161, 162, 163, + 0, 0, 0, 0, 0, 150, 0, 0, 0, 199, + 200, 0, 0, 0, 0, 201, 152, 153, 154, 155, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 196, 197, 198, 0, 199, 200, 201, 202, 203, - 204, 205, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 206, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 0, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 150, 78, 151, 152, 153, 154, 155, 0, 0, 156, - 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 158, 0, - 0, 0, 134, 0, 0, 0, 0, 0, 209, 160, - 161, 162, 163, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 196, 197, 198, 0, 199, 200, - 201, 202, 203, 204, 205, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 206, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 0, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 150, 78, 151, 152, 153, 154, 155, - 0, 0, 156, 157, 0, 0, 0, 0, 0, 0, + 11, 188, 189, 190, 0, 191, 192, 193, 194, 195, + 196, 197, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 0, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 198, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 0, 56, + 57, 58, 59, 142, 60, 143, 144, 145, 146, 147, + 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 158, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 209, 160, 161, 162, 163, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, + 0, 150, 0, 0, 0, 199, 303, 0, 0, 0, + 0, 201, 152, 153, 154, 155, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 188, 189, 190, + 0, 191, 192, 193, 194, 195, 196, 197, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 0, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 150, 78, 151, 152, - 153, 154, 155, 0, 0, 156, 157, 0, 0, 0, + 24, 25, 26, 27, 28, 0, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 198, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 0, 56, 57, 58, 59, 142, + 60, 143, 144, 145, 146, 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4, 158, 6, 7, 8, 9, 10, - 11, 0, 0, 0, 209, 160, 161, 162, 163, 0, - 0, 0, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 0, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 0, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 150, 78, 151, 152, 153, 154, 155, 0, 0, 156, - 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 3, 4, 158, 6, - 7, 8, 9, 10, 11, 0, 0, 0, 0, 160, - 161, 162, 163, 0, 0, 0, 12, 13, 14, 15, + 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, + 0, 199, 0, 0, 0, 0, 0, 201, 152, 153, + 154, 155, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 188, 189, 190, 0, 191, 192, 193, + 194, 195, 196, 197, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 0, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 198, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 0, 56, 57, 58, 59, 142, 60, 143, 144, 145, + 146, 147, 0, 0, 148, 149, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 150, 0, 0, 0, 125, 0, 0, + 0, 0, 0, 201, 152, 153, 154, 155, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 188, + 189, 190, 0, 191, 192, 193, 194, 195, 196, 197, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 0, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 198, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 0, 56, 57, 58, + 59, 142, 60, 143, 144, 145, 146, 147, 0, 0, + 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, + 152, 153, 154, 155, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 0, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 120, 78, 0, 0, 8, 9, - 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 27, 28, 0, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 0, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 0, 56, 57, 58, 59, 142, 60, 143, + 144, 145, 146, 147, 0, 0, 148, 149, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 137, 2, 3, 4, 150, 6, 7, 8, 9, + 10, 11, 0, 0, 0, 201, 152, 153, 154, 155, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, - 0, 0, 121, 32, 33, 34, 35, 36, 37, 0, - 0, 0, 0, 0, 0, 0, 0, 46, 47, 0, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 0, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 0, 150, 78, 151, 152, 153, 154, 155, 0, 0, - 156, 157, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, - 0, 0, 159, 8, 9, 10, 11, 0, 0, 0, - 160, 161, 162, 163, 0, 0, 0, 0, 12, 13, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 0, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 0, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 0, + 56, 57, 58, 59, 142, 60, 143, 144, 145, 146, + 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, + 0, 0, 150, 8, 9, 10, 11, 0, 0, 0, + 0, 0, 0, 152, 153, 154, 155, 0, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 0, 0, 0, 0, 0, 31, 32, + 33, 34, 35, 36, 0, 0, 0, 40, 41, 0, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 0, 56, 57, 58, 0, 109, + 60, 0, 0, 8, 9, 10, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 0, 0, 0, 0, 0, 32, 33, - 34, 35, 36, 37, 0, 0, 0, 0, 0, 0, - 0, 0, 46, 47, 0, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 0, 150, 78, 151, 152, - 153, 154, 155, 0, 0, 156, 157, 0, 0, 0, + 24, 25, 26, 0, 0, 0, 0, 110, 31, 32, + 33, 34, 35, 36, 0, 0, 0, 40, 41, 0, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 0, 56, 57, 58, 0, 142, + 60, 143, 144, 145, 146, 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 158, 0, 0, 231, 8, 9, - 10, 11, 0, 0, 0, 160, 161, 162, 163, 0, - 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, - 0, 0, 0, 32, 33, 34, 35, 36, 37, 0, - 0, 0, 0, 0, 0, 0, 0, 46, 47, 0, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 0, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 0, 150, 78, 151, 152, 153, 154, 155, 0, 0, - 156, 157, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, - 8, 9, 10, 11, 0, 0, 0, 0, 0, 287, - 160, 161, 162, 163, 0, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, - 37, 0, 0, 0, 0, 0, 0, 0, 0, 46, - 47, 0, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 0, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 0, 150, 78, 151, 152, 153, 154, 155, - 0, 0, 156, 157, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, + 151, 8, 9, 10, 11, 0, 0, 0, 152, 153, + 154, 155, 0, 0, 0, 0, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 0, 0, 0, 0, 0, 31, 32, 33, 34, + 35, 36, 0, 0, 0, 40, 41, 0, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 0, 56, 57, 58, 0, 142, 60, 143, + 144, 145, 146, 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 158, 0, 0, 312, 8, 9, 10, 11, 0, - 0, 0, 160, 161, 162, 163, 0, 0, 0, 0, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 0, 0, 0, 0, 0, - 32, 33, 34, 35, 36, 37, 0, 0, 0, 0, - 0, 0, 0, 0, 46, 47, 0, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 0, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 0, 150, 78, - 151, 152, 153, 154, 155, 0, 0, 156, 157, 0, + 0, 0, 0, 0, 0, 150, 0, 0, 225, 8, + 9, 10, 11, 0, 0, 0, 152, 153, 154, 155, + 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, + 0, 0, 0, 0, 31, 32, 33, 34, 35, 36, + 0, 0, 0, 40, 41, 0, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 0, 56, 57, 58, 0, 142, 60, 143, 144, 145, + 146, 147, 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 158, 8, 9, 10, - 11, 0, 0, 0, 0, 0, 0, 160, 161, 162, - 163, 0, 12, 13, 14, 15, 16, 17, 18, 19, + 0, 0, 0, 150, 8, 9, 10, 11, 0, 0, + 0, 0, 0, 281, 152, 153, 154, 155, 0, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 0, 0, 0, 0, 0, 31, + 32, 33, 34, 35, 36, 0, 0, 0, 40, 41, + 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 0, 56, 57, 58, 0, + 142, 60, 143, 144, 145, 146, 147, 0, 0, 148, + 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, + 0, 306, 8, 9, 10, 11, 0, 0, 0, 152, + 153, 154, 155, 0, 0, 0, 0, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 0, 0, 0, 31, 32, 33, + 34, 35, 36, 0, 0, 0, 40, 41, 0, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 0, 56, 57, 58, 0, 142, 60, + 143, 144, 145, 146, 147, 0, 0, 148, 149, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 150, 8, 9, 10, + 11, 0, 0, 0, 0, 0, 0, 152, 153, 154, + 155, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, 0, - 0, 0, 32, 33, 34, 35, 36, 37, 0, 0, - 0, 0, 0, 0, 0, 0, 46, 251, 0, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 0, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 0, - 150, 78, 151, 152, 153, 154, 155, 0, 0, 156, - 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 3, 4, 158, 6, - 7, 8, 9, 10, 11, 0, 0, 0, 0, 160, - 161, 162, 163, 0, 0, 0, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 0, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 0, 78, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, - 0, 6, 7, 8, 9, 10, 11, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 239, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 0, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 0, 78, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, - 3, 4, 0, 6, 7, 8, 9, 10, 11, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 276, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 0, 0, 31, 32, 33, 34, 35, 36, 0, 0, + 0, 40, 245, 0, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 0, 56, + 57, 58, 0, 142, 60, 143, 144, 145, 146, 147, + 0, 0, 148, 149, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 137, 2, 3, + 4, 150, 6, 7, 8, 9, 10, 11, 0, 0, + 0, 0, 152, 153, 154, 155, 0, 0, 0, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 0, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 0, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 0, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 0, 78, - 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 350, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 0, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 0, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 0, 78, 1, 2, 3, 4, 5, 6, 7, 8, + 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 0, 56, 57, 58, 59, + 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 137, 2, 3, 4, 0, 6, 7, 8, + 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 233, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 0, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 0, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 0, 56, 57, 58, 59, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 137, 2, 3, + 4, 0, 6, 7, 8, 9, 10, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 270, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 0, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 0, 56, 57, 58, 59, + 0, 60, 0, 0, 0, 0, 0, 0, 0, 116, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 344, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 0, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 0, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 0, 56, 57, 58, 59, 0, 60, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 0, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 0, 56, 57, 58, 59, + 0, 60, 137, 2, 3, 4, 0, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 0, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 0, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 0, 78, 1, 2, 3, 4, 0, 6, - 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 0, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 0, 78, 8, 9, 10, 11, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 0, 0, 0, 0, - 0, 32, 33, 34, 35, 36, 37, 0, 0, 0, - 0, 0, 0, 0, 0, 46, 47, 0, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 0, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 0, 326, - 78, 8, 9, 10, 11, 327, 0, 0, 0, 0, + 28, 0, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 0, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 0, 56, 57, 58, 59, 0, 60, 2, 3, 4, + 0, 0, 0, 8, 9, 10, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 0, 0, 0, 0, 0, 31, 32, + 33, 34, 35, 36, 0, 0, 0, 40, 41, 0, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 0, 56, 57, 58, 0, 0, + 60, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 0, 0, 0, 0, 0, 32, 33, 34, 35, - 36, 37, 0, 0, 0, 0, 0, 0, 0, 0, - 46, 47, 0, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 0, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 0, 0, 78 + 26, 0, 0, 0, 0, 0, 31, 32, 33, 34, + 35, 36, 0, 0, 0, 40, 41, 0, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 0, 56, 57, 58, 0, 320, 60, 8, + 9, 10, 11, 321, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, + 0, 0, 0, 0, 31, 32, 33, 34, 35, 36, + 0, 0, 0, 40, 41, 0, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 0, 56, 57, 58, 0, 0, 60 }; static const yytype_int16 yycheck[] = { - 0, 46, 88, 83, 230, 125, 143, 148, 88, 83, - 108, 221, 158, 129, 353, 93, 109, 142, 0, 381, - 123, 0, 142, 104, 105, 93, 94, 130, 114, 123, - 110, 359, 123, 121, 114, 172, 110, 131, 125, 130, - 122, 86, 122, 133, 131, 135, 128, 409, 122, 129, - 191, 144, 380, 131, 131, 129, 202, 125, 139, 140, - 146, 102, 103, 402, 106, 107, 146, 122, 148, 408, - 115, 116, 122, 128, 148, 122, 192, 128, 128, 204, - 131, 128, 123, 83, 204, 122, 127, 122, 88, 315, - 122, 128, 128, 230, 128, 131, 128, 131, 98, 128, - 246, 101, 131, 228, 229, 4, 5, 6, 228, 229, - 110, 191, 192, 250, 114, 128, 98, 191, 192, 98, - 93, 94, 122, 262, 263, 264, 265, 128, 274, 129, - 131, 136, 137, 138, 134, 123, 277, 121, 364, 285, - 125, 367, 93, 289, 93, 94, 146, 125, 148, 130, - 360, 131, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 123, 389, 100, 101, 96, 97, 121, 306, - 307, 130, 128, 129, 258, 259, 143, 122, 315, 125, - 121, 260, 261, 266, 267, 411, 108, 142, 131, 141, - 110, 191, 192, 318, 131, 124, 142, 277, 318, 131, - 121, 129, 121, 277, 121, 121, 121, 130, 126, 123, - 156, 157, 124, 359, 122, 125, 129, 124, 124, 130, - 124, 221, 61, 121, 124, 130, 128, 364, 121, 175, - 367, 122, 126, 130, 380, 124, 131, 374, 122, 17, - 125, 131, 130, 247, 131, 268, 371, 269, 394, 270, - 114, 371, 389, 271, 352, 272, 110, 273, 204, 114, - 5, 407, 195, 235, 400, 319, 408, 294, 380, 354, - 98, -1, -1, -1, 411, -1, -1, 277, 354, -1, - -1, -1, 228, 229, -1, 359, -1, -1, -1, -1, - -1, -1, -1, -1, 294, -1, -1, -1, -1, 385, - -1, -1, -1, -1, -1, 385, 380, -1, -1, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 384, + 0, 40, 94, 135, 150, 115, 0, 111, 115, 134, + 140, 120, 0, 70, 76, 375, 120, 353, 9, 116, + 213, 118, 104, 92, 134, 9, 1, 134, 1, 68, + 76, 77, 164, 87, 88, 106, 140, 347, 374, 224, + 106, 148, 149, 114, 404, 102, 114, 113, 194, 40, + 41, 42, 114, 183, 111, 105, 40, 41, 127, 43, + 167, 111, 108, 120, 105, 104, 111, 51, 122, 123, + 70, 196, 9, 73, 131, 184, 105, 108, 78, 183, + 184, 138, 111, 140, 78, 85, 196, 397, 106, 196, + 78, 130, 224, 403, 240, 113, 69, 106, 223, 76, + 105, 74, 102, 40, 41, 42, 111, 85, 86, 105, + 83, 111, 244, 223, 105, 111, 223, 104, 111, 108, + 120, 114, 268, 105, 309, 125, 183, 184, 106, 111, + 113, 131, 110, 279, 4, 5, 6, 283, 138, 108, + 140, 271, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 354, 137, 111, 137, 105, 114, 271, 300, 301, + 114, 111, 111, 358, 104, 114, 361, 309, 111, 111, + 305, 114, 114, 183, 184, 40, 41, 312, 9, 256, + 257, 258, 259, 76, 77, 305, 76, 77, 305, 384, + 89, 90, 312, 79, 80, 312, 105, 353, 40, 41, + 42, 83, 84, 213, 271, 119, 120, 121, 104, 40, + 41, 406, 43, 44, 111, 112, 358, 125, 374, 361, + 51, 52, 53, 9, 254, 255, 368, 252, 253, 124, + 365, 260, 261, 389, 126, 91, 93, 107, 114, 353, + 114, 104, 384, 104, 346, 365, 402, 114, 365, 104, + 112, 104, 104, 113, 40, 41, 107, 43, 44, 109, + 374, 271, 106, 106, 406, 51, 52, 53, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 288, 108, + 105, 113, 112, 107, 107, 113, 104, 113, 56, 111, + 76, 107, 113, 107, 104, 114, 105, 109, 105, 107, + 17, 114, 108, 114, 241, 262, 265, 263, 113, 264, + 103, 131, 379, 266, 96, 267, 131, 5, 187, 229, + 395, 348, 313, 403, 288, 348, 374, 78, -1, 378, + -1, -1, -1, -1, -1, -1, -1, 347, 348, -1, + -1, -1, -1, 353, 354, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 353, 354, -1, -1, -1, -1, 359, - 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 318, -1, -1, -1, -1, -1, -1, -1, - 380, -1, -1, -1, -1, 385, -1, -1, -1, -1, + -1, -1, -1, -1, 374, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 402, -1, -1, -1, -1, -1, 408, -1, - -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 371, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, -1, -1, - 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 121, - -1, -1, -1, 125, 126, -1, -1, -1, -1, 131, - 132, 133, 134, 135, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, 397, -1, -1, + -1, -1, -1, 403, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 39, 40, 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 121, -1, -1, -1, 125, 126, -1, -1, - -1, -1, 131, 132, 133, 134, 135, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, -1, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, -1, -1, 102, 103, -1, -1, + 69, 70, -1, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 121, -1, -1, -1, 125, - -1, -1, -1, -1, -1, 131, 132, 133, 134, 135, + -1, -1, -1, -1, -1, 104, -1, -1, -1, 108, + 109, -1, -1, -1, -1, 114, 115, 116, 117, 118, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 33, 34, 35, 36, 37, 38, 39, 40, 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, -1, -1, 102, - 103, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 121, -1, - -1, -1, 125, -1, -1, -1, -1, -1, 131, 132, - 133, 134, 135, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, -1, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - -1, -1, 102, 103, -1, -1, -1, -1, -1, -1, + 63, 64, 65, 66, 67, 68, 69, 70, -1, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 121, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 131, 132, 133, 134, 135, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 25, 26, + -1, 104, -1, -1, -1, 108, 109, -1, -1, -1, + -1, 114, 115, 116, 117, 118, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 37, 38, 39, 40, 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, -1, -1, 102, 103, -1, -1, -1, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 4, 5, 6, 121, 8, 9, 10, 11, 12, - 13, -1, -1, -1, 131, 132, 133, 134, 135, -1, - -1, -1, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, -1, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, -1, -1, 102, - 103, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3, 4, 5, 6, 121, 8, - 9, 10, 11, 12, 13, -1, -1, -1, -1, 132, - 133, 134, 135, -1, -1, -1, 25, 26, 27, 28, + -1, -1, -1, -1, -1, -1, -1, 104, -1, -1, + -1, 108, -1, -1, -1, -1, -1, 114, 115, 116, + 117, 118, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, -1, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 104, -1, -1, -1, 108, -1, -1, + -1, -1, -1, 114, 115, 116, 117, 118, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, -1, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, -1, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, -1, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, -1, -1, + 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 114, + 115, 116, 117, 118, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, -1, -1, 10, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 39, 40, 41, -1, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, -1, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, -1, -1, 85, 86, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 3, 4, 5, 6, 104, 8, 9, 10, 11, + 12, 13, -1, -1, -1, 114, 115, 116, 117, 118, -1, -1, -1, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - -1, -1, 131, 45, 46, 47, 48, 49, 50, -1, - -1, -1, -1, -1, -1, -1, -1, 59, 60, -1, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - -1, 93, 94, 95, 96, 97, 98, 99, -1, -1, - 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 121, - -1, -1, 124, 10, 11, 12, 13, -1, -1, -1, - 132, 133, 134, 135, -1, -1, -1, -1, 25, 26, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, -1, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, -1, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, -1, -1, 85, 86, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, + -1, -1, 104, 10, 11, 12, 13, -1, -1, -1, + -1, -1, -1, 115, 116, 117, 118, -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, 45, 46, - 47, 48, 49, 50, -1, -1, -1, -1, -1, -1, - -1, -1, 59, 60, -1, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, -1, 93, 94, 95, 96, - 97, 98, 99, -1, -1, 102, 103, -1, -1, -1, + 47, 48, 49, 50, -1, -1, -1, 54, 55, -1, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, + 77, -1, -1, 10, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, -1, -1, -1, -1, 114, 45, 46, + 47, 48, 49, 50, -1, -1, -1, 54, 55, -1, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, + 77, 78, 79, 80, 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 121, -1, -1, 124, 10, 11, - 12, 13, -1, -1, -1, 132, 133, 134, 135, -1, - -1, -1, -1, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - -1, -1, -1, 45, 46, 47, 48, 49, 50, -1, - -1, -1, -1, -1, -1, -1, -1, 59, 60, -1, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - -1, 93, 94, 95, 96, 97, 98, 99, -1, -1, - 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 121, - 10, 11, 12, 13, -1, -1, -1, -1, -1, 131, - 132, 133, 134, 135, -1, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, - 50, -1, -1, -1, -1, -1, -1, -1, -1, 59, - 60, -1, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, -1, 93, 94, 95, 96, 97, 98, 99, - -1, -1, 102, 103, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 104, -1, -1, + 107, 10, 11, 12, 13, -1, -1, -1, 115, 116, + 117, 118, -1, -1, -1, -1, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, + 49, 50, -1, -1, -1, 54, 55, -1, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, -1, 76, 77, 78, + 79, 80, 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 121, -1, -1, 124, 10, 11, 12, 13, -1, - -1, -1, 132, 133, 134, 135, -1, -1, -1, -1, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, - 45, 46, 47, 48, 49, 50, -1, -1, -1, -1, - -1, -1, -1, -1, 59, 60, -1, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, -1, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, -1, 93, 94, - 95, 96, 97, 98, 99, -1, -1, 102, 103, -1, + -1, -1, -1, -1, -1, 104, -1, -1, 107, 10, + 11, 12, 13, -1, -1, -1, 115, 116, 117, 118, + -1, -1, -1, -1, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, + -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, + -1, -1, -1, 54, 55, -1, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + -1, 72, 73, 74, -1, 76, 77, 78, 79, 80, + 81, 82, -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 121, 10, 11, 12, - 13, -1, -1, -1, -1, -1, -1, 132, 133, 134, - 135, -1, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, -1, 104, 10, 11, 12, 13, -1, -1, + -1, -1, -1, 114, 115, 116, 117, 118, -1, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, -1, -1, -1, -1, -1, 45, + 46, 47, 48, 49, 50, -1, -1, -1, 54, 55, + -1, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, -1, 72, 73, 74, -1, + 76, 77, 78, 79, 80, 81, 82, -1, -1, 85, + 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 104, -1, + -1, 107, 10, 11, 12, 13, -1, -1, -1, 115, + 116, 117, 118, -1, -1, -1, -1, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, -1, -1, -1, -1, -1, 45, 46, 47, + 48, 49, 50, -1, -1, -1, 54, 55, -1, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, -1, 72, 73, 74, -1, 76, 77, + 78, 79, 80, 81, 82, -1, -1, 85, 86, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 104, 10, 11, 12, + 13, -1, -1, -1, -1, -1, -1, 115, 116, 117, + 118, -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, -1, -1, - -1, -1, -1, -1, -1, -1, 59, 60, -1, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, -1, - 93, 94, 95, 96, 97, 98, 99, -1, -1, 102, - 103, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3, 4, 5, 6, 121, 8, - 9, 10, 11, 12, 13, -1, -1, -1, -1, 132, - 133, 134, 135, -1, -1, -1, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, - -1, 8, 9, 10, 11, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 126, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, -1, 94, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, 6, -1, 8, 9, 10, 11, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 126, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, -1, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, -1, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, - -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 126, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, -1, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, -1, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - -1, 94, 3, 4, 5, 6, 7, 8, 9, 10, + -1, 54, 55, -1, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, -1, 72, + 73, 74, -1, 76, 77, 78, 79, 80, 81, 82, + -1, -1, 85, 86, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, + 6, 104, 8, 9, 10, 11, 12, 13, -1, -1, + -1, -1, 115, 116, 117, 118, -1, -1, -1, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + -1, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, -1, 72, 73, 74, 75, + -1, 77, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 3, 4, 5, 6, -1, 8, 9, 10, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 109, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, -1, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + -1, 72, 73, 74, 75, -1, 77, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, + 6, -1, 8, 9, 10, 11, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 109, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + -1, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, -1, 72, 73, 74, 75, + -1, 77, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 109, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, -1, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + -1, 72, 73, 74, 75, -1, 77, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + -1, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, -1, 72, 73, 74, 75, + -1, 77, 3, 4, 5, 6, -1, 8, 9, 10, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - -1, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, -1, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, -1, 94, 3, 4, 5, 6, -1, 8, - 9, 10, 11, 12, 13, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 10, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, -1, -1, -1, -1, - -1, 45, 46, 47, 48, 49, 50, -1, -1, -1, - -1, -1, -1, -1, -1, 59, 60, -1, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, -1, 93, - 94, 10, 11, 12, 13, 99, -1, -1, -1, -1, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, -1, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + -1, 72, 73, 74, 75, -1, 77, 4, 5, 6, + -1, -1, -1, 10, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, -1, -1, -1, -1, -1, 45, 46, + 47, 48, 49, 50, -1, -1, -1, 54, 55, -1, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, -1, 72, 73, 74, -1, -1, + 77, 10, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, -1, -1, -1, 45, 46, 47, 48, - 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, - 59, 60, -1, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, -1, -1, 94 + 49, 50, -1, -1, -1, 54, 55, -1, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, -1, 76, 77, 10, + 11, 12, 13, 82, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, + -1, -1, -1, -1, 45, 46, 47, 48, 49, 50, + -1, -1, -1, 54, 55, -1, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + -1, 72, 73, 74, -1, -1, 77 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1580,81 +1484,79 @@ static const yytype_uint8 yystos[] = { 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 94, 177, - 178, 179, 180, 181, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 198, 199, 200, 235, 236, - 237, 194, 93, 94, 125, 146, 121, 131, 238, 122, - 128, 182, 183, 184, 189, 193, 128, 131, 93, 146, - 93, 131, 176, 191, 193, 123, 0, 236, 198, 202, - 125, 93, 196, 197, 125, 218, 183, 182, 184, 146, - 146, 121, 123, 130, 125, 131, 189, 193, 203, 204, - 93, 95, 96, 97, 98, 99, 102, 103, 121, 124, - 132, 133, 134, 135, 147, 148, 149, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 175, 198, - 131, 203, 201, 130, 122, 128, 14, 15, 16, 18, - 19, 20, 21, 22, 23, 24, 61, 125, 126, 131, - 158, 171, 172, 174, 177, 178, 198, 208, 209, 210, - 211, 219, 220, 221, 223, 225, 227, 234, 123, 123, - 130, 124, 175, 172, 207, 193, 146, 205, 206, 126, - 204, 158, 158, 174, 102, 103, 123, 127, 122, 122, - 128, 60, 172, 121, 158, 136, 137, 138, 133, 135, - 100, 101, 104, 105, 139, 140, 106, 107, 143, 142, - 141, 108, 110, 109, 144, 124, 126, 203, 96, 97, - 197, 131, 131, 229, 121, 121, 131, 131, 174, 121, - 175, 129, 121, 126, 212, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 130, 173, 128, 131, 126, - 209, 175, 124, 175, 207, 130, 124, 205, 123, 128, - 131, 93, 131, 122, 150, 174, 93, 99, 153, 172, - 158, 158, 158, 160, 160, 161, 161, 162, 162, 162, - 162, 163, 163, 164, 165, 166, 167, 168, 169, 174, - 126, 215, 216, 217, 230, 174, 131, 174, 129, 228, - 219, 172, 172, 124, 130, 124, 207, 130, 131, 175, - 206, 123, 131, 124, 129, 61, 218, 210, 208, 220, - 231, 122, 122, 174, 187, 189, 226, 213, 207, 130, - 207, 124, 175, 172, 121, 226, 232, 233, 215, 222, - 224, 146, 122, 126, 207, 124, 174, 131, 122, 17, - 211, 130, 210, 214, 218, 131, 122, 174, 214, 215, - 207, 131 + 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, + 77, 160, 161, 162, 163, 164, 169, 170, 171, 172, + 174, 175, 176, 177, 178, 181, 182, 183, 218, 219, + 220, 44, 76, 172, 175, 177, 40, 41, 76, 77, + 108, 129, 104, 114, 221, 105, 111, 9, 40, 41, + 42, 166, 167, 173, 111, 114, 76, 129, 175, 76, + 114, 159, 176, 181, 175, 106, 0, 219, 175, 181, + 185, 108, 76, 179, 180, 108, 201, 166, 165, 168, + 176, 167, 129, 104, 106, 113, 108, 3, 174, 176, + 186, 187, 76, 78, 79, 80, 81, 82, 85, 86, + 104, 107, 115, 116, 117, 118, 130, 131, 132, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 158, 181, 114, 186, 184, 113, 105, 111, 14, 15, + 16, 18, 19, 20, 21, 22, 23, 24, 56, 108, + 109, 114, 141, 154, 155, 157, 160, 161, 181, 191, + 192, 193, 194, 202, 203, 204, 206, 208, 210, 217, + 129, 165, 168, 106, 113, 107, 158, 155, 190, 176, + 129, 188, 189, 109, 187, 141, 141, 157, 85, 86, + 106, 110, 105, 105, 111, 55, 155, 104, 141, 119, + 120, 121, 116, 118, 83, 84, 87, 88, 122, 123, + 89, 90, 126, 125, 124, 91, 93, 92, 127, 107, + 109, 186, 79, 80, 180, 114, 114, 212, 104, 104, + 114, 114, 157, 104, 158, 112, 104, 109, 195, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 113, + 156, 111, 114, 109, 192, 106, 107, 158, 190, 113, + 107, 188, 106, 111, 114, 76, 114, 105, 133, 157, + 76, 82, 136, 155, 141, 141, 141, 143, 143, 144, + 144, 145, 145, 145, 145, 146, 146, 147, 148, 149, + 150, 151, 152, 157, 109, 198, 199, 200, 213, 157, + 114, 157, 112, 211, 202, 155, 155, 158, 113, 107, + 190, 113, 114, 158, 189, 106, 114, 107, 112, 56, + 201, 193, 191, 203, 214, 105, 105, 157, 171, 174, + 209, 196, 107, 190, 113, 190, 107, 158, 155, 104, + 209, 215, 216, 198, 205, 207, 129, 105, 109, 190, + 107, 157, 114, 105, 17, 194, 113, 193, 197, 201, + 114, 105, 157, 197, 198, 190, 114 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 145, 146, 146, 147, 148, 148, 148, 148, 148, - 148, 149, 149, 149, 149, 149, 149, 150, 151, 152, - 152, 153, 153, 154, 154, 155, 155, 156, 157, 157, - 157, 158, 158, 158, 158, 159, 159, 159, 159, 160, - 160, 160, 160, 161, 161, 161, 162, 162, 162, 163, - 163, 163, 163, 163, 164, 164, 164, 165, 165, 166, - 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, - 171, 172, 172, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 174, 174, 175, 176, 177, 177, - 177, 177, 177, 177, 177, 177, 178, 179, 179, 180, - 180, 181, 182, 182, 183, 183, 183, 183, 184, 185, - 185, 185, 185, 185, 185, 186, 186, 186, 186, 186, - 186, 187, 187, 188, 188, 189, 189, 190, 191, 191, - 191, 191, 191, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 193, 194, 194, 194, - 195, 196, 196, 197, 197, 197, 198, 198, 198, 199, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, - 199, 199, 199, 199, 199, 199, 201, 200, 202, 200, - 203, 203, 204, 204, 205, 205, 206, 206, 207, 208, - 209, 209, 210, 210, 210, 210, 210, 210, 210, 211, - 212, 213, 211, 214, 214, 216, 215, 217, 215, 218, - 218, 219, 219, 220, 220, 221, 222, 222, 224, 223, - 225, 225, 226, 226, 228, 227, 229, 227, 230, 227, - 231, 231, 232, 232, 233, 233, 234, 234, 234, 234, - 234, 235, 235, 236, 236, 238, 237 + 0, 128, 129, 129, 130, 131, 131, 131, 131, 131, + 131, 132, 132, 132, 132, 132, 132, 133, 134, 135, + 135, 136, 136, 137, 137, 138, 138, 139, 140, 140, + 140, 141, 141, 141, 141, 142, 142, 142, 142, 143, + 143, 143, 143, 144, 144, 144, 145, 145, 145, 146, + 146, 146, 146, 146, 147, 147, 147, 148, 148, 149, + 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, + 154, 155, 155, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 157, 157, 158, 159, 160, 160, + 160, 160, 160, 160, 160, 161, 162, 162, 163, 163, + 164, 165, 165, 166, 166, 166, 166, 167, 167, 167, + 167, 168, 169, 169, 169, 169, 169, 169, 170, 170, + 170, 170, 170, 170, 170, 171, 171, 172, 172, 173, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 175, 175, 175, 175, 175, 175, 176, 176, 177, 177, + 177, 178, 179, 179, 180, 180, 180, 181, 181, 181, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 184, 183, 185, 183, 186, + 186, 187, 187, 188, 188, 189, 189, 190, 191, 192, + 192, 193, 193, 193, 193, 193, 193, 193, 194, 195, + 196, 194, 197, 197, 199, 198, 200, 198, 201, 201, + 202, 202, 203, 203, 204, 205, 205, 207, 206, 208, + 208, 209, 209, 211, 210, 212, 210, 213, 210, 214, + 214, 215, 215, 216, 216, 217, 217, 217, 217, 217, + 218, 218, 219, 219, 221, 220 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -1669,26 +1571,25 @@ static const yytype_uint8 yyr2[] = 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 2, 2, - 4, 5, 6, 9, 2, 3, 2, 1, 1, 2, - 3, 3, 2, 5, 2, 1, 2, 1, 1, 1, - 3, 6, 7, 8, 5, 1, 2, 5, 6, 7, - 4, 1, 2, 1, 1, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 3, 1, 3, 3, 1, 3, 4, 1, + 4, 5, 6, 9, 2, 2, 1, 1, 2, 3, + 3, 2, 5, 3, 2, 3, 2, 0, 1, 1, + 1, 1, 1, 3, 6, 7, 8, 5, 1, 2, + 5, 6, 7, 4, 2, 1, 2, 1, 1, 1, + 1, 1, 2, 1, 2, 1, 1, 2, 2, 3, + 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, + 1, 4, 1, 3, 1, 3, 3, 1, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 6, 0, 5, - 1, 2, 3, 4, 1, 3, 1, 4, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, - 3, 1, 2, 1, 2, 5, 3, 1, 0, 6, - 3, 2, 1, 4, 0, 6, 0, 8, 0, 7, - 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, - 2, 1, 2, 1, 1, 0, 3 + 1, 1, 1, 1, 1, 0, 6, 0, 5, 1, + 2, 3, 4, 1, 3, 1, 4, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, + 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, + 1, 2, 1, 2, 5, 3, 1, 0, 6, 3, + 2, 1, 4, 0, 6, 0, 8, 0, 7, 1, + 1, 1, 0, 2, 3, 2, 2, 2, 3, 2, + 1, 2, 1, 1, 0, 3 }; @@ -2664,7 +2565,7 @@ yyreduce: const TType *type = new TType((yyvsp[0].interm.intermTypedNode)->getType()); (yyvsp[-1].interm.function)->addParameter(TConstParameter(type)); (yyval.interm).function = (yyvsp[-1].interm.function); - (yyval.interm).nodePair.node1 = TIntermediate::MakeAggregate((yyvsp[0].interm.intermTypedNode), (yylsp[0])); + (yyval.interm).nodePair.node1 = context->intermediate.makeAggregate((yyvsp[0].interm.intermTypedNode), (yylsp[0])); } break; @@ -3165,7 +3066,10 @@ yyreduce: case 89: { - (yyval.interm.intermNode) = (yyvsp[-1].interm).intermDeclaration; + TIntermAggregate *aggNode = (yyvsp[-1].interm).intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + (yyval.interm.intermNode) = aggNode; } break; @@ -3177,7 +3081,7 @@ yyreduce: context->error((yylsp[-3]), "precision is not supported in fragment shader", "highp"); } if (!context->symbolTable.setDefaultPrecision( (yyvsp[-1].interm.type), (yyvsp[-2].interm.precision) )) { - context->error((yylsp[-3]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[-1].interm.type).getBasicType())); + context->error((yylsp[-3]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[-1].interm.type).type)); } (yyval.interm.intermNode) = 0; } @@ -3187,8 +3091,8 @@ yyreduce: case 91: { - ES3_OR_NEWER((yyvsp[-3].lex).string->c_str(), (yylsp[-4]), "interface blocks"); - (yyval.interm.intermNode) = context->addInterfaceBlock(*(yyvsp[-4].interm.typeQualifierBuilder), (yylsp[-3]), *(yyvsp[-3].lex).string, (yyvsp[-2].interm.fieldList), NULL, (yyloc), NULL, (yyloc)); + ES3_OR_NEWER(getQualifierString((yyvsp[-4].interm.type).qualifier), (yylsp[-4]), "interface blocks"); + (yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[-4].interm.type), (yylsp[-3]), *(yyvsp[-3].lex).string, (yyvsp[-2].interm.fieldList), NULL, (yyloc), NULL, (yyloc)); } break; @@ -3196,8 +3100,8 @@ yyreduce: case 92: { - ES3_OR_NEWER((yyvsp[-4].lex).string->c_str(), (yylsp[-5]), "interface blocks"); - (yyval.interm.intermNode) = context->addInterfaceBlock(*(yyvsp[-5].interm.typeQualifierBuilder), (yylsp[-4]), *(yyvsp[-4].lex).string, (yyvsp[-3].interm.fieldList), (yyvsp[-1].lex).string, (yylsp[-1]), NULL, (yyloc)); + ES3_OR_NEWER(getQualifierString((yyvsp[-5].interm.type).qualifier), (yylsp[-5]), "interface blocks"); + (yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[-5].interm.type), (yylsp[-4]), *(yyvsp[-4].lex).string, (yyvsp[-3].interm.fieldList), (yyvsp[-1].lex).string, (yylsp[-1]), NULL, (yyloc)); } break; @@ -3205,8 +3109,8 @@ yyreduce: case 93: { - ES3_OR_NEWER((yyvsp[-7].lex).string->c_str(), (yylsp[-8]), "interface blocks"); - (yyval.interm.intermNode) = context->addInterfaceBlock(*(yyvsp[-8].interm.typeQualifierBuilder), (yylsp[-7]), *(yyvsp[-7].lex).string, (yyvsp[-6].interm.fieldList), (yyvsp[-4].lex).string, (yylsp[-4]), (yyvsp[-2].interm.intermTypedNode), (yylsp[-3])); + ES3_OR_NEWER(getQualifierString((yyvsp[-8].interm.type).qualifier), (yylsp[-8]), "interface blocks"); + (yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[-8].interm.type), (yylsp[-7]), *(yyvsp[-7].lex).string, (yyvsp[-6].interm.fieldList), (yyvsp[-4].lex).string, (yylsp[-4]), (yyvsp[-2].interm.intermTypedNode), (yylsp[-3])); } break; @@ -3214,7 +3118,7 @@ yyreduce: case 94: { - context->parseGlobalLayoutQualifier(*(yyvsp[-1].interm.typeQualifierBuilder)); + context->parseGlobalLayoutQualifier((yyvsp[-1].interm.type)); (yyval.interm.intermNode) = 0; } @@ -3223,7 +3127,7 @@ yyreduce: case 95: { - (yyval.interm.intermNode) = context->parseInvariantDeclaration(*(yyvsp[-2].interm.typeQualifierBuilder), (yylsp[-1]), (yyvsp[-1].lex).string, (yyvsp[-1].lex).symbol); + (yyval.interm).function = context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function)); } break; @@ -3231,8 +3135,7 @@ yyreduce: case 96: { - (yyval.interm).function = context->parseFunctionDeclarator((yylsp[0]), (yyvsp[-1].interm.function)); - context->exitFunctionDeclaration(); + (yyval.interm.function) = (yyvsp[0].interm.function); } break; @@ -3248,14 +3151,6 @@ yyreduce: case 98: { - (yyval.interm.function) = (yyvsp[0].interm.function); - } - - break; - - case 99: - - { // Add the parameter (yyval.interm.function) = (yyvsp[-1].interm.function); if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid) @@ -3266,7 +3161,7 @@ yyreduce: break; - case 100: + case 99: { // @@ -3288,21 +3183,20 @@ yyreduce: break; - case 101: + case 100: { (yyval.interm.function) = context->parseFunctionHeader((yyvsp[-2].interm.type), (yyvsp[-1].lex).string, (yylsp[-1])); context->symbolTable.push(); - context->enterFunctionDeclaration(); } break; - case 102: + case 101: { - if ((yyvsp[-1].interm.type).getBasicType() == EbtVoid) { + if ((yyvsp[-1].interm.type).type == EbtVoid) { context->error((yylsp[0]), "illegal use of type 'void'", (yyvsp[0].lex).string->c_str()); } context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string); @@ -3312,7 +3206,7 @@ yyreduce: break; - case 103: + case 102: { // Check that we can make an array out of this type @@ -3331,11 +3225,21 @@ yyreduce: break; + case 103: + + { + (yyval.interm) = (yyvsp[0].interm); + context->checkIsParameterQualifierValid((yylsp[0]), (yyvsp[-2].interm.qualifier), (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); + } + + break; + case 104: { (yyval.interm) = (yyvsp[0].interm); - context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm).param.type); + context->checkOutParameterIsNotSampler((yylsp[0]), (yyvsp[-1].interm.qualifier), *(yyvsp[0].interm).param.type); + context->checkIsParameterQualifierValid((yylsp[0]), EvqTemporary, (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); } break; @@ -3344,7 +3248,7 @@ yyreduce: { (yyval.interm) = (yyvsp[0].interm); - (yyval.interm).param.type->setQualifier(EvqIn); + context->checkIsParameterQualifierValid((yylsp[0]), (yyvsp[-2].interm.qualifier), (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); } break; @@ -3353,7 +3257,8 @@ yyreduce: { (yyval.interm) = (yyvsp[0].interm); - context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm).param.type); + context->checkOutParameterIsNotSampler((yylsp[0]), (yyvsp[-1].interm.qualifier), *(yyvsp[0].interm).param.type); + context->checkIsParameterQualifierValid((yylsp[0]), EvqTemporary, (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); } break; @@ -3361,8 +3266,7 @@ yyreduce: case 107: { - (yyval.interm) = (yyvsp[0].interm); - (yyval.interm).param.type->setQualifier(EvqIn); + (yyval.interm.qualifier) = EvqIn; } break; @@ -3370,8 +3274,7 @@ yyreduce: case 108: { - TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; - (yyval.interm).param = param; + (yyval.interm.qualifier) = EvqIn; } break; @@ -3379,7 +3282,7 @@ yyreduce: case 109: { - (yyval.interm) = (yyvsp[0].interm); + (yyval.interm.qualifier) = EvqOut; } break; @@ -3387,8 +3290,7 @@ yyreduce: case 110: { - (yyval.interm) = (yyvsp[-2].interm); - context->parseDeclarator((yyval.interm).type, (yylsp[0]), *(yyvsp[0].lex).string, (yyval.interm).intermDeclaration); + (yyval.interm.qualifier) = EvqInOut; } break; @@ -3396,8 +3298,8 @@ yyreduce: case 111: { - (yyval.interm) = (yyvsp[-5].interm); - context->parseArrayDeclarator((yyval.interm).type, (yylsp[-3]), *(yyvsp[-3].lex).string, (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode), (yyval.interm).intermDeclaration); + TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; + (yyval.interm).param = param; } break; @@ -3405,9 +3307,7 @@ yyreduce: case 112: { - ES3_OR_NEWER("[]", (yylsp[-4]), "implicitly sized array"); - (yyval.interm) = (yyvsp[-6].interm); - context->parseArrayInitDeclarator((yyval.interm).type, (yylsp[-4]), *(yyvsp[-4].lex).string, (yylsp[-3]), nullptr, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration); + (yyval.interm) = (yyvsp[0].interm); } break; @@ -3415,9 +3315,8 @@ yyreduce: case 113: { - ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)"); - (yyval.interm) = (yyvsp[-7].interm); - context->parseArrayInitDeclarator((yyval.interm).type, (yylsp[-5]), *(yyvsp[-5].lex).string, (yylsp[-4]), (yyvsp[-3].interm.intermTypedNode), (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration); + (yyval.interm) = (yyvsp[-2].interm); + (yyval.interm).intermAggregate = context->parseDeclarator((yyval.interm).type, (yyvsp[-2].interm).intermAggregate, (yylsp[0]), *(yyvsp[0].lex).string); } break; @@ -3425,8 +3324,8 @@ yyreduce: case 114: { - (yyval.interm) = (yyvsp[-4].interm); - context->parseInitDeclarator((yyval.interm).type, (yylsp[-2]), *(yyvsp[-2].lex).string, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode), (yyval.interm).intermDeclaration); + (yyval.interm) = (yyvsp[-5].interm); + (yyval.interm).intermAggregate = context->parseArrayDeclarator((yyval.interm).type, (yyvsp[-5].interm).intermAggregate, (yylsp[-3]), *(yyvsp[-3].lex).string, (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); } break; @@ -3434,8 +3333,9 @@ yyreduce: case 115: { - (yyval.interm).type = (yyvsp[0].interm.type); - (yyval.interm).intermDeclaration = context->parseSingleDeclaration((yyval.interm).type, (yylsp[0]), ""); + ES3_OR_NEWER("[]", (yylsp[-4]), "implicitly sized array"); + (yyval.interm) = (yyvsp[-6].interm); + (yyval.interm).intermAggregate = context->parseArrayInitDeclarator((yyval.interm).type, (yyvsp[-6].interm).intermAggregate, (yylsp[-4]), *(yyvsp[-4].lex).string, (yylsp[-3]), nullptr, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); } break; @@ -3443,8 +3343,9 @@ yyreduce: case 116: { - (yyval.interm).type = (yyvsp[-1].interm.type); - (yyval.interm).intermDeclaration = context->parseSingleDeclaration((yyval.interm).type, (yylsp[0]), *(yyvsp[0].lex).string); + ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)"); + (yyval.interm) = (yyvsp[-7].interm); + (yyval.interm).intermAggregate = context->parseArrayInitDeclarator((yyval.interm).type, (yyvsp[-7].interm).intermAggregate, (yylsp[-5]), *(yyvsp[-5].lex).string, (yylsp[-4]), (yyvsp[-3].interm.intermTypedNode), (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); } break; @@ -3452,8 +3353,8 @@ yyreduce: case 117: { - (yyval.interm).type = (yyvsp[-4].interm.type); - (yyval.interm).intermDeclaration = context->parseSingleArrayDeclaration((yyval.interm).type, (yylsp[-3]), *(yyvsp[-3].lex).string, (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); + (yyval.interm) = (yyvsp[-4].interm); + (yyval.interm).intermAggregate = context->parseInitDeclarator((yyval.interm).type, (yyvsp[-4].interm).intermAggregate, (yylsp[-2]), *(yyvsp[-2].lex).string, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); } break; @@ -3461,9 +3362,8 @@ yyreduce: case 118: { - ES3_OR_NEWER("[]", (yylsp[-3]), "implicitly sized array"); - (yyval.interm).type = (yyvsp[-5].interm.type); - (yyval.interm).intermDeclaration = context->parseSingleArrayInitDeclaration((yyval.interm).type, (yylsp[-4]), *(yyvsp[-4].lex).string, (yylsp[-3]), nullptr, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).type = (yyvsp[0].interm.type); + (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yylsp[0]), ""); } break; @@ -3471,9 +3371,8 @@ yyreduce: case 119: { - ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)"); - (yyval.interm).type = (yyvsp[-6].interm.type); - (yyval.interm).intermDeclaration = context->parseSingleArrayInitDeclaration((yyval.interm).type, (yylsp[-5]), *(yyvsp[-5].lex).string, (yylsp[-4]), (yyvsp[-3].interm.intermTypedNode), (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).type = (yyvsp[-1].interm.type); + (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yylsp[0]), *(yyvsp[0].lex).string); } break; @@ -3481,8 +3380,8 @@ yyreduce: case 120: { - (yyval.interm).type = (yyvsp[-3].interm.type); - (yyval.interm).intermDeclaration = context->parseSingleInitDeclaration((yyval.interm).type, (yylsp[-2]), *(yyvsp[-2].lex).string, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); + (yyval.interm).type = (yyvsp[-4].interm.type); + (yyval.interm).intermAggregate = context->parseSingleArrayDeclaration((yyval.interm).type, (yylsp[-3]), *(yyvsp[-3].lex).string, (yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); } break; @@ -3490,8 +3389,9 @@ yyreduce: case 121: { - context->addFullySpecifiedType(&(yyvsp[0].interm.type)); - (yyval.interm.type) = (yyvsp[0].interm.type); + ES3_OR_NEWER("[]", (yylsp[-3]), "implicitly sized array"); + (yyval.interm).type = (yyvsp[-5].interm.type); + (yyval.interm).intermAggregate = context->parseSingleArrayInitDeclaration((yyval.interm).type, (yylsp[-4]), *(yyvsp[-4].lex).string, (yylsp[-3]), nullptr, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); } break; @@ -3499,7 +3399,9 @@ yyreduce: case 122: { - (yyval.interm.type) = context->addFullySpecifiedType(*(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.type)); + ES3_OR_NEWER("=", (yylsp[-1]), "first-class arrays (array initializer)"); + (yyval.interm).type = (yyvsp[-6].interm.type); + (yyval.interm).intermAggregate = context->parseSingleArrayInitDeclaration((yyval.interm).type, (yylsp[-5]), *(yyvsp[-5].lex).string, (yylsp[-4]), (yyvsp[-3].interm.intermTypedNode), (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); } break; @@ -3507,7 +3409,8 @@ yyreduce: case 123: { - (yyval.interm.qualifier) = EvqSmooth; + (yyval.interm).type = (yyvsp[-3].interm.type); + (yyval.interm).intermAggregate = context->parseSingleInitDeclaration((yyval.interm).type, (yylsp[-2]), *(yyvsp[-2].lex).string, (yylsp[-1]), (yyvsp[0].interm.intermTypedNode)); } break; @@ -3515,7 +3418,8 @@ yyreduce: case 124: { - (yyval.interm.qualifier) = EvqFlat; + // $$.type is not used in invariant declarations. + (yyval.interm).intermAggregate = context->parseInvariantDeclaration((yylsp[-1]), (yylsp[0]), (yyvsp[0].lex).string, (yyvsp[0].lex).symbol); } break; @@ -3523,8 +3427,14 @@ yyreduce: case 125: { - (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0])); - (yyval.interm.typeQualifierBuilder)->appendQualifier((yyvsp[0].interm.qualifierWrapper)); + (yyval.interm.type) = (yyvsp[0].interm.type); + + if ((yyvsp[0].interm.type).array) { + ES3_OR_NEWER("[]", (yylsp[0]), "first-class-array"); + if (context->getShaderVersion() != 300) { + (yyvsp[0].interm.type).clearArrayness(); + } + } } break; @@ -3532,8 +3442,7 @@ yyreduce: case 126: { - (yyval.interm.typeQualifierBuilder) = (yyvsp[-1].interm.typeQualifierBuilder); - (yyval.interm.typeQualifierBuilder)->appendQualifier((yyvsp[0].interm.qualifierWrapper)); + (yyval.interm.type) = context->addFullySpecifiedType((yyvsp[-1].interm.type).qualifier, (yyvsp[-1].interm.type).invariant, (yyvsp[-1].interm.type).layoutQualifier, (yyvsp[0].interm.type)); } break; @@ -3541,7 +3450,7 @@ yyreduce: case 127: { - // empty + (yyval.interm.type).qualifier = EvqSmooth; } break; @@ -3549,8 +3458,7 @@ yyreduce: case 128: { - context->checkLocalVariableConstStorageQualifier(*(yyvsp[0].interm.qualifierWrapper)); - (yyval.interm.qualifierWrapper) = (yyvsp[0].interm.qualifierWrapper); + (yyval.interm.type).qualifier = EvqFlat; } break; @@ -3558,8 +3466,7 @@ yyreduce: case 129: { - context->checkIsAtGlobalLevel((yylsp[0]), "layout"); - (yyval.interm.qualifierWrapper) = new TLayoutQualifierWrapper((yyvsp[0].interm.layoutQualifier), (yylsp[0])); + (yyval.interm.qualifier) = EvqConst; } break; @@ -3567,7 +3474,10 @@ yyreduce: case 130: { - (yyval.interm.qualifierWrapper) = new TPrecisionQualifierWrapper((yyvsp[0].interm.precision), (yylsp[0])); + VERTEX_ONLY("attribute", (yylsp[0])); + ES2_ONLY("attribute", (yylsp[0])); + context->checkIsAtGlobalLevel((yylsp[0]), "attribute"); + (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yylsp[0])); } break; @@ -3575,7 +3485,12 @@ yyreduce: case 131: { - (yyval.interm.qualifierWrapper) = new TInterpolationQualifierWrapper((yyvsp[0].interm.qualifier), (yylsp[0])); + ES2_ONLY("varying", (yylsp[0])); + context->checkIsAtGlobalLevel((yylsp[0]), "varying"); + if (context->getShaderType() == GL_VERTEX_SHADER) + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[0])); + else + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[0])); } break; @@ -3583,8 +3498,13 @@ yyreduce: case 132: { - context->checkIsAtGlobalLevel((yylsp[0]), "invariant"); - (yyval.interm.qualifierWrapper) = new TInvariantQualifierWrapper((yylsp[0])); + ES2_ONLY("varying", (yylsp[-1])); + context->checkIsAtGlobalLevel((yylsp[-1]), "invariant varying"); + if (context->getShaderType() == GL_VERTEX_SHADER) + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[-1])); + else + (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[-1])); + (yyval.interm.type).invariant = true; } break; @@ -3592,10 +3512,11 @@ yyreduce: case 133: { - VERTEX_ONLY("attribute", (yylsp[0])); - ES2_ONLY("attribute", (yylsp[0])); - context->checkIsAtGlobalLevel((yylsp[0]), "attribute"); - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqAttribute, (yylsp[0])); + if ((yyvsp[0].interm.type).qualifier != EvqConst && !context->symbolTable.atGlobalLevel()) + { + context->error((yylsp[0]), "Local variables can only use the const storage qualifier.", getQualifierString((yyvsp[0].interm.type).qualifier)); + } + (yyval.interm.type).setBasic(EbtVoid, (yyvsp[0].interm.type).qualifier, (yylsp[0])); } break; @@ -3603,12 +3524,7 @@ yyreduce: case 134: { - ES2_ONLY("varying", (yylsp[0])); - context->checkIsAtGlobalLevel((yylsp[0]), "varying"); - if (context->getShaderType() == GL_VERTEX_SHADER) - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVaryingOut, (yylsp[0])); - else - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVaryingIn, (yylsp[0])); + (yyval.interm.type) = context->joinInterpolationQualifiers((yylsp[-1]), (yyvsp[-1].interm.type).qualifier, (yylsp[0]), (yyvsp[0].interm.type).qualifier); } break; @@ -3616,7 +3532,10 @@ yyreduce: case 135: { - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqConst, (yylsp[0])); + context->error((yylsp[0]), "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString((yyvsp[0].interm.type).qualifier)); + + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtVoid, qual, (yylsp[0])); } break; @@ -3624,24 +3543,8 @@ yyreduce: case 136: { - if (context->declaringFunction()) - { - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqIn, (yylsp[0])); - } - else if (context->getShaderType() == GL_FRAGMENT_SHADER) - { - ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier"); - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqFragmentIn, (yylsp[0])); - } - else if (context->getShaderType() == GL_VERTEX_SHADER) - { - ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier"); - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVertexIn, (yylsp[0])); - } - else - { - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqComputeIn, (yylsp[0])); - } + (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).layoutQualifier = (yyvsp[0].interm.layoutQualifier); } break; @@ -3649,23 +3552,8 @@ yyreduce: case 137: { - if (context->declaringFunction()) - { - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqOut, (yylsp[0])); - } - else - { - ES3_OR_NEWER("out", (yylsp[0]), "storage qualifier"); - NON_COMPUTE_ONLY("out", (yylsp[0])); - if (context->getShaderType() == GL_FRAGMENT_SHADER) - { - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqFragmentOut, (yylsp[0])); - } - else - { - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVertexOut, (yylsp[0])); - } - } + (yyval.interm.type).setBasic(EbtVoid, (yyvsp[0].interm.type).qualifier, (yylsp[0])); + (yyval.interm.type).layoutQualifier = (yyvsp[-1].interm.layoutQualifier); } break; @@ -3673,11 +3561,9 @@ yyreduce: case 138: { - if (!context->declaringFunction()) - { - context->error((yylsp[0]), "invalid inout qualifier", "'inout' can be only used with function parameters"); - } - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqInOut, (yylsp[0])); + context->checkInvariantIsOutVariableES3((yyvsp[0].interm.type).qualifier, (yylsp[-1])); + (yyval.interm.type).setBasic(EbtVoid, (yyvsp[0].interm.type).qualifier, (yylsp[0])); + (yyval.interm.type).invariant = true; } break; @@ -3685,8 +3571,9 @@ yyreduce: case 139: { - ES3_OR_NEWER("centroid", (yylsp[0]), "storage qualifier"); - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqCentroid, (yylsp[0])); + context->checkInvariantIsOutVariableES3((yyvsp[0].interm.type).qualifier, (yylsp[-2])); + (yyval.interm.type) = context->joinInterpolationQualifiers((yylsp[-1]), (yyvsp[-1].interm.type).qualifier, (yylsp[0]), (yyvsp[0].interm.type).qualifier); + (yyval.interm.type).invariant = true; } break; @@ -3694,8 +3581,7 @@ yyreduce: case 140: { - context->checkIsAtGlobalLevel((yylsp[0]), "uniform"); - (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqUniform, (yylsp[0])); + (yyval.interm.type).qualifier = EvqConst; } break; @@ -3703,7 +3589,20 @@ yyreduce: case 141: { - (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqReadOnly, (yylsp[0])); + if (context->getShaderType() == GL_FRAGMENT_SHADER) + { + ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier"); + (yyval.interm.type).qualifier = EvqFragmentIn; + } + else if (context->getShaderType() == GL_VERTEX_SHADER) + { + ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier"); + (yyval.interm.type).qualifier = EvqVertexIn; + } + else + { + (yyval.interm.type).qualifier = EvqComputeIn; + } } break; @@ -3711,7 +3610,9 @@ yyreduce: case 142: { - (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqWriteOnly, (yylsp[0])); + ES3_OR_NEWER("out", (yylsp[0]), "storage qualifier"); + NON_COMPUTE_ONLY("out", (yylsp[0])); + (yyval.interm.type).qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; } break; @@ -3719,7 +3620,9 @@ yyreduce: case 143: { - (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqCoherent, (yylsp[0])); + ES3_OR_NEWER("centroid in", (yylsp[-1]), "storage qualifier"); + FRAG_ONLY("centroid in", (yylsp[-1])); + (yyval.interm.type).qualifier = EvqCentroidIn; } break; @@ -3727,7 +3630,9 @@ yyreduce: case 144: { - (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqRestrict, (yylsp[0])); + ES3_OR_NEWER("centroid out", (yylsp[-1]), "storage qualifier"); + VERTEX_ONLY("centroid out", (yylsp[-1])); + (yyval.interm.type).qualifier = EvqCentroidOut; } break; @@ -3735,7 +3640,8 @@ yyreduce: case 145: { - (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqVolatile, (yylsp[0])); + context->checkIsAtGlobalLevel((yylsp[0]), "uniform"); + (yyval.interm.type).qualifier = EvqUniform; } break; @@ -3744,7 +3650,11 @@ yyreduce: { (yyval.interm.type) = (yyvsp[0].interm.type); - (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).getBasicType()); + + if ((yyval.interm.type).precision == EbpUndefined) { + (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).type); + context->checkPrecisionSpecified((yylsp[0]), (yyval.interm.type).precision, (yyvsp[0].interm.type).type); + } } break; @@ -3752,7 +3662,12 @@ yyreduce: case 147: { - (yyval.interm.precision) = EbpHigh; + (yyval.interm.type) = (yyvsp[0].interm.type); + (yyval.interm.type).precision = (yyvsp[-1].interm.precision); + + if (!SupportsPrecision((yyvsp[0].interm.type).type)) { + context->error((yylsp[-1]), "illegal type for precision qualifier", getBasicString((yyvsp[0].interm.type).type)); + } } break; @@ -3760,7 +3675,7 @@ yyreduce: case 148: { - (yyval.interm.precision) = EbpMedium; + (yyval.interm.precision) = EbpHigh; } break; @@ -3768,7 +3683,7 @@ yyreduce: case 149: { - (yyval.interm.precision) = EbpLow; + (yyval.interm.precision) = EbpMedium; } break; @@ -3776,8 +3691,7 @@ yyreduce: case 150: { - ES3_OR_NEWER("layout", (yylsp[-3]), "qualifier"); - (yyval.interm.layoutQualifier) = (yyvsp[-1].interm.layoutQualifier); + (yyval.interm.precision) = EbpLow; } break; @@ -3785,7 +3699,8 @@ yyreduce: case 151: { - (yyval.interm.layoutQualifier) = (yyvsp[0].interm.layoutQualifier); + ES3_OR_NEWER("layout", (yylsp[-3]), "qualifier"); + (yyval.interm.layoutQualifier) = (yyvsp[-1].interm.layoutQualifier); } break; @@ -3793,7 +3708,7 @@ yyreduce: case 152: { - (yyval.interm.layoutQualifier) = context->joinLayoutQualifiers((yyvsp[-2].interm.layoutQualifier), (yyvsp[0].interm.layoutQualifier), (yylsp[0])); + (yyval.interm.layoutQualifier) = (yyvsp[0].interm.layoutQualifier); } break; @@ -3801,7 +3716,7 @@ yyreduce: case 153: { - (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[0].lex).string, (yylsp[0])); + (yyval.interm.layoutQualifier) = context->joinLayoutQualifiers((yyvsp[-2].interm.layoutQualifier), (yyvsp[0].interm.layoutQualifier), (yylsp[0])); } break; @@ -3809,7 +3724,7 @@ yyreduce: case 154: { - (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[-2].lex).string, (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0])); + (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[0].lex).string, (yylsp[0])); } break; @@ -3825,7 +3740,7 @@ yyreduce: case 156: { - (yyval.interm.type).initialize((yyvsp[0].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); + (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(*(yyvsp[-2].lex).string, (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0])); } break; @@ -3833,9 +3748,7 @@ yyreduce: case 157: { - ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array"); - (yyval.interm.type).initialize((yyvsp[-2].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - (yyval.interm.type).setArraySize(0); + (yyval.interm.type) = (yyvsp[0].interm.type); } break; @@ -3843,12 +3756,9 @@ yyreduce: case 158: { - (yyval.interm.type).initialize((yyvsp[-3].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary)); - if (context->checkIsValidTypeForArray((yylsp[-2]), (yyval.interm.type))) - { - unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.type).setArraySize(size); - } + ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array"); + (yyval.interm.type) = (yyvsp[-2].interm.type); + (yyval.interm.type).setArraySize(0); } break; @@ -3856,7 +3766,13 @@ yyreduce: case 159: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtVoid, (yylsp[0])); + (yyval.interm.type) = (yyvsp[-3].interm.type); + + if (context->checkIsValidTypeForArray((yylsp[-2]), (yyvsp[-3].interm.type))) + { + unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode)); + (yyval.interm.type).setArraySize(size); + } } break; @@ -3864,7 +3780,8 @@ yyreduce: case 160: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtVoid, qual, (yylsp[0])); } break; @@ -3872,7 +3789,8 @@ yyreduce: case 161: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); } break; @@ -3880,7 +3798,8 @@ yyreduce: case 162: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0])); } break; @@ -3888,7 +3807,8 @@ yyreduce: case 163: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0])); } break; @@ -3896,8 +3816,8 @@ yyreduce: case 164: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0])); } break; @@ -3905,8 +3825,9 @@ yyreduce: case 165: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(2); } break; @@ -3914,8 +3835,9 @@ yyreduce: case 166: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(3); } break; @@ -3923,8 +3845,9 @@ yyreduce: case 167: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(4); } break; @@ -3932,8 +3855,9 @@ yyreduce: case 168: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(2); } break; @@ -3941,8 +3865,9 @@ yyreduce: case 169: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(3); } break; @@ -3950,8 +3875,9 @@ yyreduce: case 170: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(4); } break; @@ -3959,8 +3885,9 @@ yyreduce: case 171: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(2); } break; @@ -3968,8 +3895,9 @@ yyreduce: case 172: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(3); } break; @@ -3977,8 +3905,9 @@ yyreduce: case 173: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(4); } break; @@ -3986,8 +3915,9 @@ yyreduce: case 174: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(2); } break; @@ -3995,8 +3925,9 @@ yyreduce: case 175: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setAggregate(4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(3); } break; @@ -4004,8 +3935,9 @@ yyreduce: case 176: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0])); + (yyval.interm.type).setAggregate(4); } break; @@ -4013,8 +3945,9 @@ yyreduce: case 177: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(2, 2); } break; @@ -4022,8 +3955,9 @@ yyreduce: case 178: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(3, 3); } break; @@ -4031,8 +3965,9 @@ yyreduce: case 179: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(4, 4); } break; @@ -4040,8 +3975,9 @@ yyreduce: case 180: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(2, 3); } break; @@ -4049,8 +3985,9 @@ yyreduce: case 181: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(3, 2); } break; @@ -4058,8 +3995,9 @@ yyreduce: case 182: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(2, 4); } break; @@ -4067,8 +4005,9 @@ yyreduce: case 183: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(4, 2); } break; @@ -4076,8 +4015,9 @@ yyreduce: case 184: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(3, 4); } break; @@ -4085,7 +4025,9 @@ yyreduce: case 185: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2D, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0])); + (yyval.interm.type).setMatrix(4, 3); } break; @@ -4093,7 +4035,8 @@ yyreduce: case 186: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler3D, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2D, qual, (yylsp[0])); } break; @@ -4101,7 +4044,8 @@ yyreduce: case 187: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCube, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler3D, qual, (yylsp[0])); } break; @@ -4109,7 +4053,8 @@ yyreduce: case 188: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArray, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yylsp[0])); } break; @@ -4117,7 +4062,8 @@ yyreduce: case 189: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2D, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2DArray, qual, (yylsp[0])); } break; @@ -4125,7 +4071,8 @@ yyreduce: case 190: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler3D, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtISampler2D, qual, (yylsp[0])); } break; @@ -4133,7 +4080,8 @@ yyreduce: case 191: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCube, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtISampler3D, qual, (yylsp[0])); } break; @@ -4141,7 +4089,8 @@ yyreduce: case 192: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DArray, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtISamplerCube, qual, (yylsp[0])); } break; @@ -4149,7 +4098,8 @@ yyreduce: case 193: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2D, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtISampler2DArray, qual, (yylsp[0])); } break; @@ -4157,7 +4107,8 @@ yyreduce: case 194: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler3D, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUSampler2D, qual, (yylsp[0])); } break; @@ -4165,7 +4116,8 @@ yyreduce: case 195: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCube, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUSampler3D, qual, (yylsp[0])); } break; @@ -4173,7 +4125,8 @@ yyreduce: case 196: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DArray, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUSamplerCube, qual, (yylsp[0])); } break; @@ -4181,7 +4134,8 @@ yyreduce: case 197: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DShadow, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtUSampler2DArray, qual, (yylsp[0])); } break; @@ -4189,7 +4143,8 @@ yyreduce: case 198: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeShadow, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2DShadow, qual, (yylsp[0])); } break; @@ -4197,7 +4152,8 @@ yyreduce: case 199: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArrayShadow, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSamplerCubeShadow, qual, (yylsp[0])); } break; @@ -4205,11 +4161,8 @@ yyreduce: case 200: { - if (!context->supportsExtension("GL_OES_EGL_image_external") && - !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) { - context->error((yylsp[0]), "unsupported type", "samplerExternalOES"); - } - (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2DArrayShadow, qual, (yylsp[0])); } break; @@ -4217,10 +4170,12 @@ yyreduce: case 201: { - if (!context->supportsExtension("GL_ARB_texture_rectangle")) { - context->error((yylsp[0]), "unsupported type", "sampler2DRect"); + if (!context->supportsExtension("GL_OES_EGL_image_external") && + !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) { + context->error((yylsp[0]), "unsupported type", "samplerExternalOES"); } - (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0])); + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yylsp[0])); } break; @@ -4228,7 +4183,11 @@ yyreduce: case 202: { - (yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray); + if (!context->supportsExtension("GL_ARB_texture_rectangle")) { + context->error((yylsp[0]), "unsupported type", "sampler2DRect"); + } + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yylsp[0])); } break; @@ -4236,7 +4195,8 @@ yyreduce: case 203: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0])); + (yyval.interm.type) = (yyvsp[0].interm.type); + (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } break; @@ -4244,134 +4204,47 @@ yyreduce: case 204: { - (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0])); - } - - break; - - case 205: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0])); - } - - break; - - case 206: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0])); - } - - break; - - case 207: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0])); - } - - break; - - case 208: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0])); - } - - break; - - case 209: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0])); - } - - break; - - case 210: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0])); - } - - break; - - case 211: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0])); - } - - break; - - case 212: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0])); - } - - break; - - case 213: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0])); - } - - break; - - case 214: - - { - (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0])); - } - - break; - - case 215: - - { // // This is for user defined type names. The lexical phase looked up the // type. // TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType(); - (yyval.interm.typeSpecifierNonArray).initialize(EbtStruct, (yylsp[0])); - (yyval.interm.typeSpecifierNonArray).userDef = &structure; + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + (yyval.interm.type).setBasic(EbtStruct, qual, (yylsp[0])); + (yyval.interm.type).userDef = &structure; } break; - case 216: + case 205: { context->enterStructDeclaration((yylsp[-1]), *(yyvsp[-1].lex).string); } break; - case 217: + case 206: { - (yyval.interm.typeSpecifierNonArray) = context->addStructure((yylsp[-5]), (yylsp[-4]), (yyvsp[-4].lex).string, (yyvsp[-1].interm.fieldList)); + (yyval.interm.type) = context->addStructure((yylsp[-5]), (yylsp[-4]), (yyvsp[-4].lex).string, (yyvsp[-1].interm.fieldList)); } break; - case 218: + case 207: { context->enterStructDeclaration((yylsp[0]), *(yyvsp[0].lex).string); } break; - case 219: + case 208: { - (yyval.interm.typeSpecifierNonArray) = context->addStructure((yylsp[-4]), (yyloc), NewPoolTString(""), (yyvsp[-1].interm.fieldList)); + (yyval.interm.type) = context->addStructure((yylsp[-4]), (yyloc), NewPoolTString(""), (yyvsp[-1].interm.fieldList)); } break; - case 220: + case 209: { (yyval.interm.fieldList) = (yyvsp[0].interm.fieldList); @@ -4379,7 +4252,7 @@ yyreduce: break; - case 221: + case 210: { (yyval.interm.fieldList) = (yyvsp[-1].interm.fieldList); @@ -4396,7 +4269,7 @@ yyreduce: break; - case 222: + case 211: { (yyval.interm.fieldList) = context->addStructDeclaratorList((yyvsp[-2].interm.type), (yyvsp[-1].interm.fieldList)); @@ -4404,16 +4277,18 @@ yyreduce: break; - case 223: + case 212: { // ES3 Only, but errors should be handled elsewhere - (yyval.interm.fieldList) = context->addStructDeclaratorListWithQualifiers(*(yyvsp[-3].interm.typeQualifierBuilder), &(yyvsp[-2].interm.type), (yyvsp[-1].interm.fieldList)); + (yyvsp[-2].interm.type).qualifier = (yyvsp[-3].interm.type).qualifier; + (yyvsp[-2].interm.type).layoutQualifier = (yyvsp[-3].interm.type).layoutQualifier; + (yyval.interm.fieldList) = context->addStructDeclaratorList((yyvsp[-2].interm.type), (yyvsp[-1].interm.fieldList)); } break; - case 224: + case 213: { (yyval.interm.fieldList) = NewPoolTFieldList(); @@ -4422,7 +4297,7 @@ yyreduce: break; - case 225: + case 214: { (yyval.interm.fieldList)->push_back((yyvsp[0].interm.field)); @@ -4430,7 +4305,7 @@ yyreduce: break; - case 226: + case 215: { context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string); @@ -4441,7 +4316,7 @@ yyreduce: break; - case 227: + case 216: { context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string); @@ -4455,197 +4330,196 @@ yyreduce: break; - case 228: + case 217: { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } break; - case 229: + case 218: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 230: + case 219: - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); } + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); } break; - case 231: + case 220: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 232: + case 221: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 233: + case 222: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 234: + case 223: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 235: + case 224: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermSwitch); } break; - case 236: + case 225: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermCase); } break; - case 237: + case 226: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 238: + case 227: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 239: + case 228: - { (yyval.interm.intermBlock) = 0; } + { (yyval.interm.intermAggregate) = 0; } break; - case 240: + case 229: { context->symbolTable.push(); } break; - case 241: + case 230: { context->symbolTable.pop(); } break; - case 242: + case 231: { - if ((yyvsp[-2].interm.intermBlock) != 0) { - (yyvsp[-2].interm.intermBlock)->setLine((yyloc)); + if ((yyvsp[-2].interm.intermAggregate) != 0) { + (yyvsp[-2].interm.intermAggregate)->setOp(EOpSequence); + (yyvsp[-2].interm.intermAggregate)->setLine((yyloc)); } - (yyval.interm.intermBlock) = (yyvsp[-2].interm.intermBlock); + (yyval.interm.intermAggregate) = (yyvsp[-2].interm.intermAggregate); } break; - case 243: + case 232: - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); } + { (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); } break; - case 244: + case 233: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 245: + case 234: { context->symbolTable.push(); } break; - case 246: + case 235: - { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock); } + { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); } break; - case 247: + case 236: { context->symbolTable.push(); } break; - case 248: + case 237: { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } break; - case 249: + case 238: { - (yyval.interm.intermBlock) = 0; + (yyval.interm.intermAggregate) = 0; } break; - case 250: + case 239: { - if ((yyvsp[-1].interm.intermBlock)) { - (yyvsp[-1].interm.intermBlock)->setLine((yyloc)); + if ((yyvsp[-1].interm.intermAggregate)) { + (yyvsp[-1].interm.intermAggregate)->setOp(EOpSequence); + (yyvsp[-1].interm.intermAggregate)->setLine((yyloc)); } - (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); + (yyval.interm.intermAggregate) = (yyvsp[-1].interm.intermAggregate); } break; - case 251: + case 240: { - (yyval.interm.intermBlock) = new TIntermBlock(); - (yyval.interm.intermBlock)->setLine((yyloc)); - (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); + (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[0].interm.intermNode), (yyloc)); } break; - case 252: + case 241: { - (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); - (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); + (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[-1].interm.intermAggregate), (yyvsp[0].interm.intermNode), (yyloc)); } break; - case 253: + case 242: { (yyval.interm.intermNode) = 0; } break; - case 254: + case 243: { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); } break; - case 255: + case 244: { context->checkIsScalarBool((yylsp[-4]), (yyvsp[-2].interm.intermTypedNode)); - (yyval.interm.intermNode) = context->intermediate.addIfElse((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4])); + (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4])); } break; - case 256: + case 245: { (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); @@ -4654,7 +4528,7 @@ yyreduce: break; - case 257: + case 246: { (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); @@ -4663,22 +4537,22 @@ yyreduce: break; - case 258: + case 247: { context->incrSwitchNestingLevel(); } break; - case 259: + case 248: { - (yyval.interm.intermSwitch) = context->addSwitch((yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermBlock), (yylsp[-5])); + (yyval.interm.intermSwitch) = context->addSwitch((yyvsp[-3].interm.intermTypedNode), (yyvsp[0].interm.intermAggregate), (yylsp[-5])); context->decrSwitchNestingLevel(); } break; - case 260: + case 249: { (yyval.interm.intermCase) = context->addCase((yyvsp[-1].interm.intermTypedNode), (yylsp[-2])); @@ -4686,7 +4560,7 @@ yyreduce: break; - case 261: + case 250: { (yyval.interm.intermCase) = context->addDefault((yylsp[-1])); @@ -4694,7 +4568,7 @@ yyreduce: break; - case 262: + case 251: { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); @@ -4703,13 +4577,13 @@ yyreduce: break; - case 263: + case 252: { - TIntermBinary *initNode = nullptr; + TIntermNode *intermNode; context->checkIsScalarBool((yylsp[-2]), (yyvsp[-3].interm.type)); - if (!context->executeInitializer((yylsp[-2]), *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), (yyvsp[0].interm.intermTypedNode), &initNode)) + if (!context->executeInitializer((yylsp[-2]), *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), (yyvsp[0].interm.intermTypedNode), &intermNode)) (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); else { (yyval.interm.intermTypedNode) = 0; @@ -4718,13 +4592,13 @@ yyreduce: break; - case 264: + case 253: { context->symbolTable.push(); context->incrLoopNestingLevel(); } break; - case 265: + case 254: { context->symbolTable.pop(); @@ -4734,13 +4608,13 @@ yyreduce: break; - case 266: + case 255: { context->incrLoopNestingLevel(); } break; - case 267: + case 256: { context->checkIsScalarBool((yylsp[0]), (yyvsp[-2].interm.intermTypedNode)); @@ -4751,13 +4625,13 @@ yyreduce: break; - case 268: + case 257: { context->symbolTable.push(); context->incrLoopNestingLevel(); } break; - case 269: + case 258: { context->symbolTable.pop(); @@ -4767,7 +4641,7 @@ yyreduce: break; - case 270: + case 259: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); @@ -4775,7 +4649,7 @@ yyreduce: break; - case 271: + case 260: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); @@ -4783,7 +4657,7 @@ yyreduce: break; - case 272: + case 261: { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); @@ -4791,7 +4665,7 @@ yyreduce: break; - case 273: + case 262: { (yyval.interm.intermTypedNode) = 0; @@ -4799,7 +4673,7 @@ yyreduce: break; - case 274: + case 263: { (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); @@ -4808,7 +4682,7 @@ yyreduce: break; - case 275: + case 264: { (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); @@ -4817,7 +4691,7 @@ yyreduce: break; - case 276: + case 265: { (yyval.interm.intermNode) = context->addBranch(EOpContinue, (yylsp[-1])); @@ -4825,7 +4699,7 @@ yyreduce: break; - case 277: + case 266: { (yyval.interm.intermNode) = context->addBranch(EOpBreak, (yylsp[-1])); @@ -4833,7 +4707,7 @@ yyreduce: break; - case 278: + case 267: { (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yylsp[-1])); @@ -4841,7 +4715,7 @@ yyreduce: break; - case 279: + case 268: { (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yyvsp[-1].interm.intermTypedNode), (yylsp[-2])); @@ -4849,7 +4723,7 @@ yyreduce: break; - case 280: + case 269: { FRAG_ONLY("discard", (yylsp[-1])); @@ -4858,26 +4732,25 @@ yyreduce: break; - case 281: + case 270: { - (yyval.interm.intermBlock) = new TIntermBlock(); - (yyval.interm.intermBlock)->setLine((yyloc)); - (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); - context->setTreeRoot((yyval.interm.intermBlock)); + (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); + context->setTreeRoot((yyval.interm.intermNode)); } break; - case 282: + case 271: { - (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); + (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode), (yyloc)); + context->setTreeRoot((yyval.interm.intermNode)); } break; - case 283: + case 272: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); @@ -4885,7 +4758,7 @@ yyreduce: break; - case 284: + case 273: { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); @@ -4893,18 +4766,18 @@ yyreduce: break; - case 285: + case 274: { - context->parseFunctionDefinitionHeader((yylsp[0]), &((yyvsp[0].interm).function), &(yyvsp[0].interm).intermAggregate); + context->parseFunctionPrototype((yylsp[0]), (yyvsp[0].interm).function, &(yyvsp[0].interm).intermAggregate); } break; - case 286: + case 275: { - (yyval.interm.intermNode) = context->addFunctionDefinition(*((yyvsp[-2].interm).function), (yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermBlock), (yylsp[-2])); + (yyval.interm.intermNode) = context->addFunctionDefinition(*((yyvsp[-2].interm).function), (yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermAggregate), (yylsp[-2])); } break; diff --git a/gfx/angle/src/compiler/translator/glslang_tab.h b/gfx/angle/src/compiler/translator/glslang_tab.h index 8b043c01d..7331594a4 100755 --- a/gfx/angle/src/compiler/translator/glslang_tab.h +++ b/gfx/angle/src/compiler/translator/glslang_tab.h @@ -50,151 +50,134 @@ extern int yydebug; /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE -enum yytokentype -{ - INVARIANT = 258, - HIGH_PRECISION = 259, - MEDIUM_PRECISION = 260, - LOW_PRECISION = 261, - PRECISION = 262, - ATTRIBUTE = 263, - CONST_QUAL = 264, - BOOL_TYPE = 265, - FLOAT_TYPE = 266, - INT_TYPE = 267, - UINT_TYPE = 268, - BREAK = 269, - CONTINUE = 270, - DO = 271, - ELSE = 272, - FOR = 273, - IF = 274, - DISCARD = 275, - RETURN = 276, - SWITCH = 277, - CASE = 278, - DEFAULT = 279, - BVEC2 = 280, - BVEC3 = 281, - BVEC4 = 282, - IVEC2 = 283, - IVEC3 = 284, - IVEC4 = 285, - VEC2 = 286, - VEC3 = 287, - VEC4 = 288, - UVEC2 = 289, - UVEC3 = 290, - UVEC4 = 291, - MATRIX2 = 292, - MATRIX3 = 293, - MATRIX4 = 294, - IN_QUAL = 295, - OUT_QUAL = 296, - INOUT_QUAL = 297, - UNIFORM = 298, - VARYING = 299, - MATRIX2x3 = 300, - MATRIX3x2 = 301, - MATRIX2x4 = 302, - MATRIX4x2 = 303, - MATRIX3x4 = 304, - MATRIX4x3 = 305, - CENTROID = 306, - FLAT = 307, - SMOOTH = 308, - READONLY = 309, - WRITEONLY = 310, - COHERENT = 311, - RESTRICT = 312, - VOLATILE = 313, - STRUCT = 314, - VOID_TYPE = 315, - WHILE = 316, - SAMPLER2D = 317, - SAMPLERCUBE = 318, - SAMPLER_EXTERNAL_OES = 319, - SAMPLER2DRECT = 320, - SAMPLER2DARRAY = 321, - ISAMPLER2D = 322, - ISAMPLER3D = 323, - ISAMPLERCUBE = 324, - ISAMPLER2DARRAY = 325, - USAMPLER2D = 326, - USAMPLER3D = 327, - USAMPLERCUBE = 328, - USAMPLER2DARRAY = 329, - SAMPLER3D = 330, - SAMPLER3DRECT = 331, - SAMPLER2DSHADOW = 332, - SAMPLERCUBESHADOW = 333, - SAMPLER2DARRAYSHADOW = 334, - IMAGE2D = 335, - IIMAGE2D = 336, - UIMAGE2D = 337, - IMAGE3D = 338, - IIMAGE3D = 339, - UIMAGE3D = 340, - IMAGE2DARRAY = 341, - IIMAGE2DARRAY = 342, - UIMAGE2DARRAY = 343, - IMAGECUBE = 344, - IIMAGECUBE = 345, - UIMAGECUBE = 346, - LAYOUT = 347, - IDENTIFIER = 348, - TYPE_NAME = 349, - FLOATCONSTANT = 350, - INTCONSTANT = 351, - UINTCONSTANT = 352, - BOOLCONSTANT = 353, - FIELD_SELECTION = 354, - LEFT_OP = 355, - RIGHT_OP = 356, - INC_OP = 357, - DEC_OP = 358, - LE_OP = 359, - GE_OP = 360, - EQ_OP = 361, - NE_OP = 362, - AND_OP = 363, - OR_OP = 364, - XOR_OP = 365, - MUL_ASSIGN = 366, - DIV_ASSIGN = 367, - ADD_ASSIGN = 368, - MOD_ASSIGN = 369, - LEFT_ASSIGN = 370, - RIGHT_ASSIGN = 371, - AND_ASSIGN = 372, - XOR_ASSIGN = 373, - OR_ASSIGN = 374, - SUB_ASSIGN = 375, - LEFT_PAREN = 376, - RIGHT_PAREN = 377, - LEFT_BRACKET = 378, - RIGHT_BRACKET = 379, - LEFT_BRACE = 380, - RIGHT_BRACE = 381, - DOT = 382, - COMMA = 383, - COLON = 384, - EQUAL = 385, - SEMICOLON = 386, - BANG = 387, - DASH = 388, - TILDE = 389, - PLUS = 390, - STAR = 391, - SLASH = 392, - PERCENT = 393, - LEFT_ANGLE = 394, - RIGHT_ANGLE = 395, - VERTICAL_BAR = 396, - CARET = 397, - AMPERSAND = 398, - QUESTION = 399 -}; + enum yytokentype + { + INVARIANT = 258, + HIGH_PRECISION = 259, + MEDIUM_PRECISION = 260, + LOW_PRECISION = 261, + PRECISION = 262, + ATTRIBUTE = 263, + CONST_QUAL = 264, + BOOL_TYPE = 265, + FLOAT_TYPE = 266, + INT_TYPE = 267, + UINT_TYPE = 268, + BREAK = 269, + CONTINUE = 270, + DO = 271, + ELSE = 272, + FOR = 273, + IF = 274, + DISCARD = 275, + RETURN = 276, + SWITCH = 277, + CASE = 278, + DEFAULT = 279, + BVEC2 = 280, + BVEC3 = 281, + BVEC4 = 282, + IVEC2 = 283, + IVEC3 = 284, + IVEC4 = 285, + VEC2 = 286, + VEC3 = 287, + VEC4 = 288, + UVEC2 = 289, + UVEC3 = 290, + UVEC4 = 291, + MATRIX2 = 292, + MATRIX3 = 293, + MATRIX4 = 294, + IN_QUAL = 295, + OUT_QUAL = 296, + INOUT_QUAL = 297, + UNIFORM = 298, + VARYING = 299, + MATRIX2x3 = 300, + MATRIX3x2 = 301, + MATRIX2x4 = 302, + MATRIX4x2 = 303, + MATRIX3x4 = 304, + MATRIX4x3 = 305, + CENTROID = 306, + FLAT = 307, + SMOOTH = 308, + STRUCT = 309, + VOID_TYPE = 310, + WHILE = 311, + SAMPLER2D = 312, + SAMPLERCUBE = 313, + SAMPLER_EXTERNAL_OES = 314, + SAMPLER2DRECT = 315, + SAMPLER2DARRAY = 316, + ISAMPLER2D = 317, + ISAMPLER3D = 318, + ISAMPLERCUBE = 319, + ISAMPLER2DARRAY = 320, + USAMPLER2D = 321, + USAMPLER3D = 322, + USAMPLERCUBE = 323, + USAMPLER2DARRAY = 324, + SAMPLER3D = 325, + SAMPLER3DRECT = 326, + SAMPLER2DSHADOW = 327, + SAMPLERCUBESHADOW = 328, + SAMPLER2DARRAYSHADOW = 329, + LAYOUT = 330, + IDENTIFIER = 331, + TYPE_NAME = 332, + FLOATCONSTANT = 333, + INTCONSTANT = 334, + UINTCONSTANT = 335, + BOOLCONSTANT = 336, + FIELD_SELECTION = 337, + LEFT_OP = 338, + RIGHT_OP = 339, + INC_OP = 340, + DEC_OP = 341, + LE_OP = 342, + GE_OP = 343, + EQ_OP = 344, + NE_OP = 345, + AND_OP = 346, + OR_OP = 347, + XOR_OP = 348, + MUL_ASSIGN = 349, + DIV_ASSIGN = 350, + ADD_ASSIGN = 351, + MOD_ASSIGN = 352, + LEFT_ASSIGN = 353, + RIGHT_ASSIGN = 354, + AND_ASSIGN = 355, + XOR_ASSIGN = 356, + OR_ASSIGN = 357, + SUB_ASSIGN = 358, + LEFT_PAREN = 359, + RIGHT_PAREN = 360, + LEFT_BRACKET = 361, + RIGHT_BRACKET = 362, + LEFT_BRACE = 363, + RIGHT_BRACE = 364, + DOT = 365, + COMMA = 366, + COLON = 367, + EQUAL = 368, + SEMICOLON = 369, + BANG = 370, + DASH = 371, + TILDE = 372, + PLUS = 373, + STAR = 374, + SLASH = 375, + PERCENT = 376, + LEFT_ANGLE = 377, + RIGHT_ANGLE = 378, + VERTICAL_BAR = 379, + CARET = 380, + AMPERSAND = 381, + QUESTION = 382 + }; #endif /* Value type. */ @@ -217,27 +200,22 @@ union YYSTYPE struct { TOperator op; union { - TIntermNode *intermNode; + TIntermNode* intermNode; TIntermNodePair nodePair; - TIntermTyped *intermTypedNode; - TIntermAggregate *intermAggregate; - TIntermBlock *intermBlock; - TIntermDeclaration *intermDeclaration; - TIntermSwitch *intermSwitch; - TIntermCase *intermCase; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + TIntermSwitch* intermSwitch; + TIntermCase* intermCase; }; union { - TTypeSpecifierNonArray typeSpecifierNonArray; TPublicType type; TPrecision precision; TLayoutQualifier layoutQualifier; TQualifier qualifier; - TFunction *function; + TFunction* function; TParameter param; - TField *field; - TFieldList *fieldList; - TQualifierWrapperBase *qualifierWrapper; - TTypeQualifierBuilder *typeQualifierBuilder; + TField* field; + TFieldList* fieldList; }; } interm; diff --git a/gfx/angle/src/compiler/translator/intermOut.cpp b/gfx/angle/src/compiler/translator/intermOut.cpp index 53ee1d02a..6dca547f0 100755 --- a/gfx/angle/src/compiler/translator/intermOut.cpp +++ b/gfx/angle/src/compiler/translator/intermOut.cpp @@ -7,17 +7,13 @@ #include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" -namespace sh -{ - namespace { -void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info) +void OutputFunction(TInfoSinkBase &out, const char *str, TIntermAggregate *node) { - const char *internal = info->getNameObj().isInternal() ? " (internal function)" : ""; - out << str << internal << ": " << info->getNameObj().getString() << " (symbol id " - << info->getId() << ")"; + const char *internal = node->getNameObj().isInternal() ? " (internal function)" : ""; + out << str << internal << ": " << node->getNameObj().getString(); } // @@ -46,17 +42,10 @@ class TOutputTraverser : public TIntermTraverser protected: void visitSymbol(TIntermSymbol *) override; void visitConstantUnion(TIntermConstantUnion *) override; - bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; bool visitBinary(Visit visit, TIntermBinary *) override; bool visitUnary(Visit visit, TIntermUnary *) override; - bool visitTernary(Visit visit, TIntermTernary *node) override; - bool visitIfElse(Visit visit, TIntermIfElse *node) override; - bool visitSwitch(Visit visit, TIntermSwitch *node) override; - bool visitCase(Visit visit, TIntermCase *node) override; - bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; + bool visitSelection(Visit visit, TIntermSelection *) override; bool visitAggregate(Visit visit, TIntermAggregate *) override; - bool visitBlock(Visit visit, TIntermBlock *) override; - bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; bool visitLoop(Visit visit, TIntermLoop *) override; bool visitBranch(Visit visit, TIntermBranch *) override; }; @@ -93,14 +82,6 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node) sink << "(" << node->getCompleteString() << ")\n"; } -bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = sink; - OutputTreeText(out, node, mDepth); - out << "vector swizzle"; - return true; -} - bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase& out = sink; @@ -109,148 +90,148 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) switch (node->getOp()) { - case EOpComma: - out << "comma"; - break; - case EOpAssign: - out << "move second child to first child"; - break; - case EOpInitialize: - out << "initialize first child with second child"; - break; - case EOpAddAssign: - out << "add second child into first child"; - break; - case EOpSubAssign: - out << "subtract second child into first child"; - break; - case EOpMulAssign: - out << "multiply second child into first child"; - break; - case EOpVectorTimesMatrixAssign: - out << "matrix mult second child into first child"; - break; - case EOpVectorTimesScalarAssign: - out << "vector scale second child into first child"; - break; - case EOpMatrixTimesScalarAssign: - out << "matrix scale second child into first child"; - break; - case EOpMatrixTimesMatrixAssign: - out << "matrix mult second child into first child"; - break; - case EOpDivAssign: - out << "divide second child into first child"; - break; - case EOpIModAssign: - out << "modulo second child into first child"; - break; - case EOpBitShiftLeftAssign: - out << "bit-wise shift first child left by second child"; - break; - case EOpBitShiftRightAssign: - out << "bit-wise shift first child right by second child"; - break; - case EOpBitwiseAndAssign: - out << "bit-wise and second child into first child"; - break; - case EOpBitwiseXorAssign: - out << "bit-wise xor second child into first child"; - break; - case EOpBitwiseOrAssign: - out << "bit-wise or second child into first child"; - break; - - case EOpIndexDirect: - out << "direct index"; - break; - case EOpIndexIndirect: - out << "indirect index"; - break; - case EOpIndexDirectStruct: - out << "direct index for structure"; - break; - case EOpIndexDirectInterfaceBlock: - out << "direct index for interface block"; - break; - - case EOpAdd: - out << "add"; - break; - case EOpSub: - out << "subtract"; - break; - case EOpMul: - out << "component-wise multiply"; - break; - case EOpDiv: - out << "divide"; - break; - case EOpIMod: - out << "modulo"; - break; - case EOpBitShiftLeft: - out << "bit-wise shift left"; - break; - case EOpBitShiftRight: - out << "bit-wise shift right"; - break; - case EOpBitwiseAnd: - out << "bit-wise and"; - break; - case EOpBitwiseXor: - out << "bit-wise xor"; - break; - case EOpBitwiseOr: - out << "bit-wise or"; - break; - - case EOpEqual: - out << "Compare Equal"; - break; - case EOpNotEqual: - out << "Compare Not Equal"; - break; - case EOpLessThan: - out << "Compare Less Than"; - break; - case EOpGreaterThan: - out << "Compare Greater Than"; - break; - case EOpLessThanEqual: - out << "Compare Less Than or Equal"; - break; - case EOpGreaterThanEqual: - out << "Compare Greater Than or Equal"; - break; - - case EOpVectorTimesScalar: - out << "vector-scale"; - break; - case EOpVectorTimesMatrix: - out << "vector-times-matrix"; - break; - case EOpMatrixTimesVector: - out << "matrix-times-vector"; - break; - case EOpMatrixTimesScalar: - out << "matrix-scale"; - break; - case EOpMatrixTimesMatrix: - out << "matrix-multiply"; - break; - - case EOpLogicalOr: - out << "logical-or"; - break; - case EOpLogicalXor: - out << "logical-xor"; - break; - case EOpLogicalAnd: - out << "logical-and"; - break; - default: - out << "<unknown op>"; + case EOpAssign: + out << "move second child to first child"; + break; + case EOpInitialize: + out << "initialize first child with second child"; + break; + case EOpAddAssign: + out << "add second child into first child"; + break; + case EOpSubAssign: + out << "subtract second child into first child"; + break; + case EOpMulAssign: + out << "multiply second child into first child"; + break; + case EOpVectorTimesMatrixAssign: + out << "matrix mult second child into first child"; + break; + case EOpVectorTimesScalarAssign: + out << "vector scale second child into first child"; + break; + case EOpMatrixTimesScalarAssign: + out << "matrix scale second child into first child"; + break; + case EOpMatrixTimesMatrixAssign: + out << "matrix mult second child into first child"; + break; + case EOpDivAssign: + out << "divide second child into first child"; + break; + case EOpIModAssign: + out << "modulo second child into first child"; + break; + case EOpBitShiftLeftAssign: + out << "bit-wise shift first child left by second child"; + break; + case EOpBitShiftRightAssign: + out << "bit-wise shift first child right by second child"; + break; + case EOpBitwiseAndAssign: + out << "bit-wise and second child into first child"; + break; + case EOpBitwiseXorAssign: + out << "bit-wise xor second child into first child"; + break; + case EOpBitwiseOrAssign: + out << "bit-wise or second child into first child"; + break; + + case EOpIndexDirect: + out << "direct index"; + break; + case EOpIndexIndirect: + out << "indirect index"; + break; + case EOpIndexDirectStruct: + out << "direct index for structure"; + break; + case EOpIndexDirectInterfaceBlock: + out << "direct index for interface block"; + break; + case EOpVectorSwizzle: + out << "vector swizzle"; + break; + + case EOpAdd: + out << "add"; + break; + case EOpSub: + out << "subtract"; + break; + case EOpMul: + out << "component-wise multiply"; + break; + case EOpDiv: + out << "divide"; + break; + case EOpIMod: + out << "modulo"; + break; + case EOpBitShiftLeft: + out << "bit-wise shift left"; + break; + case EOpBitShiftRight: + out << "bit-wise shift right"; + break; + case EOpBitwiseAnd: + out << "bit-wise and"; + break; + case EOpBitwiseXor: + out << "bit-wise xor"; + break; + case EOpBitwiseOr: + out << "bit-wise or"; + break; + + case EOpEqual: + out << "Compare Equal"; + break; + case EOpNotEqual: + out << "Compare Not Equal"; + break; + case EOpLessThan: + out << "Compare Less Than"; + break; + case EOpGreaterThan: + out << "Compare Greater Than"; + break; + case EOpLessThanEqual: + out << "Compare Less Than or Equal"; + break; + case EOpGreaterThanEqual: + out << "Compare Greater Than or Equal"; + break; + + case EOpVectorTimesScalar: + out << "vector-scale"; + break; + case EOpVectorTimesMatrix: + out << "vector-times-matrix"; + break; + case EOpMatrixTimesVector: + out << "matrix-times-vector"; + break; + case EOpMatrixTimesScalar: + out << "matrix-scale"; + break; + case EOpMatrixTimesMatrix: + out << "matrix-multiply"; + break; + + case EOpLogicalOr: + out << "logical-or"; + break; + case EOpLogicalXor: + out << "logical-xor"; + break; + case EOpLogicalAnd: + out << "logical-and"; + break; + default: + out << "<unknown op>"; } out << " (" << node->getCompleteString() << ")"; @@ -381,38 +362,27 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) return true; } -bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TInfoSinkBase &out = sink; - OutputTreeText(out, node, mDepth); - OutputFunction(out, "Function Definition", node->getFunctionSymbolInfo()); - out << "\n"; - return true; -} - bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { TInfoSinkBase &out = sink; - OutputTreeText(out, node, mDepth); - if (node->getOp() == EOpNull) { out.prefix(EPrefixError); - out << "node is still EOpNull!\n"; + out << "node is still EOpNull!"; return true; } + OutputTreeText(out, node, mDepth); switch (node->getOp()) { - case EOpFunctionCall: - OutputFunction(out, "Function Call", node->getFunctionSymbolInfo()); - break; + case EOpSequence: out << "Sequence\n"; return true; + case EOpComma: out << "Comma\n"; return true; + case EOpFunction: OutputFunction(out, "Function Definition", node); break; + case EOpFunctionCall: OutputFunction(out, "Function Call", node); break; case EOpParameters: out << "Function Parameters: "; break; - case EOpPrototype: - OutputFunction(out, "Function Prototype", node->getFunctionSymbolInfo()); - break; + case EOpPrototype: OutputFunction(out, "Function Prototype", node); break; case EOpConstructFloat: out << "Construct float"; break; case EOpConstructVec2: out << "Construct vec2"; break; @@ -471,6 +441,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpOuterProduct: out << "outer product"; break; + case EOpDeclaration: out << "Declaration: "; break; case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; default: @@ -478,7 +449,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) out << "Bad aggregation op"; } - if (node->getOp() != EOpParameters) + if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) out << " (" << node->getCompleteString() << ")"; out << "\n"; @@ -486,33 +457,13 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) return true; } -bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = sink; - - OutputTreeText(out, node, mDepth); - out << "Code block\n"; - - return true; -} - -bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TInfoSinkBase &out = sink; - - OutputTreeText(out, node, mDepth); - out << "Declaration\n"; - - return true; -} - -bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) +bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection *node) { TInfoSinkBase &out = sink; OutputTreeText(out, node, mDepth); - out << "Ternary selection"; + out << "Test condition and select"; out << " (" << node->getCompleteString() << ")\n"; ++mDepth; @@ -522,38 +473,6 @@ bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) node->getCondition()->traverse(this); OutputTreeText(sink, node, mDepth); - if (node->getTrueExpression()) - { - out << "true case\n"; - node->getTrueExpression()->traverse(this); - } - if (node->getFalseExpression()) - { - OutputTreeText(sink, node, mDepth); - out << "false case\n"; - node->getFalseExpression()->traverse(this); - } - - --mDepth; - - return false; -} - -bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = sink; - - OutputTreeText(out, node, mDepth); - - out << "If test\n"; - - ++mDepth; - - OutputTreeText(sink, node, mDepth); - out << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(sink, node, mDepth); if (node->getTrueBlock()) { out << "true case\n"; @@ -576,35 +495,6 @@ bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node) return false; } -bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node) -{ - TInfoSinkBase &out = sink; - - OutputTreeText(out, node, mDepth); - - out << "Switch\n"; - - return true; -} - -bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node) -{ - TInfoSinkBase &out = sink; - - OutputTreeText(out, node, mDepth); - - if (node->getCondition() == nullptr) - { - out << "Default\n"; - } - else - { - out << "Case\n"; - } - - return true; -} - void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) { TInfoSinkBase &out = sink; @@ -734,5 +624,3 @@ void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink) root->traverse(&it); } - -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/length_limits.h b/gfx/angle/src/compiler/translator/length_limits.h index 607157f4a..88634381f 100755 --- a/gfx/angle/src/compiler/translator/length_limits.h +++ b/gfx/angle/src/compiler/translator/length_limits.h @@ -16,11 +16,6 @@ // These constants are factored out from the rest of the headers to // make it easier to reference them from the compiler sources. -namespace sh -{ - size_t GetGlobalMaxTokenSize(ShShaderSpec spec); -} // namespace sh - #endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_ diff --git a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp new file mode 100644 index 000000000..790974a2b --- /dev/null +++ b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp @@ -0,0 +1,130 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/timing/RestrictFragmentShaderTiming.h" + +RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink) + : mSink(sink) + , mNumErrors(0) +{ + // Sampling ops found only in fragment shaders. + mSamplingOps.insert("texture2D(s21;vf2;f1;"); + mSamplingOps.insert("texture2DProj(s21;vf3;f1;"); + mSamplingOps.insert("texture2DProj(s21;vf4;f1;"); + mSamplingOps.insert("textureCube(sC1;vf3;f1;"); + // Sampling ops found in both vertex and fragment shaders. + mSamplingOps.insert("texture2D(s21;vf2;"); + mSamplingOps.insert("texture2DProj(s21;vf3;"); + mSamplingOps.insert("texture2DProj(s21;vf4;"); + mSamplingOps.insert("textureCube(sC1;vf3;"); + // Sampling ops provided by OES_EGL_image_external. + mSamplingOps.insert("texture2D(1;vf2;"); + mSamplingOps.insert("texture2DProj(1;vf3;"); + mSamplingOps.insert("texture2DProj(1;vf4;"); + // Sampling ops provided by ARB_texture_rectangle. + mSamplingOps.insert("texture2DRect(1;vf2;"); + mSamplingOps.insert("texture2DRectProj(1;vf3;"); + mSamplingOps.insert("texture2DRectProj(1;vf4;"); + // Sampling ops provided by EXT_shader_texture_lod. + mSamplingOps.insert("texture2DLodEXT(1;vf2;f1;"); + mSamplingOps.insert("texture2DProjLodEXT(1;vf3;f1;"); + mSamplingOps.insert("texture2DProjLodEXT(1;vf4;f1;"); + mSamplingOps.insert("textureCubeLodEXT(1;vf4;f1;"); + mSamplingOps.insert("texture2DGradEXT(1;vf2;vf2;vf2;"); + mSamplingOps.insert("texture2DProjGradEXT(1;vf3;vf2;vf2;"); + mSamplingOps.insert("texture2DProjGradEXT(1;vf4;vf2;vf2;"); + mSamplingOps.insert("textureCubeGradEXT(1;vf3;vf3;vf3;"); +} + +// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc. +// can vary based on the value of the input arguments. If so, we should restrict those as well. +void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph) +{ + mNumErrors = 0; + + // FIXME(mvujovic): The dependency graph does not support user defined function calls right now, + // so we generate errors for them. + validateUserDefinedFunctionCallUsage(graph); + + // Starting from each sampler, traverse the dependency graph and generate an error each time we + // hit a node where sampler dependent values are not allowed. + for (auto samplerSymbol : graph.samplerSymbols()) + { + clearVisited(); + samplerSymbol->traverse(this); + } +} + +void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph) +{ + for (const auto* functionCall : graph.userDefinedFunctionCalls()) + { + beginError(functionCall->getIntermFunctionCall()); + mSink << "A call to a user defined function is not permitted.\n"; + } +} + +void RestrictFragmentShaderTiming::beginError(const TIntermNode* node) +{ + ++mNumErrors; + mSink.prefix(EPrefixError); + mSink.location(node->getLine()); +} + +bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const +{ + return !intermFunctionCall->isUserDefined() && + mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end(); +} + +void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter) +{ + // Texture cache access time might leak sensitive information. + // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a + // sampling operation. + if (isSamplingOp(parameter->getIntermFunctionCall())) { + switch (parameter->getArgumentNumber()) { + case 1: + // Second argument (coord) + beginError(parameter->getIntermFunctionCall()); + mSink << "An expression dependent on a sampler is not permitted to be the" + << " coordinate argument of a sampling operation.\n"; + break; + case 2: + // Third argument (bias) + beginError(parameter->getIntermFunctionCall()); + mSink << "An expression dependent on a sampler is not permitted to be the" + << " bias argument of a sampling operation.\n"; + break; + default: + // First argument (sampler) + break; + } + } +} + +void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection) +{ + beginError(selection->getIntermSelection()); + mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n"; +} + +void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop) +{ + beginError(loop->getIntermLoop()); + mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n"; +} + +void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp) +{ + beginError(logicalOp->getIntermLogicalOp()); + mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical " + << logicalOp->getOpString() + << " operator.\n"; +} diff --git a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h new file mode 100644 index 000000000..b8c7e8295 --- /dev/null +++ b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ +#define COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/depgraph/DependencyGraph.h" + +class TInfoSinkBase; + +class RestrictFragmentShaderTiming : TDependencyGraphTraverser +{ + public: + RestrictFragmentShaderTiming(TInfoSinkBase &sink); + void enforceRestrictions(const TDependencyGraph &graph); + int numErrors() const { return mNumErrors; } + + void visitArgument(TGraphArgument *parameter) override; + void visitSelection(TGraphSelection *selection) override; + void visitLoop(TGraphLoop *loop) override; + void visitLogicalOp(TGraphLogicalOp *logicalOp) override; + + private: + void beginError(const TIntermNode *node); + void validateUserDefinedFunctionCallUsage(const TDependencyGraph &graph); + bool isSamplingOp(const TIntermAggregate *intermFunctionCall) const; + + TInfoSinkBase &mSink; + int mNumErrors; + + typedef std::set<TString> StringSet; + StringSet mSamplingOps; +}; + +#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ diff --git a/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp b/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp new file mode 100644 index 000000000..7c1208a29 --- /dev/null +++ b/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/timing/RestrictVertexShaderTiming.h" + +void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) +{ + if (IsSampler(node->getBasicType())) { + ++mNumErrors; + mSink.message(EPrefixError, + node->getLine(), + "Samplers are not permitted in vertex shaders.\n"); + } +} diff --git a/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h new file mode 100644 index 000000000..23a821772 --- /dev/null +++ b/gfx/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ +#define COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/InfoSink.h" + +class TInfoSinkBase; + +class RestrictVertexShaderTiming : public TIntermTraverser { +public: + RestrictVertexShaderTiming(TInfoSinkBase& sink) + : TIntermTraverser(true, false, false) + , mSink(sink) + , mNumErrors(0) {} + + void enforceRestrictions(TIntermNode* root) { root->traverse(this); } + int numErrors() { return mNumErrors; } + + void visitSymbol(TIntermSymbol *) override; + +private: + TInfoSinkBase& mSink; + int mNumErrors; +}; + +#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ diff --git a/gfx/angle/src/compiler/translator/util.cpp b/gfx/angle/src/compiler/translator/util.cpp index 89f237ceb..bd3e484eb 100755 --- a/gfx/angle/src/compiler/translator/util.cpp +++ b/gfx/angle/src/compiler/translator/util.cpp @@ -159,30 +159,6 @@ GLenum GLVariableType(const TType &type) case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW; case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW; case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW; - case EbtImage2D: - return GL_IMAGE_2D; - case EbtIImage2D: - return GL_INT_IMAGE_2D; - case EbtUImage2D: - return GL_UNSIGNED_INT_IMAGE_2D; - case EbtImage2DArray: - return GL_IMAGE_2D_ARRAY; - case EbtIImage2DArray: - return GL_INT_IMAGE_2D_ARRAY; - case EbtUImage2DArray: - return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; - case EbtImage3D: - return GL_IMAGE_3D; - case EbtIImage3D: - return GL_INT_IMAGE_3D; - case EbtUImage3D: - return GL_UNSIGNED_INT_IMAGE_3D; - case EbtImageCube: - return GL_IMAGE_CUBE; - case EbtIImageCube: - return GL_INT_IMAGE_CUBE; - case EbtUImageCube: - return GL_UNSIGNED_INT_IMAGE_CUBE; default: UNREACHABLE(); } @@ -302,18 +278,10 @@ InterpolationType GetInterpolationType(TQualifier qualifier) } } -TType GetShaderVariableBasicType(const sh::ShaderVariable &var) +TType ConvertShaderVariableTypeToTType(sh::GLenum type) { - switch (var.type) + switch (type) { - case GL_BOOL: - return TType(EbtBool); - case GL_BOOL_VEC2: - return TType(EbtBool, 2); - case GL_BOOL_VEC3: - return TType(EbtBool, 3); - case GL_BOOL_VEC4: - return TType(EbtBool, 4); case GL_FLOAT: return TType(EbtFloat); case GL_FLOAT_VEC2: @@ -569,52 +537,4 @@ template void GetVariableTraverser::traverse(const TType &, const TString &, std template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *); -// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier -bool CanBeInvariantESSL1(TQualifier qualifier) -{ - return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) || - IsBuiltinOutputVariable(qualifier) || - (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing); -} - -// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier -// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier -bool CanBeInvariantESSL3OrGreater(TQualifier qualifier) -{ - return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut || - IsBuiltinOutputVariable(qualifier); -} - -bool IsBuiltinOutputVariable(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqPosition: - case EvqPointSize: - case EvqFragDepth: - case EvqFragDepthEXT: - case EvqFragColor: - case EvqSecondaryFragColorEXT: - case EvqFragData: - case EvqSecondaryFragDataEXT: - return true; - default: - break; - } - return false; -} - -bool IsBuiltinFragmentInputVariable(TQualifier qualifier) -{ - switch (qualifier) - { - case EvqFragCoord: - case EvqPointCoord: - case EvqFrontFacing: - return true; - default: - break; - } - return false; } -} // namespace sh diff --git a/gfx/angle/src/compiler/translator/util.h b/gfx/angle/src/compiler/translator/util.h index bfad5fb4c..4e577b111 100755 --- a/gfx/angle/src/compiler/translator/util.h +++ b/gfx/angle/src/compiler/translator/util.h @@ -25,9 +25,10 @@ bool strtof_clamp(const std::string &str, float *value); // Return false if overflow happens. bool atoi_clamp(const char *str, unsigned int *value); +class TSymbolTable; + namespace sh { -class TSymbolTable; GLenum GLVariableType(const TType &type); GLenum GLVariablePrecision(const TType &type); @@ -36,8 +37,8 @@ bool IsVaryingOut(TQualifier qualifier); bool IsVarying(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier); TString ArrayString(const TType &type); - -TType GetShaderVariableBasicType(const sh::ShaderVariable &var); +// Handles only basic output variable types. +TType ConvertShaderVariableTypeToTType(sh::GLenum type); TOperator TypeToConstructorOperator(const TType &type); @@ -64,10 +65,6 @@ class GetVariableTraverser : angle::NonCopyable const TSymbolTable &mSymbolTable; }; -bool IsBuiltinOutputVariable(TQualifier qualifier); -bool IsBuiltinFragmentInputVariable(TQualifier qualifier); -bool CanBeInvariantESSL1(TQualifier qualifier); -bool CanBeInvariantESSL3OrGreater(TQualifier qualifier); -} // namespace sh +} #endif // COMPILER_TRANSLATOR_UTIL_H_ |