gfx/angle/src/compiler/UnfoldShortCircuit.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 //
     2 // Copyright (c) 2002-2013 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 // UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
     7 // The results are assigned to s# temporaries, which are used by the main translator instead of
     8 // the original expression.
     9 //
    11 #include "compiler/UnfoldShortCircuit.h"
    13 #include "compiler/InfoSink.h"
    14 #include "compiler/OutputHLSL.h"
    16 namespace sh
    17 {
    18 UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
    19 {
    20     mTemporaryIndex = 0;
    21 }
    23 void UnfoldShortCircuit::traverse(TIntermNode *node)
    24 {
    25     int rewindIndex = mTemporaryIndex;
    26     node->traverse(this);
    27     mTemporaryIndex = rewindIndex;
    28 }
    30 bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
    31 {
    32     TInfoSinkBase &out = mOutputHLSL->getBodyStream();
    34     switch (node->getOp())
    35     {
    36       case EOpLogicalOr:
    37         // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
    38         // and then further simplifies down to "bool s = x; if(!s) s = y;".
    39         {
    40             int i = mTemporaryIndex;
    42             out << "bool s" << i << ";\n";
    44             out << "{\n";
    46             mTemporaryIndex = i + 1;
    47             node->getLeft()->traverse(this);
    48             out << "s" << i << " = ";
    49             mTemporaryIndex = i + 1;
    50             node->getLeft()->traverse(mOutputHLSL);
    51             out << ";\n";
    52             out << "if(!s" << i << ")\n"
    53                    "{\n";
    54             mTemporaryIndex = i + 1;
    55             node->getRight()->traverse(this);
    56             out << "    s" << i << " = ";
    57             mTemporaryIndex = i + 1;
    58             node->getRight()->traverse(mOutputHLSL);
    59             out << ";\n"
    60                    "}\n";
    62             out << "}\n";
    64             mTemporaryIndex = i + 1;
    65         }
    66         return false;
    67       case EOpLogicalAnd:
    68         // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
    69         // and then further simplifies down to "bool s = x; if(s) s = y;".
    70         {
    71             int i = mTemporaryIndex;
    73             out << "bool s" << i << ";\n";
    75             out << "{\n";
    77             mTemporaryIndex = i + 1;
    78             node->getLeft()->traverse(this);
    79             out << "s" << i << " = ";
    80             mTemporaryIndex = i + 1;
    81             node->getLeft()->traverse(mOutputHLSL);
    82             out << ";\n";
    83             out << "if(s" << i << ")\n"
    84                    "{\n";
    85             mTemporaryIndex = i + 1;
    86             node->getRight()->traverse(this);
    87             out << "    s" << i << " = ";
    88             mTemporaryIndex = i + 1;
    89             node->getRight()->traverse(mOutputHLSL);
    90             out << ";\n"
    91                    "}\n";
    93             out << "}\n";
    95             mTemporaryIndex = i + 1;
    96         }
    97         return false;
    98       default:
    99         return true;
   100     }
   101 }
   103 bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
   104 {
   105     TInfoSinkBase &out = mOutputHLSL->getBodyStream();
   107     // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
   108     if (node->usesTernaryOperator())
   109     {
   110         int i = mTemporaryIndex;
   112         out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
   114         out << "{\n";
   116         mTemporaryIndex = i + 1;
   117         node->getCondition()->traverse(this);
   118         out << "if(";
   119         mTemporaryIndex = i + 1;
   120         node->getCondition()->traverse(mOutputHLSL);
   121         out << ")\n"
   122                "{\n";
   123         mTemporaryIndex = i + 1;
   124         node->getTrueBlock()->traverse(this);
   125         out << "    s" << i << " = ";
   126         mTemporaryIndex = i + 1;
   127         node->getTrueBlock()->traverse(mOutputHLSL);
   128         out << ";\n"
   129                "}\n"
   130                "else\n"
   131                "{\n";
   132         mTemporaryIndex = i + 1;
   133         node->getFalseBlock()->traverse(this);
   134         out << "    s" << i << " = ";
   135         mTemporaryIndex = i + 1;
   136         node->getFalseBlock()->traverse(mOutputHLSL);
   137         out << ";\n"
   138                "}\n";
   140         out << "}\n";
   142         mTemporaryIndex = i + 1;
   143     }
   145     return false;
   146 }
   148 bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
   149 {
   150     int rewindIndex = mTemporaryIndex;
   152     if (node->getInit())
   153     {
   154         node->getInit()->traverse(this);
   155     }
   157     if (node->getCondition())
   158     {
   159         node->getCondition()->traverse(this);
   160     }
   162     if (node->getExpression())
   163     {
   164         node->getExpression()->traverse(this);
   165     }
   167     mTemporaryIndex = rewindIndex;
   169     return false;
   170 }
   172 int UnfoldShortCircuit::getNextTemporaryIndex()
   173 {
   174     return mTemporaryIndex++;
   175 }
   176 }

mercurial