blob: 7ec4347963e4e3333c6ae435c4b871fec94c774d [file] [log] [blame]
Olli Etuahoc6833112015-04-22 15:15:54 +03001//
2// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from the AST.
7
8#include "compiler/translator/PruneEmptyDeclarations.h"
9
10#include "compiler/translator/IntermNode.h"
11
Jamie Madill45bcc782016-11-07 13:58:48 -050012namespace sh
13{
14
Olli Etuahoc6833112015-04-22 15:15:54 +030015namespace
16{
17
18class PruneEmptyDeclarationsTraverser : private TIntermTraverser
19{
20 public:
21 static void apply(TIntermNode *root);
22 private:
23 PruneEmptyDeclarationsTraverser();
Olli Etuaho13389b62016-10-16 11:48:18 +010024 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
Olli Etuahoc6833112015-04-22 15:15:54 +030025};
26
27void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
28{
29 PruneEmptyDeclarationsTraverser prune;
30 root->traverse(&prune);
31 prune.updateTree();
32}
33
34PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser()
35 : TIntermTraverser(true, false, false)
36{
37}
38
Olli Etuaho13389b62016-10-16 11:48:18 +010039bool PruneEmptyDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
Olli Etuahoc6833112015-04-22 15:15:54 +030040{
Olli Etuaho13389b62016-10-16 11:48:18 +010041 TIntermSequence *sequence = node->getSequence();
42 if (sequence->size() >= 1)
Olli Etuahoc6833112015-04-22 15:15:54 +030043 {
Olli Etuaho13389b62016-10-16 11:48:18 +010044 TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
45 // Prune declarations without a variable name, unless it's an interface block declaration.
46 if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
Olli Etuahoc6833112015-04-22 15:15:54 +030047 {
Olli Etuaho13389b62016-10-16 11:48:18 +010048 if (sequence->size() > 1)
Olli Etuahoc6833112015-04-22 15:15:54 +030049 {
Olli Etuaho13389b62016-10-16 11:48:18 +010050 // Generate a replacement that will remove the empty declarator in the beginning of
51 // a declarator list. Example of a declaration that will be changed:
52 // float, a;
53 // will be changed to
54 // float a;
55 // This applies also to struct declarations.
56 TIntermSequence emptyReplacement;
57 mMultiReplacements.push_back(
58 NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
59 }
60 else if (sym->getBasicType() != EbtStruct)
61 {
62 // Single struct declarations may just declare the struct type and no variables, so
63 // they should not be pruned. All other single empty declarations can be pruned
64 // entirely. Example of an empty declaration that will be pruned:
65 // float;
66 TIntermSequence emptyReplacement;
67 TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
68 // The declaration may be inside a block or in a loop init expression.
69 ASSERT(parentAsBlock != nullptr || getParentNode()->getAsLoopNode() != nullptr);
70 if (parentAsBlock)
Olli Etuahoc6833112015-04-22 15:15:54 +030071 {
Olli Etuaho13389b62016-10-16 11:48:18 +010072 mMultiReplacements.push_back(
73 NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
Olli Etuahoc6833112015-04-22 15:15:54 +030074 }
Olli Etuaho13389b62016-10-16 11:48:18 +010075 else
Olli Etuahoc6833112015-04-22 15:15:54 +030076 {
Olli Etuaho13389b62016-10-16 11:48:18 +010077 queueReplacement(node, nullptr, OriginalNode::IS_DROPPED);
Olli Etuahoc6833112015-04-22 15:15:54 +030078 }
Olli Etuaho13389b62016-10-16 11:48:18 +010079 }
80 else if (sym->getType().getQualifier() != EvqGlobal &&
81 sym->getType().getQualifier() != EvqTemporary)
82 {
83 // We've hit an empty struct declaration with a qualifier, for example like
84 // this:
85 // const struct a { int i; };
86 // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so
87 // we convert the declaration to a regular struct declaration. This is okay,
88 // since ESSL 1.00 spec section 4.1.8 says about structs that "The optional
89 // qualifiers only apply to any declarators, and are not part of the type being
90 // defined for name."
Olli Etuaho474a08c02016-06-28 10:49:46 +030091
Olli Etuaho13389b62016-10-16 11:48:18 +010092 if (mInGlobalScope)
93 {
94 sym->getTypePointer()->setQualifier(EvqGlobal);
95 }
96 else
97 {
98 sym->getTypePointer()->setQualifier(EvqTemporary);
Olli Etuaho474a08c02016-06-28 10:49:46 +030099 }
Olli Etuahoc6833112015-04-22 15:15:54 +0300100 }
101 }
Olli Etuahoc6833112015-04-22 15:15:54 +0300102 }
Olli Etuaho13389b62016-10-16 11:48:18 +0100103 return false;
Olli Etuahoc6833112015-04-22 15:15:54 +0300104}
105
106} // namespace
107
108void PruneEmptyDeclarations(TIntermNode *root)
109{
110 PruneEmptyDeclarationsTraverser::apply(root);
111}
Jamie Madill45bcc782016-11-07 13:58:48 -0500112
113} // namespace sh