LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - RemoveSwitchFallThrough.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 87 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2015 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/RemoveSwitchFallThrough.h"
       8             : 
       9             : namespace sh
      10             : {
      11             : 
      12           0 : TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statementList)
      13             : {
      14           0 :     RemoveSwitchFallThrough rm(statementList);
      15           0 :     ASSERT(statementList);
      16           0 :     statementList->traverse(&rm);
      17           0 :     bool lastStatementWasBreak = rm.mLastStatementWasBreak;
      18           0 :     rm.mLastStatementWasBreak = true;
      19           0 :     rm.handlePreviousCase();
      20           0 :     if (!lastStatementWasBreak)
      21             :     {
      22           0 :         TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr);
      23           0 :         rm.mStatementListOut->getSequence()->push_back(finalBreak);
      24             :     }
      25           0 :     return rm.mStatementListOut;
      26             : }
      27             : 
      28           0 : RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList)
      29             :     : TIntermTraverser(true, false, false),
      30             :       mStatementList(statementList),
      31             :       mLastStatementWasBreak(false),
      32           0 :       mPreviousCase(nullptr)
      33             : {
      34           0 :     mStatementListOut = new TIntermBlock();
      35           0 : }
      36             : 
      37           0 : void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
      38             : {
      39             :     // Note that this assumes that switch statements which don't begin by a case statement
      40             :     // have already been weeded out in validation.
      41           0 :     mPreviousCase->getSequence()->push_back(node);
      42           0 :     mLastStatementWasBreak = false;
      43           0 : }
      44             : 
      45           0 : void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
      46             : {
      47             :     // Conditions of case labels are not traversed, so this is some other constant
      48             :     // Could be just a statement like "0;"
      49           0 :     mPreviousCase->getSequence()->push_back(node);
      50           0 :     mLastStatementWasBreak = false;
      51           0 : }
      52             : 
      53           0 : bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node)
      54             : {
      55           0 :     mPreviousCase->getSequence()->push_back(node);
      56           0 :     mLastStatementWasBreak = false;
      57           0 :     return false;
      58             : }
      59             : 
      60           0 : bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node)
      61             : {
      62           0 :     mPreviousCase->getSequence()->push_back(node);
      63           0 :     mLastStatementWasBreak = false;
      64           0 :     return false;
      65             : }
      66             : 
      67           0 : bool RemoveSwitchFallThrough::visitTernary(Visit, TIntermTernary *node)
      68             : {
      69           0 :     mPreviousCase->getSequence()->push_back(node);
      70           0 :     mLastStatementWasBreak = false;
      71           0 :     return false;
      72             : }
      73             : 
      74           0 : bool RemoveSwitchFallThrough::visitIfElse(Visit, TIntermIfElse *node)
      75             : {
      76           0 :     mPreviousCase->getSequence()->push_back(node);
      77           0 :     mLastStatementWasBreak = false;
      78           0 :     return false;
      79             : }
      80             : 
      81           0 : bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
      82             : {
      83           0 :     mPreviousCase->getSequence()->push_back(node);
      84           0 :     mLastStatementWasBreak = false;
      85             :     // Don't go into nested switch statements
      86           0 :     return false;
      87             : }
      88             : 
      89           0 : void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex)
      90             : {
      91           0 :     for (size_t i = startIndex; i < sequence->size(); ++i)
      92             :     {
      93           0 :         mStatementListOut->getSequence()->push_back(sequence->at(i));
      94             :     }
      95           0 : }
      96             : 
      97           0 : void RemoveSwitchFallThrough::handlePreviousCase()
      98             : {
      99           0 :     if (mPreviousCase)
     100           0 :         mCasesSharingBreak.push_back(mPreviousCase);
     101           0 :     if (mLastStatementWasBreak)
     102             :     {
     103           0 :         bool labelsWithNoStatements = true;
     104           0 :         for (size_t i = 0; i < mCasesSharingBreak.size(); ++i)
     105             :         {
     106           0 :             if (mCasesSharingBreak.at(i)->getSequence()->size() > 1)
     107             :             {
     108           0 :                 labelsWithNoStatements = false;
     109             :             }
     110           0 :             if (labelsWithNoStatements)
     111             :             {
     112             :                 // Fall-through is allowed in case the label has no statements.
     113           0 :                 outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0);
     114             :             }
     115             :             else
     116             :             {
     117             :                 // Include all the statements that this case can fall through under the same label.
     118           0 :                 for (size_t j = i; j < mCasesSharingBreak.size(); ++j)
     119             :                 {
     120           0 :                     size_t startIndex = j > i ? 1 : 0; // Add the label only from the first sequence.
     121           0 :                     outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex);
     122             : 
     123             :                 }
     124             :             }
     125             :         }
     126           0 :         mCasesSharingBreak.clear();
     127             :     }
     128           0 :     mLastStatementWasBreak = false;
     129           0 :     mPreviousCase = nullptr;
     130           0 : }
     131             : 
     132           0 : bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
     133             : {
     134           0 :     handlePreviousCase();
     135           0 :     mPreviousCase = new TIntermBlock();
     136           0 :     mPreviousCase->getSequence()->push_back(node);
     137             :     // Don't traverse the condition of the case statement
     138           0 :     return false;
     139             : }
     140             : 
     141           0 : bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node)
     142             : {
     143           0 :     mPreviousCase->getSequence()->push_back(node);
     144           0 :     mLastStatementWasBreak = false;
     145           0 :     return false;
     146             : }
     147             : 
     148           0 : bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node)
     149             : {
     150           0 :     if (node != mStatementList)
     151             :     {
     152           0 :         mPreviousCase->getSequence()->push_back(node);
     153           0 :         mLastStatementWasBreak = false;
     154           0 :         return false;
     155             :     }
     156           0 :     return true;
     157             : }
     158             : 
     159           0 : bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node)
     160             : {
     161           0 :     mPreviousCase->getSequence()->push_back(node);
     162           0 :     mLastStatementWasBreak = false;
     163           0 :     return false;
     164             : }
     165             : 
     166           0 : bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
     167             : {
     168           0 :     mPreviousCase->getSequence()->push_back(node);
     169             :     // TODO: Verify that accepting return or continue statements here doesn't cause problems.
     170           0 :     mLastStatementWasBreak = true;
     171           0 :     return false;
     172             : }
     173             : 
     174             : }  // namespace sh

Generated by: LCOV version 1.13