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