blob: 65c9e5e424006e42e3299bafa47866d50cb5fd6b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/sksl/SkSLAnalysis.h"
#include "include/private/SkSLIRNode.h"
#include "include/private/SkSLStatement.h"
#include "src/sksl/analysis/SkSLProgramVisitor.h"
namespace SkSL {
class Expression;
namespace Analysis {
namespace {
class LoopControlFlowVisitor : public ProgramVisitor {
public:
LoopControlFlowVisitor() {}
bool visitExpression(const Expression& expr) override {
// We can avoid processing expressions entirely.
return false;
}
bool visitStatement(const Statement& stmt) override {
switch (stmt.kind()) {
case Statement::Kind::kContinue:
// A continue only affects the control flow of the loop if it's not nested inside
// another looping structure. (Inside a switch, SkSL disallows continue entirely.)
fResult.fHasContinue |= (fDepth == 0);
break;
case Statement::Kind::kBreak:
// A break only affects the control flow of the loop if it's not nested inside
// another loop/switch structure.
fResult.fHasBreak |= (fDepth == 0);
break;
case Statement::Kind::kReturn:
// A return will abort the loop's control flow no matter how deeply it is nested.
fResult.fHasReturn = true;
break;
case Statement::Kind::kFor:
case Statement::Kind::kDo:
case Statement::Kind::kSwitch: {
++fDepth;
bool done = ProgramVisitor::visitStatement(stmt);
--fDepth;
return done;
}
default:
return ProgramVisitor::visitStatement(stmt);
}
// If we've already found everything we're hunting for, we can stop searching early.
return fResult.fHasContinue && fResult.fHasBreak && fResult.fHasReturn;
}
LoopControlFlowInfo fResult;
int fDepth = 0;
};
} // namespace
LoopControlFlowInfo GetLoopControlFlowInfo(const Statement& stmt) {
LoopControlFlowVisitor visitor;
visitor.visitStatement(stmt);
return visitor.fResult;
}
} // namespace Analysis
} // namespace SkSL
|