ReplaceVariable.cpp (4676B)
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: 24 ReplaceVariableTraverser(const TVariable *toBeReplaced, const TIntermTyped *replacement) 25 : TIntermTraverser(true, false, false), 26 mToBeReplaced(toBeReplaced), 27 mReplacement(replacement) 28 {} 29 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: 46 ReplaceVariablesTraverser(const VariableReplacementMap &variableMap) 47 : TIntermTraverser(true, false, false), mVariableMap(variableMap) 48 {} 49 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: 66 GetDeclaratorReplacementsTraverser(TSymbolTable *symbolTable, 67 VariableReplacementMap *variableMap) 68 : TIntermTraverser(true, false, false, symbolTable), mVariableMap(variableMap) 69 {} 70 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. 107 [[nodiscard]] 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 117 [[nodiscard]] 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 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. 135 [[nodiscard]] 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