diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp b/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp new file mode 100644 index 0000000000..23479906e1 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ValidateBarrierFunctionCall.cpp @@ -0,0 +1,100 @@ +// +// Copyright 2020 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. +// +// ValidateBarrierFunctionCalls: +// Runs compilation checks related to the "barrier built-in function. + +#include "compiler/translator/ValidateBarrierFunctionCall.h" + +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ +namespace +{ +class Traverser : public TIntermTraverser +{ + public: + Traverser(TDiagnostics *diagnostics) + : TIntermTraverser(true, false, true), mDiagnostics(diagnostics) + {} + + bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override + { + if (!node->getFunction()->isMain()) + { + return false; + } + + mInMain = visit == PreVisit; + return true; + } + + bool visitBranch(Visit visit, TIntermBranch *branch) override + { + if (branch->getFlowOp() == EOpReturn) + { + mSeenReturn = true; + } + + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + if (node->getOp() != EOpBarrier) + { + return true; + } + + if (mSeenReturn) + { + mDiagnostics->error(node->getLine(), + "barrier() may not be called at any point after a return statement " + "in the function main().", + "barrier"); + mValid = false; + return false; + } + + // TODO(anglebug.com/5557): Determine if we should check loops as well. + if (mBranchCount > 0) + { + mDiagnostics->error( + node->getLine(), + "barrier() may not be called in potentially divergent flow control.", "barrier"); + mValid = false; + return false; + } + + return true; + } + + bool visitIfElse(Visit visit, TIntermIfElse *node) override + { + mBranchCount += ((visit == PreVisit) ? 1 : -1); + return true; + } + + bool valid() const { return mValid; } + + private: + TDiagnostics *mDiagnostics = nullptr; + bool mInMain = false; + bool mSeenReturn = false; + bool mValid = true; + uint32_t mBranchCount = 0; +}; +} // anonymous namespace + +bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics) +{ + Traverser traverser(diagnostics); + root->traverse(&traverser); + return traverser.valid(); +} +} // namespace sh |