46e510c31b98a504bebb4129cc33f0dbc3f5fe93
[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 ElseBlockRewriter::ElseBlockRewriter()
40     : TIntermTraverser(true, false, true, false),
41       mTemporaryIndex(0),
42       mFunctionType(NULL)
43 {}
44
45 bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
46 {
47     switch (node->getOp())
48     {
49       case EOpSequence:
50         if (visit == PostVisit)
51         {
52             for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
53             {
54                 TIntermNode *statement = node->getSequence()[statementIndex];
55                 TIntermSelection *selection = statement->getAsSelectionNode();
56                 if (selection && selection->getFalseBlock() != NULL)
57                 {
58                     // Check for if / else if
59                     TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
60                     if (elseIfBranch)
61                     {
62                         selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
63                         delete elseIfBranch;
64                     }
65
66                     node->getSequence()[statementIndex] = rewriteSelection(selection);
67                     delete selection;
68                 }
69             }
70         }
71         break;
72
73       case EOpFunction:
74         // Store the current function context (see comment below)
75         mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
76         break;
77
78       default: break;
79     }
80
81     return true;
82 }
83
84 TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
85 {
86     ASSERT(selection->getFalseBlock() != NULL);
87
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;
98
99     // crbug.com/346463
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)
104     {
105         TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
106             mFunctionType->getBasicString();
107         TString rawText = "return (" + typeString + ")0";
108         negatedElse = new TIntermRaw(*mFunctionType, rawText);
109     }
110
111     TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
112                                                         selection->getFalseBlock(), negatedElse);
113     TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
114                                                        selection->getTrueBlock(), falseBlock);
115
116     TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
117     declaration->getSequence().push_back(storeCondition);
118
119     TIntermAggregate *block = new TIntermAggregate(EOpSequence);
120     block->getSequence().push_back(declaration);
121     block->getSequence().push_back(newIfElse);
122
123     return block;
124 }
125
126 void RewriteElseBlocks(TIntermNode *node)
127 {
128     ElseBlockRewriter rewriter;
129     node->traverse(&rewriter);
130 }
131
132 }