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.h: Replace all references to a specific variable in the AST with references to 7 // another variable. 8 9 #ifndef COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ 10 #define COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ 11 12 #include "common/debug.h" 13 14 #include <stack> 15 #include <unordered_map> 16 17 namespace sh 18 { 19 20 class TCompiler; 21 class TFunction; 22 class TIntermAggregate; 23 class TIntermBlock; 24 class TIntermFunctionPrototype; 25 class TIntermNode; 26 class TIntermTyped; 27 class TSymbolTable; 28 class TVariable; 29 30 ANGLE_NO_DISCARD bool ReplaceVariable(TCompiler *compiler, 31 TIntermBlock *root, 32 const TVariable *toBeReplaced, 33 const TVariable *replacement); 34 ANGLE_NO_DISCARD bool ReplaceVariableWithTyped(TCompiler *compiler, 35 TIntermBlock *root, 36 const TVariable *toBeReplaced, 37 const TIntermTyped *replacement); 38 39 // A helper class to keep track of opaque variable re-typing during a pass. Unlike the above 40 // functions, this can be used to replace all opaque variables of a certain type with another in a 41 // pass that possibly does other related transformations. Only opaque variables are supported as 42 // replacing local variables is not supported. 43 // 44 // The class uses "old" to refer to the original type of the variable and "new" to refer to the type 45 // that will replace it. 46 // 47 // - replaceGlobalVariable(): Call to track a global variable that is replaced. 48 // - in TIntermTraverser::visitFunctionPrototype(): 49 // * Call visitFunctionPrototype(). 50 // * For every replaced parameter, call replaceFunctionParam(). 51 // * call convertFunctionPrototype() to convert the prototype based on the above replacements 52 // and track the function with its replacement. 53 // * Call replaceFunction() to track the function that is replaced. 54 // - In PreVisit of TIntermTraverser::visitAggregate(): 55 // * call preVisitAggregate() 56 // - In TIntermTraverser::visitSymbol(): 57 // * Replace non-function-call-argument symbols that refer to a global or function param with the 58 // replacement (getVariableReplacement()). 59 // * For function call arguments, call replaceFunctionCallArg() to track the replacement. 60 // - In PostVisit of TIntermTraverser::visitAggregate(): 61 // * Convert built-in functions per case. Call convertASTFunction() for non built-in functions 62 // for the replacement to be created. 63 // * Call postVisitAggregate() when done. 64 // 65 class RetypeOpaqueVariablesHelper 66 { 67 public: RetypeOpaqueVariablesHelper()68 RetypeOpaqueVariablesHelper() {} ~RetypeOpaqueVariablesHelper()69 ~RetypeOpaqueVariablesHelper() {} 70 71 // Global variable handling: replaceGlobalVariable(const TVariable * oldVar,TVariable * newVar)72 void replaceGlobalVariable(const TVariable *oldVar, TVariable *newVar) 73 { 74 ASSERT(mReplacedGlobalVariables.count(oldVar) == 0); 75 mReplacedGlobalVariables[oldVar] = newVar; 76 } getVariableReplacement(const TVariable * oldVar)77 TVariable *getVariableReplacement(const TVariable *oldVar) const 78 { 79 if (mReplacedGlobalVariables.count(oldVar) != 0) 80 { 81 return mReplacedGlobalVariables.at(oldVar); 82 } 83 else 84 { 85 // This function should only be called if the variable is expected to have been 86 // replaced either way (as a global variable or a function parameter). 87 ASSERT(mReplacedFunctionParams.count(oldVar) != 0); 88 return mReplacedFunctionParams.at(oldVar); 89 } 90 } 91 92 // Function parameters handling: visitFunctionPrototype()93 void visitFunctionPrototype() { mReplacedFunctionParams.clear(); } replaceFunctionParam(const TVariable * oldParam,TVariable * newParam)94 void replaceFunctionParam(const TVariable *oldParam, TVariable *newParam) 95 { 96 ASSERT(mReplacedFunctionParams.count(oldParam) == 0); 97 mReplacedFunctionParams[oldParam] = newParam; 98 } getFunctionParamReplacement(const TVariable * oldParam)99 TVariable *getFunctionParamReplacement(const TVariable *oldParam) const 100 { 101 ASSERT(mReplacedFunctionParams.count(oldParam) != 0); 102 return mReplacedFunctionParams.at(oldParam); 103 } 104 105 // Function call arguments handling: preVisitAggregate()106 void preVisitAggregate() { mReplacedFunctionCallArgs.emplace(); } isInAggregate()107 bool isInAggregate() const { return !mReplacedFunctionCallArgs.empty(); } postVisitAggregate()108 void postVisitAggregate() { mReplacedFunctionCallArgs.pop(); } replaceFunctionCallArg(const TIntermNode * oldArg,TIntermTyped * newArg)109 void replaceFunctionCallArg(const TIntermNode *oldArg, TIntermTyped *newArg) 110 { 111 ASSERT(mReplacedFunctionCallArgs.top().count(oldArg) == 0); 112 mReplacedFunctionCallArgs.top()[oldArg] = newArg; 113 } getFunctionCallArgReplacement(const TIntermNode * oldArg)114 TIntermTyped *getFunctionCallArgReplacement(const TIntermNode *oldArg) const 115 { 116 ASSERT(mReplacedFunctionCallArgs.top().count(oldArg) != 0); 117 return mReplacedFunctionCallArgs.top().at(oldArg); 118 } 119 120 // Helper code conversion methods. 121 TIntermFunctionPrototype *convertFunctionPrototype(TSymbolTable *symbolTable, 122 const TFunction *oldFunction); 123 TIntermAggregate *convertASTFunction(TIntermAggregate *node); 124 125 private: 126 // A map from the old global variable to the new one. 127 std::unordered_map<const TVariable *, TVariable *> mReplacedGlobalVariables; 128 129 // A map from functions with old type parameters to one where that's replaced with the new type. 130 std::unordered_map<const TFunction *, TFunction *> mReplacedFunctions; 131 132 // A map from function old type parameters to their replacement new type parameter for the 133 // current function definition. 134 std::unordered_map<const TVariable *, TVariable *> mReplacedFunctionParams; 135 136 // A map from function call old type arguments to their replacement for the current function 137 // call. 138 std::stack<std::unordered_map<const TIntermNode *, TIntermTyped *>> mReplacedFunctionCallArgs; 139 }; 140 141 } // namespace sh 142 143 #endif // COMPILER_TRANSLATOR_TREEUTIL_REPLACEVARIABLE_H_ 144