blob: a12af57b6849d2cecf0afc4c2d3f1d5e386b59e1 [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 Madilld7b1ab52016-12-12 14:42:19 -050037ElseBlockRewriter::ElseBlockRewriter() : TIntermTraverser(true, false, true), mFunctionType(NULL)
38{
39}
Jamie Madill787fc032014-07-07 12:49:45 -040040
Olli Etuaho336b1472016-10-05 16:37:55 +010041bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
Jamie Madille53c98b2014-02-03 11:57:13 -050042{
Olli Etuaho336b1472016-10-05 16:37:55 +010043 // Store the current function context (see comment below)
44 mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010045 return true;
46}
47
48bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
49{
50 if (visit == PostVisit)
51 {
52 for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
53 statementIndex++)
Jamie Madille53c98b2014-02-03 11:57:13 -050054 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010055 TIntermNode *statement = (*node->getSequence())[statementIndex];
56 TIntermIfElse *ifElse = statement->getAsIfElseNode();
57 if (ifElse && ifElse->getFalseBlock() != nullptr)
Jamie Madille53c98b2014-02-03 11:57:13 -050058 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010059 (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
Jamie Madille53c98b2014-02-03 11:57:13 -050060 }
61 }
Jamie Madille53c98b2014-02-03 11:57:13 -050062 }
Jamie Madille53c98b2014-02-03 11:57:13 -050063 return true;
64}
65
Olli Etuaho57961272016-09-14 13:57:46 +030066TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
Jamie Madille53c98b2014-02-03 11:57:13 -050067{
Olli Etuaho57961272016-09-14 13:57:46 +030068 ASSERT(ifElse != nullptr);
Jamie Madille53c98b2014-02-03 11:57:13 -050069
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030070 nextTemporaryIndex();
71
Olli Etuaho13389b62016-10-16 11:48:18 +010072 TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
Jamie Madill787fc032014-07-07 12:49:45 -040073
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010074 TIntermBlock *falseBlock = nullptr;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030075
76 TType boolType(EbtBool, EbpUndefined, EvqTemporary);
Jamie Madill4836d222014-07-24 06:55:51 -040077
Olli Etuaho57961272016-09-14 13:57:46 +030078 if (ifElse->getFalseBlock())
Jamie Madill787fc032014-07-07 12:49:45 -040079 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010080 TIntermBlock *negatedElse = nullptr;
Jamie Madill4836d222014-07-24 06:55:51 -040081 // crbug.com/346463
82 // D3D generates error messages claiming a function has no return value, when rewriting
83 // an if-else clause that returns something non-void in a function. By appending dummy
84 // returns (that are unreachable) we can silence this compile error.
85 if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
86 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050087 TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name()
88 : mFunctionType->getBasicString();
89 TString rawText = "return (" + typeString + ")0";
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030090 TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010091 negatedElse = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030092 negatedElse->getSequence()->push_back(returnNode);
Jamie Madill4836d222014-07-24 06:55:51 -040093 }
94
Olli Etuaho4d59f3c2015-05-28 17:33:53 +030095 TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
Olli Etuahoa2234302016-08-31 12:05:39 +030096 TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
Olli Etuaho32db19b2016-10-04 14:43:16 +010097 TIntermIfElse *falseIfElse =
98 new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010099 falseBlock = TIntermediate::EnsureBlock(falseIfElse);
Jamie Madill787fc032014-07-07 12:49:45 -0400100 }
101
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300102 TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
Olli Etuaho57961272016-09-14 13:57:46 +0300103 TIntermIfElse *newIfElse =
104 new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
Jamie Madille53c98b2014-02-03 11:57:13 -0500105
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100106 TIntermBlock *block = new TIntermBlock();
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300107 block->getSequence()->push_back(storeCondition);
Olli Etuaho57961272016-09-14 13:57:46 +0300108 block->getSequence()->push_back(newIfElse);
Jamie Madille53c98b2014-02-03 11:57:13 -0500109
110 return block;
111}
Jamie Madill4836d222014-07-24 06:55:51 -0400112}
113
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300114void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
Jamie Madille53c98b2014-02-03 11:57:13 -0500115{
116 ElseBlockRewriter rewriter;
Olli Etuaho4d59f3c2015-05-28 17:33:53 +0300117 rewriter.useTemporaryIndex(temporaryIndex);
Jamie Madille53c98b2014-02-03 11:57:13 -0500118 node->traverse(&rewriter);
119}
Jamie Madille53c98b2014-02-03 11:57:13 -0500120}