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