blob: ab27dfddd1a7969dd411800c8cdf25a4fa54e908 [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:
29 int mTemporaryIndex;
30 const TType *mFunctionType;
31
32 TIntermNode *rewriteSelection(TIntermSelection *selection);
33};
34
Jamie Madille53c98b2014-02-03 11:57:13 -050035TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
36{
37 TIntermUnary *unary = new TIntermUnary(op, operand->getType());
38 unary->setOperand(operand);
39 return unary;
40}
41
Jamie Madill787fc032014-07-07 12:49:45 -040042ElseBlockRewriter::ElseBlockRewriter()
43 : TIntermTraverser(true, false, true, false),
44 mTemporaryIndex(0),
45 mFunctionType(NULL)
46{}
47
Jamie Madille53c98b2014-02-03 11:57:13 -050048bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
49{
50 switch (node->getOp())
51 {
52 case EOpSequence:
Jamie Madill787fc032014-07-07 12:49:45 -040053 if (visit == PostVisit)
Jamie Madille53c98b2014-02-03 11:57:13 -050054 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070055 for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++)
Jamie Madille53c98b2014-02-03 11:57:13 -050056 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070057 TIntermNode *statement = (*node->getSequence())[statementIndex];
Jamie Madille53c98b2014-02-03 11:57:13 -050058 TIntermSelection *selection = statement->getAsSelectionNode();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030059 if (selection && selection->getFalseBlock() != nullptr)
Jamie Madille53c98b2014-02-03 11:57:13 -050060 {
Jamie Madilled3eef12014-02-26 09:47:11 -050061 // Check for if / else if
62 TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
63 if (elseIfBranch)
64 {
65 selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
66 delete elseIfBranch;
67 }
68
Zhenyao Moe40d1e92014-07-16 17:40:36 -070069 (*node->getSequence())[statementIndex] = rewriteSelection(selection);
Jamie Madille53c98b2014-02-03 11:57:13 -050070 delete selection;
71 }
72 }
73 }
74 break;
75
Jamie Madill787fc032014-07-07 12:49:45 -040076 case EOpFunction:
77 // Store the current function context (see comment below)
78 mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
79 break;
80
Jamie Madille53c98b2014-02-03 11:57:13 -050081 default: break;
82 }
83
84 return true;
85}
86
87TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
88{
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030089 ASSERT(selection != nullptr);
Jamie Madille53c98b2014-02-03 11:57:13 -050090
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030091 nextTemporaryIndex();
92
Jamie Madille53c98b2014-02-03 11:57:13 -050093 TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030094 TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
Jamie Madill787fc032014-07-07 12:49:45 -040095
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030096 TIntermSelection *falseBlock = nullptr;
97
98 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040099
100 if (selection->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -0400101 {
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300102 TIntermAggregate *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -0400103 // crbug.com/346463
104 // D3D generates error messages claiming a function has no return value, when rewriting
105 // an if-else clause that returns something non-void in a function. By appending dummy
106 // returns (that are unreachable) we can silence this compile error.
107 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
108 {
109 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
110 mFunctionType->getBasicString();
111 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300112 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
113 negatedElse = new TIntermAggregate(EOpSequence);
114 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -0400115 }
116
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300117 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Jamie Madill4836d222014-07-24 06:55:51 -0400118 TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse);
119 falseBlock = new TIntermSelection(negatedCondition,
120 selection->getFalseBlock(), negatedElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400121 }
122
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300123 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
124 TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, selection->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500125
126 TIntermAggregate *block = new TIntermAggregate(EOpSequence);
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300127 block->getSequence()->push_back(storeCondition);
Jamie Madill4836d222014-07-24 06:55:51 -0400128 block->getSequence()->push_back(newSelection);
Jamie Madille53c98b2014-02-03 11:57:13 -0500129
130 return block;
131}
132
Jamie Madill4836d222014-07-24 06:55:51 -0400133}
134
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300135void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500136{
137 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300138 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500139 node->traverse(&rewriter);
140}
141
142}