Commit 9ec79391 by Olli Etuaho Committed by Commit Bot

Use TLValueTrackingTraverser in ValidateLimitations

Use TLValueTrackingTraverser to determine whether a loop index is used as an l-value. This replaces custom logic in ValidateLimitations, greatly simplifying the code. Also pass the symbol table to ValidateLimitations as a parameter, which removes the need to store a global pointer to the current ParseContext. BUG=angleproject:1960 TEST=angle_unittests, WebGL conformance tests Change-Id: I122c85c78bbea05833d7c787cd184de568c5c45f Reviewed-on: https://chromium-review.googlesource.com/465606 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent b5e884a4
...@@ -64,8 +64,6 @@ ...@@ -64,8 +64,6 @@
'compiler/translator/InitializeDll.cpp', 'compiler/translator/InitializeDll.cpp',
'compiler/translator/InitializeDll.h', 'compiler/translator/InitializeDll.h',
'compiler/translator/InitializeGlobals.h', 'compiler/translator/InitializeGlobals.h',
'compiler/translator/InitializeParseContext.cpp',
'compiler/translator/InitializeParseContext.h',
'compiler/translator/InitializeVariables.cpp', 'compiler/translator/InitializeVariables.cpp',
'compiler/translator/InitializeVariables.h', 'compiler/translator/InitializeVariables.h',
'compiler/translator/IntermNode.h', 'compiler/translator/IntermNode.h',
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "compiler/translator/EmulateGLFragColorBroadcast.h" #include "compiler/translator/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/Initialize.h" #include "compiler/translator/Initialize.h"
#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/InitializeVariables.h" #include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
#include "compiler/translator/PruneEmptyDeclarations.h" #include "compiler/translator/PruneEmptyDeclarations.h"
...@@ -293,7 +292,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -293,7 +292,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
compileOptions, true, &mDiagnostics, getResources()); compileOptions, true, &mDiagnostics, getResources());
parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh); parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile. // We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level. // Start pushing the user-defined symbols at global level.
...@@ -368,7 +366,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -368,7 +366,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
success = validateOutputs(root); success = validateOutputs(root);
if (success && shouldRunLoopAndIndexingValidation(compileOptions)) if (success && shouldRunLoopAndIndexingValidation(compileOptions))
success = validateLimitations(root); success =
ValidateLimitations(root, shaderType, symbolTable, shaderVersion, &mDiagnostics);
bool multiview2 = IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2"); bool multiview2 = IsExtensionEnabled(extensionBehavior, "GL_OVR_multiview2");
if (success && compileResources.OVR_multiview && IsWebGLBasedSpec(shaderSpec) && if (success && compileResources.OVR_multiview && IsWebGLBasedSpec(shaderSpec) &&
...@@ -477,7 +476,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[], ...@@ -477,7 +476,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
} }
} }
SetGlobalParseContext(NULL);
if (success) if (success)
return root; return root;
...@@ -854,13 +852,6 @@ bool TCompiler::validateOutputs(TIntermNode *root) ...@@ -854,13 +852,6 @@ bool TCompiler::validateOutputs(TIntermNode *root)
return (mDiagnostics.numErrors() == 0); return (mDiagnostics.numErrors() == 0);
} }
bool TCompiler::validateLimitations(TIntermNode *root)
{
ValidateLimitations validate(shaderType, &mDiagnostics);
root->traverse(&validate);
return mDiagnostics.numErrors() == 0;
}
bool TCompiler::limitExpressionComplexity(TIntermNode *root) bool TCompiler::limitExpressionComplexity(TIntermNode *root)
{ {
TMaxDepthTraverser traverser(maxExpressionComplexity + 1); TMaxDepthTraverser traverser(maxExpressionComplexity + 1);
......
...@@ -135,9 +135,6 @@ class TCompiler : public TShHandleBase ...@@ -135,9 +135,6 @@ class TCompiler : public TShHandleBase
bool checkCallDepth(); bool checkCallDepth();
// Returns true if a program has no conflicting or missing fragment outputs // Returns true if a program has no conflicting or missing fragment outputs
bool validateOutputs(TIntermNode *root); bool validateOutputs(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);
// Add emulated functions to the built-in function emulator. // Add emulated functions to the built-in function emulator.
virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
ShCompileOptions compileOptions){}; ShCompileOptions compileOptions){};
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "compiler/translator/Cache.h" #include "compiler/translator/Cache.h"
#include "compiler/translator/InitializeDll.h" #include "compiler/translator/InitializeDll.h"
#include "compiler/translator/InitializeGlobals.h" #include "compiler/translator/InitializeGlobals.h"
#include "compiler/translator/InitializeParseContext.h"
#include "common/platform.h" #include "common/platform.h"
...@@ -24,12 +23,6 @@ bool InitProcess() ...@@ -24,12 +23,6 @@ bool InitProcess()
return false; return false;
} }
if (!InitializeParseContextIndex())
{
assert(0 && "InitProcess(): Failed to initalize parse context");
return false;
}
TCache::initialize(); TCache::initialize();
return true; return true;
...@@ -37,7 +30,6 @@ bool InitProcess() ...@@ -37,7 +30,6 @@ bool InitProcess()
void DetachProcess() void DetachProcess()
{ {
FreeParseContextIndex();
FreePoolIndex(); FreePoolIndex();
TCache::destroy(); TCache::destroy();
} }
......
//
// 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/InitializeParseContext.h"
#include "common/tls.h"
#include <assert.h>
namespace sh
{
TLSIndex GlobalParseContextIndex = TLS_INVALID_INDEX;
bool InitializeParseContextIndex()
{
assert(GlobalParseContextIndex == TLS_INVALID_INDEX);
GlobalParseContextIndex = CreateTLSIndex();
return GlobalParseContextIndex != TLS_INVALID_INDEX;
}
void FreeParseContextIndex()
{
assert(GlobalParseContextIndex != TLS_INVALID_INDEX);
DestroyTLSIndex(GlobalParseContextIndex);
GlobalParseContextIndex = TLS_INVALID_INDEX;
}
void SetGlobalParseContext(TParseContext *context)
{
assert(GlobalParseContextIndex != TLS_INVALID_INDEX);
SetTLSValue(GlobalParseContextIndex, context);
}
TParseContext *GetGlobalParseContext()
{
assert(GlobalParseContextIndex != TLS_INVALID_INDEX);
return static_cast<TParseContext *>(GetTLSValue(GlobalParseContextIndex));
}
} // namespace sh
//
// 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.
//
#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_
...@@ -14,48 +14,13 @@ namespace sh ...@@ -14,48 +14,13 @@ namespace sh
class TDiagnostics; class TDiagnostics;
// Traverses intermediate tree to ensure that the shader does not exceed the // Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES
// minimum functionality mandated in GLSL 1.0 spec, Appendix A. // 1.00 spec Appendix A.
class ValidateLimitations : public TIntermTraverser bool ValidateLimitations(TIntermNode *root,
{ GLenum shaderType,
public: const TSymbolTable &symbolTable,
ValidateLimitations(sh::GLenum shaderType, TDiagnostics *diagnostics); int shaderVersion,
TDiagnostics *diagnostics);
bool visitBinary(Visit, TIntermBinary *) override;
bool visitUnary(Visit, TIntermUnary *) override;
bool visitAggregate(Visit, TIntermAggregate *) override;
bool visitLoop(Visit, TIntermLoop *) override;
private:
void error(TSourceLoc loc, const char *reason, const char *token);
bool withinLoopBody() const;
bool isLoopIndex(TIntermSymbol *symbol);
bool validateLoopType(TIntermLoop *node);
bool validateForLoopHeader(TIntermLoop *node);
// If valid, return the index symbol id; Otherwise, return -1.
int validateForLoopInit(TIntermLoop *node);
bool validateForLoopCond(TIntermLoop *node, int indexSymbolId);
bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId);
// Returns true if none of the loop indices is used as the argument to
// the given function out or inout parameter.
bool validateFunctionCall(TIntermAggregate *node);
bool validateOperation(TIntermOperator *node, TIntermNode *operand);
// Returns true if indexing does not exceed the minimum functionality
// mandated in GLSL 1.0 spec, Appendix A, Section 5.
bool isConstExpr(TIntermNode *node);
bool isConstIndexExpr(TIntermNode *node);
bool validateIndexing(TIntermBinary *node);
sh::GLenum mShaderType;
TDiagnostics *mDiagnostics;
std::vector<int> mLoopSymbolIds;
bool mValidateIndexing;
bool mValidateInnerLoops;
};
} // namespace sh } // namespace sh
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "compiler/translator/ValidateOutputs.h" #include "compiler/translator/ValidateOutputs.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
namespace sh namespace sh
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
'<(angle_path)/src/libANGLE/validationES_unittest.cpp', '<(angle_path)/src/libANGLE/validationES_unittest.cpp',
'<(angle_path)/src/tests/angle_unittests_utils.h', '<(angle_path)/src/tests/angle_unittests_utils.h',
'<(angle_path)/src/tests/compiler_tests/API_test.cpp', '<(angle_path)/src/tests/compiler_tests/API_test.cpp',
'<(angle_path)/src/tests/compiler_tests/AppendixALimitations_test.cpp',
'<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp', '<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ConstantFolding_test.cpp', '<(angle_path)/src/tests/compiler_tests/ConstantFolding_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp', '<(angle_path)/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp',
......
//
// Copyright (c) 2017 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.
//
// AppendixALimitations_test.cpp:
// Tests for validating ESSL 1.00 Appendix A limitations.
//
#include "gtest/gtest.h"
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
using namespace sh;
class AppendixALimitationsTest : public ShaderCompileTreeTest
{
public:
AppendixALimitationsTest() {}
protected:
::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
ShShaderSpec getShaderSpec() const override { return SH_WEBGL_SPEC; }
};
// Test an invalid shader where a for loop index is used as an out parameter.
TEST_F(AppendixALimitationsTest, IndexAsFunctionOutParameter)
{
const std::string &shaderString =
"precision mediump float;\n"
"void fun(out int a)\n"
"{\n"
" a = 2;\n"
"}\n"
"void main()\n"
"{\n"
" for (int i = 0; i < 2; ++i)\n"
" {\n"
" fun(i);\n"
" }\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test an invalid shader where a for loop index is used as an inout parameter.
TEST_F(AppendixALimitationsTest, IndexAsFunctionInOutParameter)
{
const std::string &shaderString =
"precision mediump float;\n"
"void fun(int b, inout int a)\n"
"{\n"
" a += b;\n"
"}\n"
"void main()\n"
"{\n"
" for (int i = 0; i < 2; ++i)\n"
" {\n"
" fun(2, i);\n"
" }\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test a valid shader where a for loop index is used as an in parameter in a function that also has
// an out parameter.
TEST_F(AppendixALimitationsTest, IndexAsFunctionInParameter)
{
const std::string &shaderString =
"precision mediump float;\n"
"void fun(int b, inout int a)\n"
"{\n"
" a += b;\n"
"}\n"
"void main()\n"
"{\n"
" for (int i = 0; i < 2; ++i)\n"
" {\n"
" int a = 1;"
" fun(i, a);\n"
" }\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test an invalid shader where a for loop index is used as a target of assignment.
TEST_F(AppendixALimitationsTest, IndexAsTargetOfAssignment)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" for (int i = 0; i < 2; ++i)\n"
" {\n"
" i = 2;\n"
" }\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test an invalid shader where a for loop index is incremented inside the loop.
TEST_F(AppendixALimitationsTest, IndexIncrementedInLoopBody)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" for (int i = 0; i < 2; ++i)\n"
" {\n"
" ++i;\n"
" }\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment