Commit c6833115 by Olli Etuaho

Prune empty declarations from the AST

Empty declarations in ESSL shaders currently result in errors on several platforms. Prune empty declarations that are not struct or interface block declarations from the AST. TEST=WebGL conformance tests, angle_unittests, angle_end2end_tests BUG=angleproject:980 Change-Id: I9e3abf8134e6dfed0253cc83f69ce0ee92b0e0e7 Reviewed-on: https://chromium-review.googlesource.com/266841Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 39282e1f
......@@ -78,6 +78,8 @@
'compiler/translator/PoolAlloc.cpp',
'compiler/translator/PoolAlloc.h',
'compiler/translator/Pragma.h',
'compiler/translator/PruneEmptyDeclarations.cpp',
'compiler/translator/PruneEmptyDeclarations.h',
'compiler/translator/QualifierAlive.cpp',
'compiler/translator/QualifierAlive.h',
'compiler/translator/RegenerateStructNames.cpp',
......
......@@ -11,6 +11,7 @@
#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/ParseContext.h"
#include "compiler/translator/PruneEmptyDeclarations.h"
#include "compiler/translator/RegenerateStructNames.h"
#include "compiler/translator/RenameFunction.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
......@@ -249,6 +250,10 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
if (success && !(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
success = pruneUnusedFunctions(root);
// Prune empty declarations to work around driver bugs and to keep declaration output simple.
if (success)
PruneEmptyDeclarations(root);
if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER)
success = validateOutputs(root);
......
//
// 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.
//
// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from the AST.
#include "compiler/translator/PruneEmptyDeclarations.h"
#include "compiler/translator/IntermNode.h"
namespace
{
class PruneEmptyDeclarationsTraverser : private TIntermTraverser
{
public:
static void apply(TIntermNode *root);
private:
PruneEmptyDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override;
};
void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
{
PruneEmptyDeclarationsTraverser prune;
root->traverse(&prune);
prune.updateTree();
}
PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser()
: TIntermTraverser(true, false, false)
{
}
bool PruneEmptyDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node)
{
if (node->getOp() == EOpDeclaration)
{
TIntermSequence *sequence = node->getSequence();
if (sequence->size() >= 1)
{
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())
{
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)
{
// 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));
}
}
}
return false;
}
return true;
}
} // namespace
void PruneEmptyDeclarations(TIntermNode *root)
{
PruneEmptyDeclarationsTraverser::apply(root);
}
//
// 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.
//
// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from the AST.
#ifndef COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
#define COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
class TIntermNode;
void PruneEmptyDeclarations(TIntermNode *root);
#endif // COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
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