Hash :
96f44329
Author :
Date :
2024-03-25T14:16:10
Revert "Remove few redundant ImmutableString to std::string conversions" This reverts commit ebb94b807f184f2d36cb0843c429667cd80e0675. Reason for revert: Needs a different implementation of std::string::size() to pass C++17 compilers. Original change's description: > Remove few redundant ImmutableString to std::string conversions > > Maybe removes few strlen calls. > > Bug: angleproject:8614 > Change-Id: I4fbb5f6abb8e8d21ff44a34975bab379127a0a11 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5372715 > Auto-Submit: Kimmo Kinnunen <kkinnunen@apple.com> > Commit-Queue: Geoff Lang <geofflang@chromium.org> > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > Reviewed-by: Geoff Lang <geofflang@chromium.org> Bug: angleproject:8614 Change-Id: I1a635b74674a2e1b635972bb4372c43340527a2f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5391900 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Auto-Submit: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Yuly Novikov <ynovikov@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@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
//
// Copyright 2019 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.
//
// ReplaceShadowingVariables.cpp: Replace all references to any variable in the AST that is
// a redefinition of a variable in a nested scope. This is a useful for ESSL 1.00 shaders
// where the spec section "4.2.3. Redeclaring Variables" states "However, a nested scope can
// override an outer scope's declaration of a particular variable name." This is changed in
// later spec versions, such as ESSL 3.20 spec which states "If [a variable] is declared as
// a parameter in a function definition, it is scoped until the end of that function
// definition. A function's parameter declarations and body together form a single scope."
//
// So this class is useful when translating from ESSL 1.00 shaders, where function body var
// redefinition is allowed, to later shader versions where it's not allowed.
//
#include "compiler/translator/tree_util/ReplaceShadowingVariables.h"
#include "compiler/translator/tree_util/ReplaceVariable.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include <unordered_set>
namespace sh
{
namespace
{
// Custom struct to queue up any replacements until after AST traversal
struct DeferredReplacementBlock
{
const TVariable *originalVariable; // variable to be replaced
TVariable *replacementVariable; // variable to replace originalVar with
TIntermBlock *functionBody; // function body where replacement occurs
};
class ReplaceShadowingVariablesTraverser : public TIntermTraverser
{
public:
ReplaceShadowingVariablesTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, true, true, symbolTable), mParameterNames{}, mFunctionBody(nullptr)
{}
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
{
// In pre-visit of function, record params
if (visit == PreVisit)
{
ASSERT(mParameterNames.size() == 0);
const TFunction *func = node->getFunctionPrototype()->getFunction();
// Grab all of the parameter names from the function prototype
size_t paramCount = func->getParamCount();
for (size_t i = 0; i < paramCount; ++i)
{
mParameterNames.emplace(std::string(func->getParam(i)->name().data()));
}
if (mParameterNames.size() > 0)
mFunctionBody = node->getBody();
}
else if (visit == PostVisit)
{
// Clear data saved from function definition
mParameterNames.clear();
mFunctionBody = nullptr;
}
return true;
}
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
{
if (visit == PreVisit && mParameterNames.size() != 0)
{
TIntermSequence *decls = node->getSequence();
for (auto &declVector : *decls)
{
// no init case
TIntermSymbol *symNode = declVector->getAsSymbolNode();
if (symNode == nullptr)
{
// init case
TIntermBinary *binaryNode = declVector->getAsBinaryNode();
ASSERT(binaryNode->getOp() == EOpInitialize);
symNode = binaryNode->getLeft()->getAsSymbolNode();
}
ASSERT(symNode != nullptr);
std::string varName = std::string(symNode->variable().name().data());
if (mParameterNames.count(varName) > 0)
{
// We found a redefined var so queue replacement
mReplacements.emplace_back(DeferredReplacementBlock{
&symNode->variable(),
CreateTempVariable(mSymbolTable, &symNode->variable().getType()),
mFunctionBody});
}
}
}
return true;
}
// Perform replacement of vars for any deferred replacements that were identified
[[nodiscard]] bool executeReplacements(TCompiler *compiler)
{
for (DeferredReplacementBlock &replace : mReplacements)
{
if (!ReplaceVariable(compiler, replace.functionBody, replace.originalVariable,
replace.replacementVariable))
{
return false;
}
}
mReplacements.clear();
return true;
}
private:
std::unordered_set<std::string> mParameterNames;
TIntermBlock *mFunctionBody;
std::vector<DeferredReplacementBlock> mReplacements;
};
} // anonymous namespace
// Replaces every occurrence of a variable with another variable.
[[nodiscard]] bool ReplaceShadowingVariables(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable)
{
ReplaceShadowingVariablesTraverser traverser(symbolTable);
root->traverse(&traverser);
if (!traverser.executeReplacements(compiler))
{
return false;
}
return traverser.updateTree(compiler, root);
}
} // namespace sh