1e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// 2e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. 3e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// Use of this source code is governed by a BSD-style license that can be 4e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// found in the LICENSE file. 5e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// 6e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// RewriteElseBlocks.cpp: Implementation for tree transform to change 7e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// all if-else blocks to if-if blocks. 8e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill// 9e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 10e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill#include "compiler/translator/RewriteElseBlocks.h" 11e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill#include "compiler/translator/NodeSearch.h" 12e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill#include "compiler/translator/SymbolTable.h" 13e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 14e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madillnamespace sh 15e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 16e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 17e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie MadillTIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type) 18e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 19e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TType variableType(type, EbpHigh, EvqInternal); 20e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill return new TIntermSymbol(-1, name, variableType); 21e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 22e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 23e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie MadillTIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType) 24e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 25e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermBinary *binary = new TIntermBinary(op); 26e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill binary->setLeft(left); 27e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill binary->setRight(right); 28e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill binary->setType(resultType); 29e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill return binary; 30e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 31e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 32e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie MadillTIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand) 33e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 34e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermUnary *unary = new TIntermUnary(op, operand->getType()); 35e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill unary->setOperand(operand); 36e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill return unary; 37e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 38e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 39ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie MadillElseBlockRewriter::ElseBlockRewriter() 40ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill : TIntermTraverser(true, false, true, false), 41ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill mTemporaryIndex(0), 42ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill mFunctionType(NULL) 43ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill{} 44ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill 45e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madillbool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) 46e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 47e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill switch (node->getOp()) 48e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill { 49e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill case EOpSequence: 50ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill if (visit == PostVisit) 51e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill { 52e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++) 53e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill { 54e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermNode *statement = node->getSequence()[statementIndex]; 55e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermSelection *selection = statement->getAsSelectionNode(); 56e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill if (selection && selection->getFalseBlock() != NULL) 57e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill { 585ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill // Check for if / else if 595ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode(); 605ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill if (elseIfBranch) 615ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill { 625ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch)); 635ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill delete elseIfBranch; 645ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill } 655ec99a794952ac04e89bac86b3a6acc50667be71Jamie Madill 66e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill node->getSequence()[statementIndex] = rewriteSelection(selection); 67e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill delete selection; 68e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill } 69e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill } 70e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill } 71e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill break; 72e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 73ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill case EOpFunction: 74ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill // Store the current function context (see comment below) 75ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL); 76ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill break; 77ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill 78e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill default: break; 79e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill } 80e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 81e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill return true; 82e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 83e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 84e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie MadillTIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection) 85e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 86e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill ASSERT(selection->getFalseBlock() != NULL); 87e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 88e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TString temporaryName = "cond_" + str(mTemporaryIndex++); 89e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermTyped *typedCondition = selection->getCondition()->getAsTyped(); 90e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TType resultType(EbtBool, EbpUndefined); 91e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool); 92e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool); 93e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool); 94e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA, 95e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill typedCondition, resultType); 96e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB); 97ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill TIntermNode *negatedElse = NULL; 98ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill 99ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill // crbug.com/346463 100ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill // D3D generates error messages claiming a function has no return value, when rewriting 101ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill // an if-else clause that returns something non-void in a function. By appending dummy 102ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill // returns (that are unreachable) we can silence this compile error. 103ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill if (mFunctionType && mFunctionType->getBasicType() != EbtVoid) 104ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill { 105ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() : 106ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill mFunctionType->getBasicString(); 107ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill TString rawText = "return (" + typeString + ")0"; 108ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill negatedElse = new TIntermRaw(*mFunctionType, rawText); 109ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill } 110ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill 111e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermSelection *falseBlock = new TIntermSelection(negatedCondition, 112ebba7d306b34a56f57ff1b87682bdc67cc9c50f8Jamie Madill selection->getFalseBlock(), negatedElse); 113e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC, 114e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill selection->getTrueBlock(), falseBlock); 115e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 116e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration); 117e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill declaration->getSequence().push_back(storeCondition); 118e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 119e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill TIntermAggregate *block = new TIntermAggregate(EOpSequence); 120e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill block->getSequence().push_back(declaration); 121e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill block->getSequence().push_back(newIfElse); 122e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 123e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill return block; 124e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 125e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 126e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madillvoid RewriteElseBlocks(TIntermNode *node) 127e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill{ 128e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill ElseBlockRewriter rewriter; 129e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill node->traverse(&rewriter); 130e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 131e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill 132e53c98ba6cd85074d8f2dae76b34321c7786da3aJamie Madill} 133