diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp new file mode 100644 index 0000000000..697cfe6c74 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp @@ -0,0 +1,145 @@ +// +// Copyright 2018 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. +// +// ReplaceVariable.cpp: Replace all references to a specific variable in the AST with references to +// another variable. + +#include "compiler/translator/tree_util/ReplaceVariable.h" + +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +namespace +{ + +class ReplaceVariableTraverser : public TIntermTraverser +{ + public: + ReplaceVariableTraverser(const TVariable *toBeReplaced, const TIntermTyped *replacement) + : TIntermTraverser(true, false, false), + mToBeReplaced(toBeReplaced), + mReplacement(replacement) + {} + + void visitSymbol(TIntermSymbol *node) override + { + if (&node->variable() == mToBeReplaced) + { + queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED); + } + } + + private: + const TVariable *const mToBeReplaced; + const TIntermTyped *const mReplacement; +}; + +class ReplaceVariablesTraverser : public TIntermTraverser +{ + public: + ReplaceVariablesTraverser(const VariableReplacementMap &variableMap) + : TIntermTraverser(true, false, false), mVariableMap(variableMap) + {} + + void visitSymbol(TIntermSymbol *node) override + { + auto iter = mVariableMap.find(&node->variable()); + if (iter != mVariableMap.end()) + { + queueReplacement(iter->second->deepCopy(), OriginalNode::IS_DROPPED); + } + } + + private: + const VariableReplacementMap &mVariableMap; +}; + +class GetDeclaratorReplacementsTraverser : public TIntermTraverser +{ + public: + GetDeclaratorReplacementsTraverser(TSymbolTable *symbolTable, + VariableReplacementMap *variableMap) + : TIntermTraverser(true, false, false, symbolTable), mVariableMap(variableMap) + {} + + bool visitDeclaration(Visit visit, TIntermDeclaration *node) override + { + const TIntermSequence &sequence = *(node->getSequence()); + + for (TIntermNode *decl : sequence) + { + TIntermSymbol *asSymbol = decl->getAsSymbolNode(); + TIntermBinary *asBinary = decl->getAsBinaryNode(); + + if (asBinary != nullptr) + { + ASSERT(asBinary->getOp() == EOpInitialize); + asSymbol = asBinary->getLeft()->getAsSymbolNode(); + } + + ASSERT(asSymbol); + const TVariable &variable = asSymbol->variable(); + + ASSERT(mVariableMap->find(&variable) == mVariableMap->end()); + + const TVariable *replacementVariable = new TVariable( + mSymbolTable, variable.name(), &variable.getType(), variable.symbolType()); + + (*mVariableMap)[&variable] = new TIntermSymbol(replacementVariable); + } + + return false; + } + + private: + VariableReplacementMap *mVariableMap; +}; + +} // anonymous namespace + +// Replaces every occurrence of a variable with another variable. +[[nodiscard]] bool ReplaceVariable(TCompiler *compiler, + TIntermBlock *root, + const TVariable *toBeReplaced, + const TVariable *replacement) +{ + ReplaceVariableTraverser traverser(toBeReplaced, new TIntermSymbol(replacement)); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +[[nodiscard]] bool ReplaceVariables(TCompiler *compiler, + TIntermBlock *root, + const VariableReplacementMap &variableMap) +{ + ReplaceVariablesTraverser traverser(variableMap); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +void GetDeclaratorReplacements(TSymbolTable *symbolTable, + TIntermBlock *root, + VariableReplacementMap *variableMap) +{ + GetDeclaratorReplacementsTraverser traverser(symbolTable, variableMap); + root->traverse(&traverser); +} + +// Replaces every occurrence of a variable with a TIntermNode. +[[nodiscard]] bool ReplaceVariableWithTyped(TCompiler *compiler, + TIntermBlock *root, + const TVariable *toBeReplaced, + const TIntermTyped *replacement) +{ + ReplaceVariableTraverser traverser(toBeReplaced, replacement); + root->traverse(&traverser); + return traverser.updateTree(compiler, root); +} + +} // namespace sh |