blob: 8a9e29e6fa5e910a9a4af5b3f3d4ed4f8546d4f3 [file] [log] [blame]
Jamie Madille53c98b2014-02-03 11:57:13 -05001//
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.
5//
6// RewriteElseBlocks.cpp: Implementation for tree transform to change
7// all if-else blocks to if-if blocks.
8//
9
10#include "compiler/translator/RewriteElseBlocks.h"
11#include "compiler/translator/NodeSearch.h"
12#include "compiler/translator/SymbolTable.h"
13
14namespace sh
15{
16
17TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type)
18{
19 TType variableType(type, EbpHigh, EvqInternal);
20 return new TIntermSymbol(-1, name, variableType);
21}
22
23TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType)
24{
25 TIntermBinary *binary = new TIntermBinary(op);
26 binary->setLeft(left);
27 binary->setRight(right);
28 binary->setType(resultType);
29 return binary;
30}
31
32TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
33{
34 TIntermUnary *unary = new TIntermUnary(op, operand->getType());
35 unary->setOperand(operand);
36 return unary;
37}
38
39bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
40{
41 switch (node->getOp())
42 {
43 case EOpSequence:
44 {
45 for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
46 {
47 TIntermNode *statement = node->getSequence()[statementIndex];
48 TIntermSelection *selection = statement->getAsSelectionNode();
49 if (selection && selection->getFalseBlock() != NULL)
50 {
Jamie Madilled3eef12014-02-26 09:47:11 -050051 // Check for if / else if
52 TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
53 if (elseIfBranch)
54 {
55 selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
56 delete elseIfBranch;
57 }
58
Jamie Madille53c98b2014-02-03 11:57:13 -050059 node->getSequence()[statementIndex] = rewriteSelection(selection);
60 delete selection;
61 }
62 }
63 }
64 break;
65
66 default: break;
67 }
68
69 return true;
70}
71
72TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
73{
74 ASSERT(selection->getFalseBlock() != NULL);
75
76 TString temporaryName = "cond_" + str(mTemporaryIndex++);
77 TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
78 TType resultType(EbtBool, EbpUndefined);
79 TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool);
80 TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool);
81 TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool);
82 TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
83 typedCondition, resultType);
84 TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
85 TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
86 selection->getFalseBlock(), NULL);
87 TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
88 selection->getTrueBlock(), falseBlock);
89
90 TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
91 declaration->getSequence().push_back(storeCondition);
92
93 TIntermAggregate *block = new TIntermAggregate(EOpSequence);
94 block->getSequence().push_back(declaration);
95 block->getSequence().push_back(newIfElse);
96
97 return block;
98}
99
100void RewriteElseBlocks(TIntermNode *node)
101{
102 ElseBlockRewriter rewriter;
103 node->traverse(&rewriter);
104}
105
106}