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