Edit

kc3-lang/angle/src/compiler/translator/ValidateGlobalInitializer.cpp

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2015-07-08 17:25:22
    Hash : b5841ef2
    Message : Disallow texture lookup functions in global initializers Do this by simply disallowing all function calls in global initializers - all built-in math ops are handled as other ops, not function calls. This change was tested extensively with popular WebGL content, with no regressions found. TEST=angle_unittests BUG=angleproject:988 Change-Id: Id1107fa294ae4012d5dd3949539d0b7b4cd21943 Reviewed-on: https://chromium-review.googlesource.com/283703 Reviewed-by: Zhenyao Mo <zmo@chromium.org> Tested-by: Olli Etuaho <oetuaho@nvidia.com>

  • src/compiler/translator/ValidateGlobalInitializer.cpp
  • //
    // 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/ParseContext.h"
    
    namespace
    {
    
    class ValidateGlobalInitializerTraverser : public TIntermTraverser
    {
      public:
        ValidateGlobalInitializerTraverser(const TParseContext *context);
    
        void visitSymbol(TIntermSymbol *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; }
        bool issueWarning() const { return mIssueWarning; }
    
      private:
        const TParseContext *mContext;
        bool mIsValid;
        bool mIssueWarning;
    };
    
    void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
    {
        const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion());
        if (sym->isVariable())
        {
            // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
            // Global initializers must be constant expressions.
            const TVariable *var = static_cast<const TVariable *>(sym);
            switch (var->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 (mContext->getShaderVersion() >= 300)
                {
                    mIsValid = false;
                }
                else
                {
                    mIssueWarning = true;
                }
                break;
              default:
                mIsValid = false;
            }
        }
    }
    
    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 EOpFunctionCall.
        if (node->getOp() == EOpFunctionCall)
        {
            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(const TParseContext *context)
        : TIntermTraverser(true, false, false),
          mContext(context),
          mIsValid(true),
          mIssueWarning(false)
    {
    }
    
    } // namespace
    
    bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning)
    {
        ValidateGlobalInitializerTraverser validate(context);
        initializer->traverse(&validate);
        ASSERT(warning != nullptr);
        *warning = validate.issueWarning();
        return validate.isValid();
    }