summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceVariable.cpp
diff options
context:
space:
mode:
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.cpp145
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