1 // 2 // Copyright 2020 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 7 #include "compiler/translator/TranslatorMetalDirect/RewriteCaseDeclarations.h" 8 #include "compiler/translator/TranslatorMetalDirect/AstHelpers.h" 9 #include "compiler/translator/TranslatorMetalDirect/IntermRebuild.h" 10 11 using namespace sh; 12 13 //////////////////////////////////////////////////////////////////////////////// 14 15 namespace 16 { 17 18 class Rewriter : public TIntermRebuild 19 { 20 std::vector<std::vector<const TVariable *>> mDeclaredVarStack; 21 22 public: Rewriter(TCompiler & compiler)23 Rewriter(TCompiler &compiler) : TIntermRebuild(compiler, true, true) {} 24 ~Rewriter()25 ~Rewriter() override { ASSERT(mDeclaredVarStack.empty()); } 26 27 private: visitSwitchPre(TIntermSwitch & node)28 PreResult visitSwitchPre(TIntermSwitch &node) override 29 { 30 mDeclaredVarStack.emplace_back(); 31 return node; 32 } 33 visitSwitchPost(TIntermSwitch & node)34 PostResult visitSwitchPost(TIntermSwitch &node) override 35 { 36 ASSERT(!mDeclaredVarStack.empty()); 37 const auto vars = std::move(mDeclaredVarStack.back()); 38 mDeclaredVarStack.pop_back(); 39 if (!vars.empty()) 40 { 41 auto &block = *new TIntermBlock(); 42 for (const TVariable *var : vars) 43 { 44 block.appendStatement(new TIntermDeclaration{var}); 45 } 46 block.appendStatement(&node); 47 return block; 48 } 49 return node; 50 } 51 visitDeclarationPre(TIntermDeclaration & node)52 PreResult visitDeclarationPre(TIntermDeclaration &node) override 53 { 54 if (!mDeclaredVarStack.empty()) 55 { 56 TIntermNode *parent = getParentNode(); 57 if (parent->getAsBlock()) 58 { 59 TIntermNode *grandparent = getParentNode(1); 60 if (grandparent && grandparent->getAsSwitchNode()) 61 { 62 Declaration decl = ViewDeclaration(node); 63 mDeclaredVarStack.back().push_back(&decl.symbol.variable()); 64 if (decl.initExpr) 65 { 66 return *new TIntermBinary(TOperator::EOpAssign, &decl.symbol, 67 decl.initExpr); 68 } 69 else 70 { 71 return nullptr; 72 } 73 } 74 } 75 } 76 return node; 77 } 78 }; 79 80 } // anonymous namespace 81 82 //////////////////////////////////////////////////////////////////////////////// 83 RewriteCaseDeclarations(TCompiler & compiler,TIntermBlock & root)84bool sh::RewriteCaseDeclarations(TCompiler &compiler, TIntermBlock &root) 85 { 86 if (!Rewriter(compiler).rebuildRoot(root)) 87 { 88 return false; 89 } 90 return true; 91 } 92