Hash :
c6833115
Author :
Date :
2015-04-22T15:15:54
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/266841 Reviewed-by: Olli Etuaho <oetuaho@nvidia.com> Tested-by: Olli Etuaho <oetuaho@nvidia.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
//
// 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);
}