blob: 937de11cd9ddbaac4901dbeb9d21b412fbd6d489 [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:
Olli Etuaho336b1472016-10-05 16:37:55 +010028 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *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
Olli Etuaho336b1472016-10-05 16:37:55 +010042bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
Jamie Madille53c98b2014-02-03 11:57:13 -050043{
Olli Etuaho336b1472016-10-05 16:37:55 +010044 // Store the current function context (see comment below)
45 mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010046 return true;
47}
48
49bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
50{
51 if (visit == PostVisit)
52 {
53 for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
54 statementIndex++)
Jamie Madille53c98b2014-02-03 11:57:13 -050055 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010056 TIntermNode *statement = (*node->getSequence())[statementIndex];
57 TIntermIfElse *ifElse = statement->getAsIfElseNode();
58 if (ifElse && ifElse->getFalseBlock() != nullptr)
Jamie Madille53c98b2014-02-03 11:57:13 -050059 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010060 (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
Jamie Madille53c98b2014-02-03 11:57:13 -050061 }
62 }
Jamie Madille53c98b2014-02-03 11:57:13 -050063 }
Jamie Madille53c98b2014-02-03 11:57:13 -050064 return true;
65}
66
Olli Etuaho57961272016-09-14 13:57:46 +030067TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
Jamie Madille53c98b2014-02-03 11:57:13 -050068{
Olli Etuaho57961272016-09-14 13:57:46 +030069 ASSERT(ifElse != nullptr);
Jamie Madille53c98b2014-02-03 11:57:13 -050070
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030071 nextTemporaryIndex();
72
Olli Etuaho13389b62016-10-16 11:48:18 +010073 TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
Jamie Madill787fc032014-07-07 12:49:45 -040074
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010075 TIntermBlock *falseBlock = nullptr;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030076
77 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040078
Olli Etuaho57961272016-09-14 13:57:46 +030079 if (ifElse->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -040080 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010081 TIntermBlock *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -040082 // crbug.com/346463
83 // D3D generates error messages claiming a function has no return value, when rewriting
84 // an if-else clause that returns something non-void in a function. By appending dummy
85 // returns (that are unreachable) we can silence this compile error.
86 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
87 {
88 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
89 mFunctionType->getBasicString();
90 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030091 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010092 negatedElse = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030093 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -040094 }
95
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030096 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Olli Etuahoa2234302016-08-31 12:05:39 +030097 TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
Olli Etuaho32db19b2016-10-04 14:43:16 +010098 TIntermIfElse *falseIfElse =
99 new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100100 falseBlock = TIntermediate::EnsureBlock(falseIfElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400101 }
102
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300103 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
Olli Etuaho57961272016-09-14 13:57:46 +0300104 TIntermIfElse *newIfElse =
105 new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500106
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100107 TIntermBlock *block = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300108 block->getSequence()->push_back(storeCondition);
Olli Etuaho57961272016-09-14 13:57:46 +0300109 block->getSequence()->push_back(newIfElse);
Jamie Madille53c98b2014-02-03 11:57:13 -0500110
111 return block;
112}
113
Jamie Madill4836d222014-07-24 06:55:51 -0400114}
115
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300116void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500117{
118 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300119 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500120 node->traverse(&rewriter);
121}
122
123}