Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / RewriteElseBlocks.cpp
1 //
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
14 namespace sh
15 {
16
17 TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type)
18 {
19     TType variableType(type, EbpHigh, EvqInternal);
20     return new TIntermSymbol(-1, name, variableType);
21 }
22
23 TIntermBinary *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
32 TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
33 {
34     TIntermUnary *unary = new TIntermUnary(op, operand->getType());
35     unary->setOperand(operand);
36     return unary;
37 }
38
39 bool 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                 {
51                     node->getSequence()[statementIndex] = rewriteSelection(selection);
52                     delete selection;
53                 }
54             }
55         }
56         break;
57
58       default: break;
59     }
60
61     return true;
62 }
63
64 TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
65 {
66     ASSERT(selection->getFalseBlock() != NULL);
67
68     TString temporaryName = "cond_" + str(mTemporaryIndex++);
69     TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
70     TType resultType(EbtBool, EbpUndefined);
71     TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool);
72     TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool);
73     TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool);
74     TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
75                                                   typedCondition, resultType);
76     TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
77     TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
78                                                         selection->getFalseBlock(), NULL);
79     TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
80                                                        selection->getTrueBlock(), falseBlock);
81
82     TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
83     declaration->getSequence().push_back(storeCondition);
84
85     TIntermAggregate *block = new TIntermAggregate(EOpSequence);
86     block->getSequence().push_back(declaration);
87     block->getSequence().push_back(newIfElse);
88
89     return block;
90 }
91
92 void RewriteElseBlocks(TIntermNode *node)
93 {
94     ElseBlockRewriter rewriter;
95     node->traverse(&rewriter);
96 }
97
98 }