tor-browser

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

ValidateBarrierFunctionCall.cpp (2679B)


      1 //
      2 // Copyright 2020 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 // ValidateBarrierFunctionCalls:
      7 //   Runs compilation checks related to the "barrier built-in function.
      8 
      9 #include "compiler/translator/ValidateBarrierFunctionCall.h"
     10 
     11 #include "compiler/translator/Diagnostics.h"
     12 #include "compiler/translator/SymbolTable.h"
     13 #include "compiler/translator/tree_util/IntermTraverse.h"
     14 
     15 namespace sh
     16 {
     17 namespace
     18 {
     19 class Traverser : public TIntermTraverser
     20 {
     21  public:
     22    Traverser(TDiagnostics *diagnostics)
     23        : TIntermTraverser(true, false, true), mDiagnostics(diagnostics)
     24    {}
     25 
     26    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
     27    {
     28        if (!node->getFunction()->isMain())
     29        {
     30            return false;
     31        }
     32 
     33        mInMain = visit == PreVisit;
     34        return true;
     35    }
     36 
     37    bool visitBranch(Visit visit, TIntermBranch *branch) override
     38    {
     39        if (branch->getFlowOp() == EOpReturn)
     40        {
     41            mSeenReturn = true;
     42        }
     43 
     44        return true;
     45    }
     46 
     47    bool visitAggregate(Visit visit, TIntermAggregate *node) override
     48    {
     49        if (node->getOp() != EOpBarrierTCS)
     50        {
     51            return true;
     52        }
     53 
     54        if (mSeenReturn)
     55        {
     56            mDiagnostics->error(node->getLine(),
     57                                "barrier() may not be called at any point after a return statement "
     58                                "in the function main().",
     59                                "barrier");
     60            mValid = false;
     61            return false;
     62        }
     63 
     64        // TODO(anglebug.com/5557): Determine if we should check loops as well.
     65        if (mBranchCount > 0)
     66        {
     67            mDiagnostics->error(
     68                node->getLine(),
     69                "barrier() may not be called in potentially divergent flow control.", "barrier");
     70            mValid = false;
     71            return false;
     72        }
     73 
     74        return true;
     75    }
     76 
     77    bool visitIfElse(Visit visit, TIntermIfElse *node) override
     78    {
     79        mBranchCount += ((visit == PreVisit) ? 1 : -1);
     80        return true;
     81    }
     82 
     83    bool valid() const { return mValid; }
     84 
     85  private:
     86    TDiagnostics *mDiagnostics = nullptr;
     87    bool mInMain               = false;
     88    bool mSeenReturn           = false;
     89    bool mValid                = true;
     90    uint32_t mBranchCount      = 0;
     91 };
     92 }  // anonymous namespace
     93 
     94 bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics)
     95 {
     96    Traverser traverser(diagnostics);
     97    root->traverse(&traverser);
     98    return traverser.valid();
     99 }
    100 }  // namespace sh