blob: aafb86f1c964fcabe192f69d3a4405e8e1c85362 [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 Etuaho57961272016-09-14 13:57:46 +030073 TIntermTyped *typedCondition = ifElse->getCondition()->getAsTyped();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030074 TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
Jamie Madill787fc032014-07-07 12:49:45 -040075
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010076 TIntermBlock *falseBlock = nullptr;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030077
78 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040079
Olli Etuaho57961272016-09-14 13:57:46 +030080 if (ifElse->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -040081 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010082 TIntermBlock *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -040083 // crbug.com/346463
84 // D3D generates error messages claiming a function has no return value, when rewriting
85 // an if-else clause that returns something non-void in a function. By appending dummy
86 // returns (that are unreachable) we can silence this compile error.
87 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
88 {
89 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
90 mFunctionType->getBasicString();
91 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030092 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010093 negatedElse = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030094 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -040095 }
96
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030097 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Olli Etuahoa2234302016-08-31 12:05:39 +030098 TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
Olli Etuaho32db19b2016-10-04 14:43:16 +010099 TIntermIfElse *falseIfElse =
100 new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100101 falseBlock = TIntermediate::EnsureBlock(falseIfElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400102 }
103
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300104 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
Olli Etuaho57961272016-09-14 13:57:46 +0300105 TIntermIfElse *newIfElse =
106 new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500107
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100108 TIntermBlock *block = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300109 block->getSequence()->push_back(storeCondition);
Olli Etuaho57961272016-09-14 13:57:46 +0300110 block->getSequence()->push_back(newIfElse);
Jamie Madille53c98b2014-02-03 11:57:13 -0500111
112 return block;
113}
114
Jamie Madill4836d222014-07-24 06:55:51 -0400115}
116
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300117void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500118{
119 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300120 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500121 node->traverse(&rewriter);
122}
123
124}