2 // Copyright (c) 2014 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.
6 // RewriteElseBlocks.cpp: Implementation for tree transform to change
7 // all if-else blocks to if-if blocks.
10 #include "compiler/translator/RewriteElseBlocks.h"
11 #include "compiler/translator/NodeSearch.h"
12 #include "compiler/translator/SymbolTable.h"
17 TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type)
19 TType variableType(type, EbpHigh, EvqInternal);
20 return new TIntermSymbol(-1, name, variableType);
23 TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType)
25 TIntermBinary *binary = new TIntermBinary(op);
26 binary->setLeft(left);
27 binary->setRight(right);
28 binary->setType(resultType);
32 TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
34 TIntermUnary *unary = new TIntermUnary(op, operand->getType());
35 unary->setOperand(operand);
39 ElseBlockRewriter::ElseBlockRewriter()
40 : TIntermTraverser(true, false, true, false),
45 bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
47 switch (node->getOp())
50 if (visit == PostVisit)
52 for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
54 TIntermNode *statement = node->getSequence()[statementIndex];
55 TIntermSelection *selection = statement->getAsSelectionNode();
56 if (selection && selection->getFalseBlock() != NULL)
58 // Check for if / else if
59 TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
62 selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
66 node->getSequence()[statementIndex] = rewriteSelection(selection);
74 // Store the current function context (see comment below)
75 mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
84 TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
86 ASSERT(selection->getFalseBlock() != NULL);
88 TString temporaryName = "cond_" + str(mTemporaryIndex++);
89 TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
90 TType resultType(EbtBool, EbpUndefined);
91 TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool);
92 TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool);
93 TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool);
94 TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
95 typedCondition, resultType);
96 TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
97 TIntermNode *negatedElse = NULL;
100 // D3D generates error messages claiming a function has no return value, when rewriting
101 // an if-else clause that returns something non-void in a function. By appending dummy
102 // returns (that are unreachable) we can silence this compile error.
103 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
105 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
106 mFunctionType->getBasicString();
107 TString rawText = "return (" + typeString + ")0";
108 negatedElse = new TIntermRaw(*mFunctionType, rawText);
111 TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
112 selection->getFalseBlock(), negatedElse);
113 TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
114 selection->getTrueBlock(), falseBlock);
116 TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
117 declaration->getSequence().push_back(storeCondition);
119 TIntermAggregate *block = new TIntermAggregate(EOpSequence);
120 block->getSequence().push_back(declaration);
121 block->getSequence().push_back(newIfElse);
126 void RewriteElseBlocks(TIntermNode *node)
128 ElseBlockRewriter rewriter;
129 node->traverse(&rewriter);