Hash :
8ad9e757
Author :
Date :
2017-01-16T19:55:20
Always store function headers in TIntermFunctionPrototype nodes TIntermFunctionDefinition nodes now have a TIntermFunctionPrototype child that stores the function signature, instead of having a separate type and an aggregate child that stores the parameters. This makes parsing functions simpler, and paves the way for further simplifications of function parsing, like reducing conversions between symbol table structures and AST structures. TIntermAggregate is now only used for function calls. BUG=angleproject:1490 TEST=angle_unittests, angle_end2end_tests Change-Id: Ib56a77b5ef5123b142963a18499690bf37fed987 Reviewed-on: https://chromium-review.googlesource.com/427945 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RewriteElseBlocks.cpp: Implementation for tree transform to change
// all if-else blocks to if-if blocks.
//
#include "compiler/translator/RewriteElseBlocks.h"
#include "compiler/translator/Intermediate.h"
#include "compiler/translator/NodeSearch.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
namespace
{
class ElseBlockRewriter : public TIntermTraverser
{
public:
ElseBlockRewriter();
protected:
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override;
bool visitBlock(Visit visit, TIntermBlock *block) override;
private:
const TType *mFunctionType;
TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
};
ElseBlockRewriter::ElseBlockRewriter() : TIntermTraverser(true, false, true), mFunctionType(NULL)
{
}
bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
// Store the current function context (see comment below)
mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr);
return true;
}
bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
{
if (visit == PostVisit)
{
for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
statementIndex++)
{
TIntermNode *statement = (*node->getSequence())[statementIndex];
TIntermIfElse *ifElse = statement->getAsIfElseNode();
if (ifElse && ifElse->getFalseBlock() != nullptr)
{
(*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
}
}
}
return true;
}
TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
{
ASSERT(ifElse != nullptr);
nextTemporaryIndex();
TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
TIntermBlock *falseBlock = nullptr;
TType boolType(EbtBool, EbpUndefined, EvqTemporary);
if (ifElse->getFalseBlock())
{
TIntermBlock *negatedElse = nullptr;
// crbug.com/346463
// D3D generates error messages claiming a function has no return value, when rewriting
// an if-else clause that returns something non-void in a function. By appending dummy
// returns (that are unreachable) we can silence this compile error.
if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
{
TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name()
: mFunctionType->getBasicString();
TString rawText = "return (" + typeString + ")0";
TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
negatedElse = new TIntermBlock();
negatedElse->getSequence()->push_back(returnNode);
}
TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
TIntermIfElse *falseIfElse =
new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
falseBlock = TIntermediate::EnsureBlock(falseIfElse);
}
TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
TIntermIfElse *newIfElse =
new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
TIntermBlock *block = new TIntermBlock();
block->getSequence()->push_back(storeCondition);
block->getSequence()->push_back(newIfElse);
return block;
}
}
void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
{
ElseBlockRewriter rewriter;
rewriter.useTemporaryIndex(temporaryIndex);
node->traverse(&rewriter);
}
}