blob: 13d71c799f14a9d31b5b4a4c3e4855c8ce361eea [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;
Jamie Madill4836d222014-07-24 06:55:51 -040029
30 private:
Jamie Madill4836d222014-07-24 06:55:51 -040031 const TType *mFunctionType;
32
Olli Etuaho57961272016-09-14 13:57:46 +030033 TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
Jamie Madill4836d222014-07-24 06:55:51 -040034};
35
Jamie Madill787fc032014-07-07 12:49:45 -040036ElseBlockRewriter::ElseBlockRewriter()
Olli Etuaho64f0be92015-06-03 17:38:34 +030037 : TIntermTraverser(true, false, true),
Jamie Madill787fc032014-07-07 12:49:45 -040038 mFunctionType(NULL)
39{}
40
Jamie Madille53c98b2014-02-03 11:57:13 -050041bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
42{
43 switch (node->getOp())
44 {
45 case EOpSequence:
Jamie Madill787fc032014-07-07 12:49:45 -040046 if (visit == PostVisit)
Jamie Madille53c98b2014-02-03 11:57:13 -050047 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070048 for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++)
Jamie Madille53c98b2014-02-03 11:57:13 -050049 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070050 TIntermNode *statement = (*node->getSequence())[statementIndex];
Olli Etuaho57961272016-09-14 13:57:46 +030051 TIntermIfElse *ifElse = statement->getAsIfElseNode();
52 if (ifElse && ifElse->getFalseBlock() != nullptr)
Jamie Madille53c98b2014-02-03 11:57:13 -050053 {
Olli Etuaho57961272016-09-14 13:57:46 +030054 (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
Jamie Madille53c98b2014-02-03 11:57:13 -050055 }
56 }
57 }
58 break;
59
Jamie Madill787fc032014-07-07 12:49:45 -040060 case EOpFunction:
61 // Store the current function context (see comment below)
62 mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
63 break;
64
Jamie Madille53c98b2014-02-03 11:57:13 -050065 default: break;
66 }
67
68 return true;
69}
70
Olli Etuaho57961272016-09-14 13:57:46 +030071TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
Jamie Madille53c98b2014-02-03 11:57:13 -050072{
Olli Etuaho57961272016-09-14 13:57:46 +030073 ASSERT(ifElse != nullptr);
Jamie Madille53c98b2014-02-03 11:57:13 -050074
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030075 nextTemporaryIndex();
76
Olli Etuaho57961272016-09-14 13:57:46 +030077 TIntermTyped *typedCondition = ifElse->getCondition()->getAsTyped();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030078 TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
Jamie Madill787fc032014-07-07 12:49:45 -040079
Olli Etuaho32db19b2016-10-04 14:43:16 +010080 TIntermAggregate *falseBlock = nullptr;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030081
82 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040083
Olli Etuaho57961272016-09-14 13:57:46 +030084 if (ifElse->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -040085 {
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030086 TIntermAggregate *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -040087 // crbug.com/346463
88 // D3D generates error messages claiming a function has no return value, when rewriting
89 // an if-else clause that returns something non-void in a function. By appending dummy
90 // returns (that are unreachable) we can silence this compile error.
91 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
92 {
93 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
94 mFunctionType->getBasicString();
95 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030096 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
97 negatedElse = new TIntermAggregate(EOpSequence);
98 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -040099 }
100
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300101 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Olli Etuahoa2234302016-08-31 12:05:39 +0300102 TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
Olli Etuaho32db19b2016-10-04 14:43:16 +0100103 TIntermIfElse *falseIfElse =
104 new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
105 falseBlock = TIntermediate::EnsureSequence(falseIfElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400106 }
107
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300108 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
Olli Etuaho57961272016-09-14 13:57:46 +0300109 TIntermIfElse *newIfElse =
110 new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500111
112 TIntermAggregate *block = new TIntermAggregate(EOpSequence);
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300113 block->getSequence()->push_back(storeCondition);
Olli Etuaho57961272016-09-14 13:57:46 +0300114 block->getSequence()->push_back(newIfElse);
Jamie Madille53c98b2014-02-03 11:57:13 -0500115
116 return block;
117}
118
Jamie Madill4836d222014-07-24 06:55:51 -0400119}
120
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300121void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500122{
123 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300124 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500125 node->traverse(&rewriter);
126}
127
128}