Hash :
ea39a223
Author :
Date :
2017-07-06T12:47:59
Simplify queueReplacement AST transform helper queueReplacement is always called to replace the node that's currently being visited in the traverser. The currently visited node can be fetched automatically from the traversal path so it can be removed from parameters of queueReplacement. BUG=angleproject:2100 TEST=angle_unittests Change-Id: I62ab6d1cd9c0d2b4c260af9f7c85bc156fb3f349 Reviewed-on: https://chromium-review.googlesource.com/562336 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//
// 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/IntermTraverse.h"
namespace sh
{
namespace
{
class PruneEmptyDeclarationsTraverser : private TIntermTraverser
{
public:
static void apply(TIntermNode *root);
private:
PruneEmptyDeclarationsTraverser();
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
};
void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
{
PruneEmptyDeclarationsTraverser prune;
root->traverse(&prune);
prune.updateTree();
}
PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser()
: TIntermTraverser(true, false, false)
{
}
bool PruneEmptyDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{
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;
TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
// The declaration may be inside a block or in a loop init expression.
ASSERT(parentAsBlock != nullptr || getParentNode()->getAsLoopNode() != nullptr);
if (parentAsBlock)
{
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
}
else
{
queueReplacement(nullptr, OriginalNode::IS_DROPPED);
}
}
else if (sym->getType().getQualifier() != EvqGlobal &&
sym->getType().getQualifier() != EvqTemporary)
{
// We've hit an empty struct declaration with a qualifier, for example like
// this:
// const struct a { int i; };
// NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so
// we convert the declaration to a regular struct declaration. This is okay,
// since ESSL 1.00 spec section 4.1.8 says about structs that "The optional
// qualifiers only apply to any declarators, and are not part of the type being
// defined for name."
if (mInGlobalScope)
{
sym->getTypePointer()->setQualifier(EvqGlobal);
}
else
{
sym->getTypePointer()->setQualifier(EvqTemporary);
}
}
}
}
return false;
}
} // namespace
void PruneEmptyDeclarations(TIntermNode *root)
{
PruneEmptyDeclarationsTraverser::apply(root);
}
} // namespace sh