1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/UnfoldShortCircuit.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,176 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 +// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements. 1.10 +// The results are assigned to s# temporaries, which are used by the main translator instead of 1.11 +// the original expression. 1.12 +// 1.13 + 1.14 +#include "compiler/UnfoldShortCircuit.h" 1.15 + 1.16 +#include "compiler/InfoSink.h" 1.17 +#include "compiler/OutputHLSL.h" 1.18 + 1.19 +namespace sh 1.20 +{ 1.21 +UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL) 1.22 +{ 1.23 + mTemporaryIndex = 0; 1.24 +} 1.25 + 1.26 +void UnfoldShortCircuit::traverse(TIntermNode *node) 1.27 +{ 1.28 + int rewindIndex = mTemporaryIndex; 1.29 + node->traverse(this); 1.30 + mTemporaryIndex = rewindIndex; 1.31 +} 1.32 + 1.33 +bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) 1.34 +{ 1.35 + TInfoSinkBase &out = mOutputHLSL->getBodyStream(); 1.36 + 1.37 + switch (node->getOp()) 1.38 + { 1.39 + case EOpLogicalOr: 1.40 + // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;", 1.41 + // and then further simplifies down to "bool s = x; if(!s) s = y;". 1.42 + { 1.43 + int i = mTemporaryIndex; 1.44 + 1.45 + out << "bool s" << i << ";\n"; 1.46 + 1.47 + out << "{\n"; 1.48 + 1.49 + mTemporaryIndex = i + 1; 1.50 + node->getLeft()->traverse(this); 1.51 + out << "s" << i << " = "; 1.52 + mTemporaryIndex = i + 1; 1.53 + node->getLeft()->traverse(mOutputHLSL); 1.54 + out << ";\n"; 1.55 + out << "if(!s" << i << ")\n" 1.56 + "{\n"; 1.57 + mTemporaryIndex = i + 1; 1.58 + node->getRight()->traverse(this); 1.59 + out << " s" << i << " = "; 1.60 + mTemporaryIndex = i + 1; 1.61 + node->getRight()->traverse(mOutputHLSL); 1.62 + out << ";\n" 1.63 + "}\n"; 1.64 + 1.65 + out << "}\n"; 1.66 + 1.67 + mTemporaryIndex = i + 1; 1.68 + } 1.69 + return false; 1.70 + case EOpLogicalAnd: 1.71 + // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;", 1.72 + // and then further simplifies down to "bool s = x; if(s) s = y;". 1.73 + { 1.74 + int i = mTemporaryIndex; 1.75 + 1.76 + out << "bool s" << i << ";\n"; 1.77 + 1.78 + out << "{\n"; 1.79 + 1.80 + mTemporaryIndex = i + 1; 1.81 + node->getLeft()->traverse(this); 1.82 + out << "s" << i << " = "; 1.83 + mTemporaryIndex = i + 1; 1.84 + node->getLeft()->traverse(mOutputHLSL); 1.85 + out << ";\n"; 1.86 + out << "if(s" << i << ")\n" 1.87 + "{\n"; 1.88 + mTemporaryIndex = i + 1; 1.89 + node->getRight()->traverse(this); 1.90 + out << " s" << i << " = "; 1.91 + mTemporaryIndex = i + 1; 1.92 + node->getRight()->traverse(mOutputHLSL); 1.93 + out << ";\n" 1.94 + "}\n"; 1.95 + 1.96 + out << "}\n"; 1.97 + 1.98 + mTemporaryIndex = i + 1; 1.99 + } 1.100 + return false; 1.101 + default: 1.102 + return true; 1.103 + } 1.104 +} 1.105 + 1.106 +bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) 1.107 +{ 1.108 + TInfoSinkBase &out = mOutputHLSL->getBodyStream(); 1.109 + 1.110 + // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" 1.111 + if (node->usesTernaryOperator()) 1.112 + { 1.113 + int i = mTemporaryIndex; 1.114 + 1.115 + out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n"; 1.116 + 1.117 + out << "{\n"; 1.118 + 1.119 + mTemporaryIndex = i + 1; 1.120 + node->getCondition()->traverse(this); 1.121 + out << "if("; 1.122 + mTemporaryIndex = i + 1; 1.123 + node->getCondition()->traverse(mOutputHLSL); 1.124 + out << ")\n" 1.125 + "{\n"; 1.126 + mTemporaryIndex = i + 1; 1.127 + node->getTrueBlock()->traverse(this); 1.128 + out << " s" << i << " = "; 1.129 + mTemporaryIndex = i + 1; 1.130 + node->getTrueBlock()->traverse(mOutputHLSL); 1.131 + out << ";\n" 1.132 + "}\n" 1.133 + "else\n" 1.134 + "{\n"; 1.135 + mTemporaryIndex = i + 1; 1.136 + node->getFalseBlock()->traverse(this); 1.137 + out << " s" << i << " = "; 1.138 + mTemporaryIndex = i + 1; 1.139 + node->getFalseBlock()->traverse(mOutputHLSL); 1.140 + out << ";\n" 1.141 + "}\n"; 1.142 + 1.143 + out << "}\n"; 1.144 + 1.145 + mTemporaryIndex = i + 1; 1.146 + } 1.147 + 1.148 + return false; 1.149 +} 1.150 + 1.151 +bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node) 1.152 +{ 1.153 + int rewindIndex = mTemporaryIndex; 1.154 + 1.155 + if (node->getInit()) 1.156 + { 1.157 + node->getInit()->traverse(this); 1.158 + } 1.159 + 1.160 + if (node->getCondition()) 1.161 + { 1.162 + node->getCondition()->traverse(this); 1.163 + } 1.164 + 1.165 + if (node->getExpression()) 1.166 + { 1.167 + node->getExpression()->traverse(this); 1.168 + } 1.169 + 1.170 + mTemporaryIndex = rewindIndex; 1.171 + 1.172 + return false; 1.173 +} 1.174 + 1.175 +int UnfoldShortCircuit::getNextTemporaryIndex() 1.176 +{ 1.177 + return mTemporaryIndex++; 1.178 +} 1.179 +}