diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp new file mode 100644 index 0000000000..4ffb832d99 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateGlobalInitializer.cpp @@ -0,0 +1,141 @@ +// +// Copyright (c) 2002-2015 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/ValidateGlobalInitializer.h" + +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +const int kMaxAllowedTraversalDepth = 256; + +class ValidateGlobalInitializerTraverser : public TIntermTraverser +{ + public: + ValidateGlobalInitializerTraverser(int shaderVersion); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitAggregate(Visit visit, TIntermAggregate *node) override; + bool visitBinary(Visit visit, TIntermBinary *node) override; + bool visitUnary(Visit visit, TIntermUnary *node) override; + + bool isValid() const { return mIsValid && mMaxDepth < mMaxAllowedDepth; } + bool issueWarning() const { return mIssueWarning; } + + private: + int mShaderVersion; + bool mIsValid; + bool mIssueWarning; +}; + +void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) +{ + // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): + // Global initializers must be constant expressions. + switch (node->getType().getQualifier()) + { + case EvqConst: + break; + case EvqGlobal: + case EvqTemporary: + case EvqUniform: + // We allow these cases to be compatible with legacy ESSL 1.00 content. + // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal + // with. + if (mShaderVersion >= 300) + { + mIsValid = false; + } + else + { + mIssueWarning = true; + } + break; + default: + mIsValid = false; + } +} + +void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion *node) +{ + // Constant unions that are not constant expressions may result from folding a ternary + // expression. + switch (node->getType().getQualifier()) + { + case EvqConst: + break; + case EvqTemporary: + if (mShaderVersion >= 300) + { + mIsValid = false; + } + else + { + mIssueWarning = true; + } + break; + default: + UNREACHABLE(); + } +} + +bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node) +{ + // Disallow calls to user-defined functions and texture lookup functions in global variable + // initializers. + // This is done simply by disabling all function calls - built-in math functions don't use + // the function call ops. + if (node->isFunctionCall()) + { + mIsValid = false; + } + return true; +} + +bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node) +{ + if (node->isAssignment()) + { + mIsValid = false; + } + return true; +} + +bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node) +{ + if (node->isAssignment()) + { + mIsValid = false; + } + return true; +} + +ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shaderVersion) + : TIntermTraverser(true, false, false, nullptr), + mShaderVersion(shaderVersion), + mIsValid(true), + mIssueWarning(false) +{ + setMaxAllowedDepth(kMaxAllowedTraversalDepth); +} + +} // namespace + +bool ValidateGlobalInitializer(TIntermTyped *initializer, int shaderVersion, bool *warning) +{ + ValidateGlobalInitializerTraverser validate(shaderVersion); + initializer->traverse(&validate); + ASSERT(warning != nullptr); + *warning = validate.issueWarning(); + return validate.isValid(); +} + +} // namespace sh |