Line data Source code
1 : //
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"
11 :
12 : #include "compiler/translator/Intermediate.h"
13 : #include "compiler/translator/NodeSearch.h"
14 : #include "compiler/translator/SymbolTable.h"
15 :
16 : namespace sh
17 : {
18 :
19 : namespace
20 : {
21 :
22 0 : class ElseBlockRewriter : public TIntermTraverser
23 : {
24 : public:
25 : ElseBlockRewriter();
26 :
27 : protected:
28 : bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override;
29 : bool visitBlock(Visit visit, TIntermBlock *block) override;
30 :
31 : private:
32 : const TType *mFunctionType;
33 :
34 : TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
35 : };
36 :
37 0 : ElseBlockRewriter::ElseBlockRewriter()
38 : : TIntermTraverser(true, false, true),
39 0 : mFunctionType(NULL)
40 0 : {}
41 :
42 0 : bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
43 : {
44 : // Store the current function context (see comment below)
45 0 : mFunctionType = ((visit == PreVisit) ? &node->getType() : nullptr);
46 0 : return true;
47 : }
48 :
49 0 : bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
50 : {
51 0 : if (visit == PostVisit)
52 : {
53 0 : for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
54 : statementIndex++)
55 : {
56 0 : TIntermNode *statement = (*node->getSequence())[statementIndex];
57 0 : TIntermIfElse *ifElse = statement->getAsIfElseNode();
58 0 : if (ifElse && ifElse->getFalseBlock() != nullptr)
59 : {
60 0 : (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
61 : }
62 : }
63 : }
64 0 : return true;
65 : }
66 :
67 0 : TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
68 : {
69 0 : ASSERT(ifElse != nullptr);
70 :
71 0 : nextTemporaryIndex();
72 :
73 0 : TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
74 :
75 0 : TIntermBlock *falseBlock = nullptr;
76 :
77 0 : TType boolType(EbtBool, EbpUndefined, EvqTemporary);
78 :
79 0 : if (ifElse->getFalseBlock())
80 : {
81 0 : TIntermBlock *negatedElse = nullptr;
82 : // 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 0 : if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
87 : {
88 0 : TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
89 0 : mFunctionType->getBasicString();
90 0 : TString rawText = "return (" + typeString + ")0";
91 0 : TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
92 0 : negatedElse = new TIntermBlock();
93 0 : negatedElse->getSequence()->push_back(returnNode);
94 : }
95 :
96 0 : TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
97 0 : TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
98 : TIntermIfElse *falseIfElse =
99 0 : new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
100 0 : falseBlock = TIntermediate::EnsureBlock(falseIfElse);
101 : }
102 :
103 0 : TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
104 : TIntermIfElse *newIfElse =
105 0 : new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
106 :
107 0 : TIntermBlock *block = new TIntermBlock();
108 0 : block->getSequence()->push_back(storeCondition);
109 0 : block->getSequence()->push_back(newIfElse);
110 :
111 0 : return block;
112 : }
113 :
114 : }
115 :
116 0 : void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
117 : {
118 0 : ElseBlockRewriter rewriter;
119 0 : rewriter.useTemporaryIndex(temporaryIndex);
120 0 : node->traverse(&rewriter);
121 0 : }
122 :
123 : }
|