diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp | 512 |
1 files changed, 0 insertions, 512 deletions
diff --git a/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp b/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp deleted file mode 100644 index 64969c489..000000000 --- a/Source/ThirdParty/ANGLE/src/compiler/ValidateLimitations.cpp +++ /dev/null @@ -1,512 +0,0 @@ -// -// Copyright (c) 2002-2010 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/ValidateLimitations.h" -#include "compiler/InfoSink.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/ParseContext.h" - -namespace { -bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { - for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) - return true; - } - return false; -} - -void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { - for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) { - ASSERT(i->loop != NULL); - i->loop->setUnrollFlag(true); - return; - } - } - UNREACHABLE(); -} - -// Traverses a node to check if it represents a constant index expression. -// Definition: -// constant-index-expressions are a superset of constant-expressions. -// Constant-index-expressions can include loop indices as defined in -// GLSL ES 1.0 spec, Appendix A, section 4. -// The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above -class ValidateConstIndexExpr : public TIntermTraverser { -public: - ValidateConstIndexExpr(const TLoopStack& stack) - : mValid(true), mLoopStack(stack) {} - - // Returns true if the parsed node represents a constant index expression. - bool isValid() const { return mValid; } - - virtual void visitSymbol(TIntermSymbol* symbol) { - // Only constants and loop indices are allowed in a - // constant index expression. - if (mValid) { - mValid = (symbol->getQualifier() == EvqConst) || - IsLoopIndex(symbol, mLoopStack); - } - } - -private: - bool mValid; - const TLoopStack& mLoopStack; -}; - -// Traverses a node to check if it uses a loop index. -// If an int loop index is used in its body as a sampler array index, -// mark the loop for unroll. -class ValidateLoopIndexExpr : public TIntermTraverser { -public: - ValidateLoopIndexExpr(TLoopStack& stack) - : mUsesFloatLoopIndex(false), - mUsesIntLoopIndex(false), - mLoopStack(stack) {} - - bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } - bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } - - virtual void visitSymbol(TIntermSymbol* symbol) { - if (IsLoopIndex(symbol, mLoopStack)) { - switch (symbol->getBasicType()) { - case EbtFloat: - mUsesFloatLoopIndex = true; - break; - case EbtInt: - mUsesIntLoopIndex = true; - MarkLoopForUnroll(symbol, mLoopStack); - break; - default: - UNREACHABLE(); - } - } - } - -private: - bool mUsesFloatLoopIndex; - bool mUsesIntLoopIndex; - TLoopStack& mLoopStack; -}; -} // namespace - -ValidateLimitations::ValidateLimitations(ShShaderType shaderType, - TInfoSinkBase& sink) - : mShaderType(shaderType), - mSink(sink), - mNumErrors(0) -{ -} - -bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) -{ - // Check if loop index is modified in the loop body. - validateOperation(node, node->getLeft()); - - // Check indexing. - switch (node->getOp()) { - case EOpIndexDirect: - validateIndexing(node); - break; - case EOpIndexIndirect: -#if defined(__APPLE__) - // Loop unrolling is a work-around for a Mac Cg compiler bug where it - // crashes when a sampler array's index is also the loop index. - // Once Apple fixes this bug, we should remove the code in this CL. - // See http://codereview.appspot.com/4331048/. - if ((node->getLeft() != NULL) && (node->getRight() != NULL) && - (node->getLeft()->getAsSymbolNode())) { - TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); - if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { - ValidateLoopIndexExpr validate(mLoopStack); - node->getRight()->traverse(&validate); - if (validate.usesFloatLoopIndex()) { - error(node->getLine(), - "sampler array index is float loop index", - "for"); - } - } - } -#endif - validateIndexing(node); - break; - default: break; - } - return true; -} - -bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) -{ - // Check if loop index is modified in the loop body. - validateOperation(node, node->getOperand()); - - return true; -} - -bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) -{ - switch (node->getOp()) { - case EOpFunctionCall: - validateFunctionCall(node); - break; - default: - break; - } - return true; -} - -bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) -{ - if (!validateLoopType(node)) - return false; - - TLoopInfo info; - memset(&info, 0, sizeof(TLoopInfo)); - info.loop = node; - if (!validateForLoopHeader(node, &info)) - return false; - - TIntermNode* body = node->getBody(); - if (body != NULL) { - mLoopStack.push_back(info); - body->traverse(this); - mLoopStack.pop_back(); - } - - // The loop is fully processed - no need to visit children. - return false; -} - -void ValidateLimitations::error(TSourceLoc loc, - const char *reason, const char* token) -{ - mSink.prefix(EPrefixError); - mSink.location(loc); - mSink << "'" << token << "' : " << reason << "\n"; - ++mNumErrors; -} - -bool ValidateLimitations::withinLoopBody() const -{ - return !mLoopStack.empty(); -} - -bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const -{ - return IsLoopIndex(symbol, mLoopStack); -} - -bool ValidateLimitations::validateLoopType(TIntermLoop* node) { - TLoopType type = node->getType(); - if (type == ELoopFor) - return true; - - // Reject while and do-while loops. - error(node->getLine(), - "This type of loop is not allowed", - type == ELoopWhile ? "while" : "do"); - return false; -} - -bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, - TLoopInfo* info) -{ - ASSERT(node->getType() == ELoopFor); - - // - // The for statement has the form: - // for ( init-declaration ; condition ; expression ) statement - // - if (!validateForLoopInit(node, info)) - return false; - if (!validateForLoopCond(node, info)) - return false; - if (!validateForLoopExpr(node, info)) - return false; - - return true; -} - -bool ValidateLimitations::validateForLoopInit(TIntermLoop* node, - TLoopInfo* info) -{ - TIntermNode* init = node->getInit(); - if (init == NULL) { - error(node->getLine(), "Missing init declaration", "for"); - return false; - } - - // - // init-declaration has the form: - // type-specifier identifier = constant-expression - // - TIntermAggregate* decl = init->getAsAggregate(); - if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { - error(init->getLine(), "Invalid init declaration", "for"); - return false; - } - // To keep things simple do not allow declaration list. - TIntermSequence& declSeq = decl->getSequence(); - if (declSeq.size() != 1) { - error(decl->getLine(), "Invalid init declaration", "for"); - return false; - } - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { - error(decl->getLine(), "Invalid init declaration", "for"); - return false; - } - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { - error(declInit->getLine(), "Invalid init declaration", "for"); - return false; - } - // The loop index has type int or float. - TBasicType type = symbol->getBasicType(); - if ((type != EbtInt) && (type != EbtFloat)) { - error(symbol->getLine(), - "Invalid type for loop index", getBasicString(type)); - return false; - } - // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) { - error(declInit->getLine(), - "Loop index cannot be initialized with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - - info->index.id = symbol->getId(); - return true; -} - -bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, - TLoopInfo* info) -{ - TIntermNode* cond = node->getCondition(); - if (cond == NULL) { - error(node->getLine(), "Missing condition", "for"); - return false; - } - // - // condition has the form: - // loop_index relational_operator constant_expression - // - TIntermBinary* binOp = cond->getAsBinaryNode(); - if (binOp == NULL) { - error(node->getLine(), "Invalid condition", "for"); - return false; - } - // Loop index should be to the left of relational operator. - TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { - error(binOp->getLine(), "Invalid condition", "for"); - return false; - } - if (symbol->getId() != info->index.id) { - error(symbol->getLine(), - "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - default: - error(binOp->getLine(), - "Invalid relational operator", - getOperatorString(binOp->getOp())); - break; - } - // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) { - error(binOp->getLine(), - "Loop index cannot be compared with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - - return true; -} - -bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, - TLoopInfo* info) -{ - TIntermNode* expr = node->getExpression(); - if (expr == NULL) { - error(node->getLine(), "Missing expression", "for"); - return false; - } - - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary* unOp = expr->getAsUnaryNode(); - TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - TIntermSymbol* symbol = NULL; - if (unOp != NULL) { - op = unOp->getOp(); - symbol = unOp->getOperand()->getAsSymbolNode(); - } else if (binOp != NULL) { - op = binOp->getOp(); - symbol = binOp->getLeft()->getAsSymbolNode(); - } - - // The operand must be loop index. - if (symbol == NULL) { - error(expr->getLine(), "Invalid expression", "for"); - return false; - } - if (symbol->getId() != info->index.id) { - error(symbol->getLine(), - "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - - // The operator is one of: ++ -- += -=. - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - break; - default: - error(expr->getLine(), "Invalid operator", getOperatorString(op)); - return false; - } - - // Loop index must be incremented/decremented with a constant. - if (binOp != NULL) { - if (!isConstExpr(binOp->getRight())) { - error(binOp->getLine(), - "Loop index cannot be modified by non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - } - - return true; -} - -bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) -{ - ASSERT(node->getOp() == EOpFunctionCall); - - // If not within loop body, there is nothing to check. - if (!withinLoopBody()) - return true; - - // List of param indices for which loop indices are used as argument. - typedef std::vector<size_t> ParamIndex; - ParamIndex pIndex; - TIntermSequence& params = node->getSequence(); - for (TIntermSequence::size_type i = 0; i < params.size(); ++i) { - TIntermSymbol* symbol = params[i]->getAsSymbolNode(); - if (symbol && isLoopIndex(symbol)) - pIndex.push_back(i); - } - // If none of the loop indices are used as arguments, - // there is nothing to check. - if (pIndex.empty()) - return true; - - bool valid = true; - TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; - TSymbol* symbol = symbolTable.find(node->getName()); - ASSERT(symbol && symbol->isFunction()); - TFunction* function = static_cast<TFunction*>(symbol); - for (ParamIndex::const_iterator i = pIndex.begin(); - i != pIndex.end(); ++i) { - const TParameter& param = function->getParam(*i); - TQualifier qual = param.type->getQualifier(); - if ((qual == EvqOut) || (qual == EvqInOut)) { - error(params[*i]->getLine(), - "Loop index cannot be used as argument to a function out or inout parameter", - params[*i]->getAsSymbolNode()->getSymbol().c_str()); - valid = false; - } - } - - return valid; -} - -bool ValidateLimitations::validateOperation(TIntermOperator* node, - TIntermNode* operand) { - // Check if loop index is modified in the loop body. - if (!withinLoopBody() || !node->isAssignment()) - return true; - - const TIntermSymbol* symbol = operand->getAsSymbolNode(); - if (symbol && isLoopIndex(symbol)) { - error(node->getLine(), - "Loop index cannot be statically assigned to within the body of the loop", - symbol->getSymbol().c_str()); - } - return true; -} - -bool ValidateLimitations::isConstExpr(TIntermNode* node) -{ - ASSERT(node != NULL); - return node->getAsConstantUnion() != NULL; -} - -bool ValidateLimitations::isConstIndexExpr(TIntermNode* node) -{ - ASSERT(node != NULL); - - ValidateConstIndexExpr validate(mLoopStack); - node->traverse(&validate); - return validate.isValid(); -} - -bool ValidateLimitations::validateIndexing(TIntermBinary* node) -{ - ASSERT((node->getOp() == EOpIndexDirect) || - (node->getOp() == EOpIndexIndirect)); - - bool valid = true; - TIntermTyped* index = node->getRight(); - // The index expression must have integral type. - if (!index->isScalar() || (index->getBasicType() != EbtInt)) { - error(index->getLine(), - "Index expression must have integral type", - index->getCompleteString().c_str()); - valid = false; - } - // The index expession must be a constant-index-expression unless - // the operand is a uniform in a vertex shader. - TIntermTyped* operand = node->getLeft(); - bool skip = (mShaderType == SH_VERTEX_SHADER) && - (operand->getQualifier() == EvqUniform); - if (!skip && !isConstIndexExpr(index)) { - error(index->getLine(), "Index expression must be constant", "[]"); - valid = false; - } - return valid; -} - |