| // |
| // Copyright 2020 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. |
| // |
| |
| #include "compiler/translator/TranslatorMetalDirect/RewriteCaseDeclarations.h" |
| #include "compiler/translator/TranslatorMetalDirect/AstHelpers.h" |
| #include "compiler/translator/tree_util/IntermRebuild.h" |
| |
| using namespace sh; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| namespace |
| { |
| |
| class Rewriter : public TIntermRebuild |
| { |
| std::vector<std::vector<const TVariable *>> mDeclaredVarStack; |
| |
| public: |
| Rewriter(TCompiler &compiler) : TIntermRebuild(compiler, true, true) {} |
| |
| ~Rewriter() override { ASSERT(mDeclaredVarStack.empty()); } |
| |
| private: |
| PreResult visitSwitchPre(TIntermSwitch &node) override |
| { |
| mDeclaredVarStack.emplace_back(); |
| return node; |
| } |
| |
| PostResult visitSwitchPost(TIntermSwitch &node) override |
| { |
| ASSERT(!mDeclaredVarStack.empty()); |
| const auto vars = std::move(mDeclaredVarStack.back()); |
| mDeclaredVarStack.pop_back(); |
| if (!vars.empty()) |
| { |
| auto &block = *new TIntermBlock(); |
| for (const TVariable *var : vars) |
| { |
| block.appendStatement(new TIntermDeclaration{var}); |
| } |
| block.appendStatement(&node); |
| return block; |
| } |
| return node; |
| } |
| |
| PreResult visitDeclarationPre(TIntermDeclaration &node) override |
| { |
| if (!mDeclaredVarStack.empty()) |
| { |
| TIntermNode *parent = getParentNode(); |
| if (parent->getAsBlock()) |
| { |
| TIntermNode *grandparent = getParentNode(1); |
| if (grandparent && grandparent->getAsSwitchNode()) |
| { |
| Declaration decl = ViewDeclaration(node); |
| mDeclaredVarStack.back().push_back(&decl.symbol.variable()); |
| if (decl.initExpr) |
| { |
| return *new TIntermBinary(TOperator::EOpAssign, &decl.symbol, |
| decl.initExpr); |
| } |
| else |
| { |
| return nullptr; |
| } |
| } |
| } |
| } |
| return node; |
| } |
| }; |
| |
| } // anonymous namespace |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| bool sh::RewriteCaseDeclarations(TCompiler &compiler, TIntermBlock &root) |
| { |
| if (!Rewriter(compiler).rebuildRoot(root)) |
| { |
| return false; |
| } |
| return true; |
| } |