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"
20
class ElseBlockRewriter : public TIntermTraverser
26
bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override;
29
const TType *mFunctionType;
31
TIntermNode *rewriteSelection(TIntermSelection *selection);
34
TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
36
TIntermUnary *unary = new TIntermUnary(op, operand->getType());
37
unary->setOperand(operand);
41
ElseBlockRewriter::ElseBlockRewriter()
42
: TIntermTraverser(true, false, true),
46
bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
48
switch (node->getOp())
51
if (visit == PostVisit)
53
for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++)
55
TIntermNode *statement = (*node->getSequence())[statementIndex];
56
TIntermSelection *selection = statement->getAsSelectionNode();
57
if (selection && selection->getFalseBlock() != nullptr)
59
// Check for if / else if
60
TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
63
selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
67
(*node->getSequence())[statementIndex] = rewriteSelection(selection);
75
// Store the current function context (see comment below)
76
mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
85
TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
87
ASSERT(selection != nullptr);
91
TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
92
TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
94
TIntermSelection *falseBlock = nullptr;
96
TType boolType(EbtBool, EbpUndefined, EvqTemporary);
98
if (selection->getFalseBlock())
100
TIntermAggregate *negatedElse = nullptr;
102
// D3D generates error messages claiming a function has no return value, when rewriting
103
// an if-else clause that returns something non-void in a function. By appending dummy
104
// returns (that are unreachable) we can silence this compile error.
105
if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
107
TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
108
mFunctionType->getBasicString();
109
TString rawText = "return (" + typeString + ")0";
110
TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
111
negatedElse = new TIntermAggregate(EOpSequence);
112
negatedElse->getSequence()->push_back(returnNode);
115
TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
116
TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse);
117
falseBlock = new TIntermSelection(negatedCondition,
118
selection->getFalseBlock(), negatedElse);
121
TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
122
TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, selection->getTrueBlock(), falseBlock);
124
TIntermAggregate *block = new TIntermAggregate(EOpSequence);
125
block->getSequence()->push_back(storeCondition);
126
block->getSequence()->push_back(newSelection);
133
void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
135
ElseBlockRewriter rewriter;
136
rewriter.useTemporaryIndex(temporaryIndex);
137
node->traverse(&rewriter);