blob: c9427e24c1ed5920be02a7d4909294281028b65a [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"
Olli Etuaho32db19b2016-10-04 14:43:16 +010011
12#include "compiler/translator/Intermediate.h"
Jamie Madille53c98b2014-02-03 11:57:13 -050013#include "compiler/translator/NodeSearch.h"
14#include "compiler/translator/SymbolTable.h"
15
16namespace sh
17{
18
Jamie Madill4836d222014-07-24 06:55:51 -040019namespace
20{
21
22class ElseBlockRewriter : public TIntermTraverser
23{
24 public:
25 ElseBlockRewriter();
26
27 protected:
Corentin Wallez2d58f7a2015-09-28 10:44:55 -070028 bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override;
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010029 bool visitBlock(Visit visit, TIntermBlock *block) override;
Jamie Madill4836d222014-07-24 06:55:51 -040030
31 private:
Jamie Madill4836d222014-07-24 06:55:51 -040032 const TType *mFunctionType;
33
Olli Etuaho57961272016-09-14 13:57:46 +030034 TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
Jamie Madill4836d222014-07-24 06:55:51 -040035};
36
Jamie Madill787fc032014-07-07 12:49:45 -040037ElseBlockRewriter::ElseBlockRewriter()
Olli Etuaho64f0be92015-06-03 17:38:34 +030038 : TIntermTraverser(true, false, true),
Jamie Madill787fc032014-07-07 12:49:45 -040039 mFunctionType(NULL)
40{}
41
Jamie Madille53c98b2014-02-03 11:57:13 -050042bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
43{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010044 if (node->getOp() == EOpFunction)
Jamie Madille53c98b2014-02-03 11:57:13 -050045 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010046 // Store the current function context (see comment below)
47 mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr);
48 }
49 return true;
50}
51
52bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
53{
54 if (visit == PostVisit)
55 {
56 for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
57 statementIndex++)
Jamie Madille53c98b2014-02-03 11:57:13 -050058 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010059 TIntermNode *statement = (*node->getSequence())[statementIndex];
60 TIntermIfElse *ifElse = statement->getAsIfElseNode();
61 if (ifElse && ifElse->getFalseBlock() != nullptr)
Jamie Madille53c98b2014-02-03 11:57:13 -050062 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010063 (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
Jamie Madille53c98b2014-02-03 11:57:13 -050064 }
65 }
Jamie Madille53c98b2014-02-03 11:57:13 -050066 }
Jamie Madille53c98b2014-02-03 11:57:13 -050067 return true;
68}
69
Olli Etuaho57961272016-09-14 13:57:46 +030070TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
Jamie Madille53c98b2014-02-03 11:57:13 -050071{
Olli Etuaho57961272016-09-14 13:57:46 +030072 ASSERT(ifElse != nullptr);
Jamie Madille53c98b2014-02-03 11:57:13 -050073
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030074 nextTemporaryIndex();
75
Olli Etuaho57961272016-09-14 13:57:46 +030076 TIntermTyped *typedCondition = ifElse->getCondition()->getAsTyped();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030077 TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
Jamie Madill787fc032014-07-07 12:49:45 -040078
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010079 TIntermBlock *falseBlock = nullptr;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030080
81 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040082
Olli Etuaho57961272016-09-14 13:57:46 +030083 if (ifElse->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -040084 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010085 TIntermBlock *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -040086 // crbug.com/346463
87 // D3D generates error messages claiming a function has no return value, when rewriting
88 // an if-else clause that returns something non-void in a function. By appending dummy
89 // returns (that are unreachable) we can silence this compile error.
90 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
91 {
92 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
93 mFunctionType->getBasicString();
94 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030095 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010096 negatedElse = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030097 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -040098 }
99
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300100 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Olli Etuahoa2234302016-08-31 12:05:39 +0300101 TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
Olli Etuaho32db19b2016-10-04 14:43:16 +0100102 TIntermIfElse *falseIfElse =
103 new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100104 falseBlock = TIntermediate::EnsureBlock(falseIfElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400105 }
106
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300107 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
Olli Etuaho57961272016-09-14 13:57:46 +0300108 TIntermIfElse *newIfElse =
109 new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500110
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100111 TIntermBlock *block = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300112 block->getSequence()->push_back(storeCondition);
Olli Etuaho57961272016-09-14 13:57:46 +0300113 block->getSequence()->push_back(newIfElse);
Jamie Madille53c98b2014-02-03 11:57:13 -0500114
115 return block;
116}
117
Jamie Madill4836d222014-07-24 06:55:51 -0400118}
119
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300120void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500121{
122 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300123 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500124 node->traverse(&rewriter);
125}
126
127}