1 //
2 // Copyright 2018 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 // ReplaceVariable.cpp: Replace all references to a specific variable in the AST with references to
7 // another variable.
8
9 #include "compiler/translator/tree_util/ReplaceVariable.h"
10
11 #include "compiler/translator/IntermNode.h"
12 #include "compiler/translator/Symbol.h"
13 #include "compiler/translator/tree_util/IntermTraverse.h"
14
15 namespace sh
16 {
17
18 namespace
19 {
20
21 class ReplaceVariableTraverser : public TIntermTraverser
22 {
23 public:
ReplaceVariableTraverser(const TVariable * toBeReplaced,const TIntermTyped * replacement)24 ReplaceVariableTraverser(const TVariable *toBeReplaced, const TIntermTyped *replacement)
25 : TIntermTraverser(true, false, false),
26 mToBeReplaced(toBeReplaced),
27 mReplacement(replacement)
28 {}
29
visitSymbol(TIntermSymbol * node)30 void visitSymbol(TIntermSymbol *node) override
31 {
32 if (&node->variable() == mToBeReplaced)
33 {
34 queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED);
35 }
36 }
37
38 private:
39 const TVariable *const mToBeReplaced;
40 const TIntermTyped *const mReplacement;
41 };
42
43 class ReplaceVariablesTraverser : public TIntermTraverser
44 {
45 public:
ReplaceVariablesTraverser(const VariableReplacementMap & variableMap)46 ReplaceVariablesTraverser(const VariableReplacementMap &variableMap)
47 : TIntermTraverser(true, false, false), mVariableMap(variableMap)
48 {}
49
visitSymbol(TIntermSymbol * node)50 void visitSymbol(TIntermSymbol *node) override
51 {
52 auto iter = mVariableMap.find(&node->variable());
53 if (iter != mVariableMap.end())
54 {
55 queueReplacement(iter->second->deepCopy(), OriginalNode::IS_DROPPED);
56 }
57 }
58
59 private:
60 const VariableReplacementMap &mVariableMap;
61 };
62
63 class GetDeclaratorReplacementsTraverser : public TIntermTraverser
64 {
65 public:
GetDeclaratorReplacementsTraverser(TSymbolTable * symbolTable,VariableReplacementMap * variableMap)66 GetDeclaratorReplacementsTraverser(TSymbolTable *symbolTable,
67 VariableReplacementMap *variableMap)
68 : TIntermTraverser(true, false, false, symbolTable), mVariableMap(variableMap)
69 {}
70
visitDeclaration(Visit visit,TIntermDeclaration * node)71 bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
72 {
73 const TIntermSequence &sequence = *(node->getSequence());
74
75 for (TIntermNode *decl : sequence)
76 {
77 TIntermSymbol *asSymbol = decl->getAsSymbolNode();
78 TIntermBinary *asBinary = decl->getAsBinaryNode();
79
80 if (asBinary != nullptr)
81 {
82 ASSERT(asBinary->getOp() == EOpInitialize);
83 asSymbol = asBinary->getLeft()->getAsSymbolNode();
84 }
85
86 ASSERT(asSymbol);
87 const TVariable &variable = asSymbol->variable();
88
89 ASSERT(mVariableMap->find(&variable) == mVariableMap->end());
90
91 const TVariable *replacementVariable = new TVariable(
92 mSymbolTable, variable.name(), &variable.getType(), variable.symbolType());
93
94 (*mVariableMap)[&variable] = new TIntermSymbol(replacementVariable);
95 }
96
97 return false;
98 }
99
100 private:
101 VariableReplacementMap *mVariableMap;
102 };
103
104 } // anonymous namespace
105
106 // Replaces every occurrence of a variable with another variable.
ReplaceVariable(TCompiler * compiler,TIntermBlock * root,const TVariable * toBeReplaced,const TVariable * replacement)107 ANGLE_NO_DISCARD bool ReplaceVariable(TCompiler *compiler,
108 TIntermBlock *root,
109 const TVariable *toBeReplaced,
110 const TVariable *replacement)
111 {
112 ReplaceVariableTraverser traverser(toBeReplaced, new TIntermSymbol(replacement));
113 root->traverse(&traverser);
114 return traverser.updateTree(compiler, root);
115 }
116
ReplaceVariables(TCompiler * compiler,TIntermBlock * root,const VariableReplacementMap & variableMap)117 ANGLE_NO_DISCARD bool ReplaceVariables(TCompiler *compiler,
118 TIntermBlock *root,
119 const VariableReplacementMap &variableMap)
120 {
121 ReplaceVariablesTraverser traverser(variableMap);
122 root->traverse(&traverser);
123 return traverser.updateTree(compiler, root);
124 }
125
GetDeclaratorReplacements(TSymbolTable * symbolTable,TIntermBlock * root,VariableReplacementMap * variableMap)126 void GetDeclaratorReplacements(TSymbolTable *symbolTable,
127 TIntermBlock *root,
128 VariableReplacementMap *variableMap)
129 {
130 GetDeclaratorReplacementsTraverser traverser(symbolTable, variableMap);
131 root->traverse(&traverser);
132 }
133
134 // Replaces every occurrence of a variable with a TIntermNode.
ReplaceVariableWithTyped(TCompiler * compiler,TIntermBlock * root,const TVariable * toBeReplaced,const TIntermTyped * replacement)135 ANGLE_NO_DISCARD bool ReplaceVariableWithTyped(TCompiler *compiler,
136 TIntermBlock *root,
137 const TVariable *toBeReplaced,
138 const TIntermTyped *replacement)
139 {
140 ReplaceVariableTraverser traverser(toBeReplaced, replacement);
141 root->traverse(&traverser);
142 return traverser.updateTree(compiler, root);
143 }
144
145 } // namespace sh
146