// // 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> 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; }