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