tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RewriteElseBlocks.cpp (4093B)


      1 //
      2 // Copyright 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/tree_ops/d3d/RewriteElseBlocks.h"
     11 
     12 #include "compiler/translator/Compiler.h"
     13 #include "compiler/translator/IntermNode.h"
     14 #include "compiler/translator/SymbolTable.h"
     15 #include "compiler/translator/tree_util/IntermNode_util.h"
     16 #include "compiler/translator/tree_util/NodeSearch.h"
     17 
     18 namespace sh
     19 {
     20 
     21 namespace
     22 {
     23 
     24 class ElseBlockRewriter : public TIntermTraverser
     25 {
     26  public:
     27    ElseBlockRewriter(TSymbolTable *symbolTable);
     28 
     29  protected:
     30    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override;
     31    bool visitBlock(Visit visit, TIntermBlock *block) override;
     32 
     33  private:
     34    TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
     35 
     36    const TType *mFunctionType;
     37 };
     38 
     39 ElseBlockRewriter::ElseBlockRewriter(TSymbolTable *symbolTable)
     40    : TIntermTraverser(true, false, true, symbolTable), mFunctionType(nullptr)
     41 {}
     42 
     43 bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
     44 {
     45    // Store the current function context (see comment below)
     46    mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr);
     47    return true;
     48 }
     49 
     50 bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
     51 {
     52    if (visit == PostVisit)
     53    {
     54        for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
     55             statementIndex++)
     56        {
     57            TIntermNode *statement = (*node->getSequence())[statementIndex];
     58            TIntermIfElse *ifElse  = statement->getAsIfElseNode();
     59            if (ifElse && ifElse->getFalseBlock() != nullptr)
     60            {
     61                (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
     62            }
     63        }
     64    }
     65    return true;
     66 }
     67 
     68 TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
     69 {
     70    ASSERT(ifElse != nullptr);
     71 
     72    TIntermDeclaration *storeCondition = nullptr;
     73    TVariable *conditionVariable =
     74        DeclareTempVariable(mSymbolTable, ifElse->getCondition(), EvqTemporary, &storeCondition);
     75 
     76    TIntermBlock *falseBlock = nullptr;
     77 
     78    TType boolType(EbtBool, EbpUndefined, EvqTemporary);
     79 
     80    if (ifElse->getFalseBlock())
     81    {
     82        TIntermBlock *negatedElse = nullptr;
     83        // 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 mock
     86        // returns (that are unreachable) we can silence this compile error.
     87        if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
     88        {
     89            TIntermNode *returnNode = new TIntermBranch(EOpReturn, CreateZeroNode(*mFunctionType));
     90            negatedElse             = new TIntermBlock();
     91            negatedElse->appendStatement(returnNode);
     92        }
     93 
     94        TIntermSymbol *conditionSymbolElse = CreateTempSymbolNode(conditionVariable);
     95        TIntermUnary *negatedCondition =
     96            new TIntermUnary(EOpLogicalNot, conditionSymbolElse, nullptr);
     97        TIntermIfElse *falseIfElse =
     98            new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
     99        falseBlock = EnsureBlock(falseIfElse);
    100    }
    101 
    102    TIntermSymbol *conditionSymbolSel = CreateTempSymbolNode(conditionVariable);
    103    TIntermIfElse *newIfElse =
    104        new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
    105 
    106    TIntermBlock *block = new TIntermBlock();
    107    block->getSequence()->push_back(storeCondition);
    108    block->getSequence()->push_back(newIfElse);
    109 
    110    return block;
    111 }
    112 
    113 }  // anonymous namespace
    114 
    115 bool RewriteElseBlocks(TCompiler *compiler, TIntermNode *node, TSymbolTable *symbolTable)
    116 {
    117    ElseBlockRewriter rewriter(symbolTable);
    118    node->traverse(&rewriter);
    119 
    120    return compiler->validateAST(node);
    121 }
    122 
    123 }  // namespace sh