blob: 11916b60ad89b180aaacadf57684352f30ef56b5 [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
Jamie Madill4836d222014-07-24 06:55:51 -040017namespace
18{
19
20class ElseBlockRewriter : public TIntermTraverser
21{
22 public:
23 ElseBlockRewriter();
24
25 protected:
26 bool visitAggregate(Visit visit, TIntermAggregate *aggregate);
27
28 private:
Jamie Madill4836d222014-07-24 06:55:51 -040029 const TType *mFunctionType;
30
31 TIntermNode *rewriteSelection(TIntermSelection *selection);
32};
33
Jamie Madille53c98b2014-02-03 11:57:13 -050034TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
35{
36 TIntermUnary *unary = new TIntermUnary(op, operand->getType());
37 unary->setOperand(operand);
38 return unary;
39}
40
Jamie Madill787fc032014-07-07 12:49:45 -040041ElseBlockRewriter::ElseBlockRewriter()
Olli Etuaho64f0be92015-06-03 17:38:34 +030042 : TIntermTraverser(true, false, true),
Jamie Madill787fc032014-07-07 12:49:45 -040043 mFunctionType(NULL)
44{}
45
Jamie Madille53c98b2014-02-03 11:57:13 -050046bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
47{
48 switch (node->getOp())
49 {
50 case EOpSequence:
Jamie Madill787fc032014-07-07 12:49:45 -040051 if (visit == PostVisit)
Jamie Madille53c98b2014-02-03 11:57:13 -050052 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070053 for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++)
Jamie Madille53c98b2014-02-03 11:57:13 -050054 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070055 TIntermNode *statement = (*node->getSequence())[statementIndex];
Jamie Madille53c98b2014-02-03 11:57:13 -050056 TIntermSelection *selection = statement->getAsSelectionNode();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030057 if (selection && selection->getFalseBlock() != nullptr)
Jamie Madille53c98b2014-02-03 11:57:13 -050058 {
Jamie Madilled3eef12014-02-26 09:47:11 -050059 // Check for if / else if
60 TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
61 if (elseIfBranch)
62 {
63 selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
64 delete elseIfBranch;
65 }
66
Zhenyao Moe40d1e92014-07-16 17:40:36 -070067 (*node->getSequence())[statementIndex] = rewriteSelection(selection);
Jamie Madille53c98b2014-02-03 11:57:13 -050068 delete selection;
69 }
70 }
71 }
72 break;
73
Jamie Madill787fc032014-07-07 12:49:45 -040074 case EOpFunction:
75 // Store the current function context (see comment below)
76 mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
77 break;
78
Jamie Madille53c98b2014-02-03 11:57:13 -050079 default: break;
80 }
81
82 return true;
83}
84
85TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
86{
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030087 ASSERT(selection != nullptr);
Jamie Madille53c98b2014-02-03 11:57:13 -050088
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030089 nextTemporaryIndex();
90
Jamie Madille53c98b2014-02-03 11:57:13 -050091 TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030092 TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
Jamie Madill787fc032014-07-07 12:49:45 -040093
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030094 TIntermSelection *falseBlock = nullptr;
95
96 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040097
98 if (selection->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -040099 {
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300100 TIntermAggregate *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -0400101 // crbug.com/346463
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)
106 {
107 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
108 mFunctionType->getBasicString();
109 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300110 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
111 negatedElse = new TIntermAggregate(EOpSequence);
112 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -0400113 }
114
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300115 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Jamie Madill4836d222014-07-24 06:55:51 -0400116 TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse);
117 falseBlock = new TIntermSelection(negatedCondition,
118 selection->getFalseBlock(), negatedElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400119 }
120
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300121 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
122 TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, selection->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500123
124 TIntermAggregate *block = new TIntermAggregate(EOpSequence);
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300125 block->getSequence()->push_back(storeCondition);
Jamie Madill4836d222014-07-24 06:55:51 -0400126 block->getSequence()->push_back(newSelection);
Jamie Madille53c98b2014-02-03 11:57:13 -0500127
128 return block;
129}
130
Jamie Madill4836d222014-07-24 06:55:51 -0400131}
132
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300133void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500134{
135 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300136 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500137 node->traverse(&rewriter);
138}
139
140}