blob: e2d1ede79483137b8107cd3096d0a6772268d6fc [file] [log] [blame]
Michael Ludwig8f3a8362020-06-29 17:27:00 -04001/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkSLAnalysis_DEFINED
9#define SkSLAnalysis_DEFINED
10
Brian Osman1298bc42020-06-30 13:39:35 -040011#include "include/private/SkSLSampleUsage.h"
Michael Ludwig8f3a8362020-06-29 17:27:00 -040012#include "src/sksl/SkSLDefines.h"
13
Brian Osman010ce6a2020-10-19 16:34:10 -040014#include <memory>
15
Michael Ludwig8f3a8362020-06-29 17:27:00 -040016namespace SkSL {
17
John Stilesdce4d3e2020-09-25 14:35:13 -040018class ErrorReporter;
Ethan Nicholas1e9f7f32020-10-08 05:28:32 -040019class Expression;
Brian Osman2e25ff42020-10-15 10:32:04 -040020class FunctionDeclaration;
Ethan Nicholas6f87de72020-10-26 15:06:46 -040021class FunctionDefinition;
Brian Osman0006ad02020-11-18 15:38:39 -050022struct LoadedModule;
Michael Ludwig8f3a8362020-06-29 17:27:00 -040023struct Program;
Ethan Nicholas1e9f7f32020-10-08 05:28:32 -040024class ProgramElement;
Brian Osman010ce6a2020-10-19 16:34:10 -040025class ProgramUsage;
Ethan Nicholas1e9f7f32020-10-08 05:28:32 -040026class Statement;
Ethan Nicholas041fd0a2020-10-07 16:42:04 -040027class Variable;
Ethan Nicholas78686922020-10-08 06:46:27 -040028class VariableReference;
Michael Ludwig8f3a8362020-06-29 17:27:00 -040029
30/**
31 * Provides utilities for analyzing SkSL statically before it's composed into a full program.
32 */
33struct Analysis {
Brian Osman1298bc42020-06-30 13:39:35 -040034 static SampleUsage GetSampleUsage(const Program& program, const Variable& fp);
Michael Ludwig8f3a8362020-06-29 17:27:00 -040035
Brian Osman92aac1e2020-08-05 16:48:58 -040036 static bool ReferencesBuiltin(const Program& program, int builtin);
37
Michael Ludwig8f3a8362020-06-29 17:27:00 -040038 static bool ReferencesSampleCoords(const Program& program);
Brian Osman92aac1e2020-08-05 16:48:58 -040039 static bool ReferencesFragCoords(const Program& program);
Ethan Nicholas6e0fa402020-08-20 14:08:23 -040040
John Stiles9b9415e2020-11-23 14:48:06 -050041 static int NodeCountUpToLimit(const FunctionDefinition& function, int limit);
Ethan Nicholas765d2fe2020-08-26 08:29:55 -040042
Brian Osman010ce6a2020-10-19 16:34:10 -040043 static std::unique_ptr<ProgramUsage> GetUsage(const Program& program);
Brian Osman0006ad02020-11-18 15:38:39 -050044 static std::unique_ptr<ProgramUsage> GetUsage(const LoadedModule& module);
Brian Osman2e25ff42020-10-15 10:32:04 -040045
Ethan Nicholas765d2fe2020-08-26 08:29:55 -040046 static bool StatementWritesToVariable(const Statement& stmt, const Variable& var);
John Stilesa976da72020-09-25 23:06:26 -040047 static bool IsAssignable(Expression& expr, VariableReference** assignableVar,
48 ErrorReporter* errors = nullptr);
John Stilesc30fbca2020-11-19 16:25:49 -050049
50 // A "trivial" expression is one where we'd feel comfortable cloning it multiple times in
51 // the code, without worrying about incurring a performance penalty. Examples:
52 // - true
53 // - 3.14159265
54 // - myIntVariable
55 // - myColor.rgb
56 // - myArray[123]
57 // - myStruct.myField
58 // - half4(0)
59 //
60 // Trivial-ness is stackable. Somewhat large expressions can occasionally make the cut:
61 // - half4(myColor.a)
62 // - myStruct.myArrayField[7].xyz
63 static bool IsTrivialExpression(const Expression& expr);
Michael Ludwig8f3a8362020-06-29 17:27:00 -040064};
65
66/**
67 * Utility class to visit every element, statement, and expression in an SkSL program IR.
68 * This is intended for simple analysis and accumulation, where custom visitation behavior is only
69 * needed for a limited set of expression kinds.
70 *
71 * Subclasses should override visitExpression/visitStatement/visitProgramElement as needed and
72 * intercept elements of interest. They can then invoke the base class's function to visit all
73 * sub expressions. They can also choose not to call the base function to arrest recursion, or
74 * implement custom recursion.
75 *
76 * The visit functions return a bool that determines how the default implementation recurses. Once
77 * any visit call returns true, the default behavior stops recursing and propagates true up the
78 * stack.
79 */
80
John Stiles70b82422020-09-30 10:55:12 -040081template <typename PROG, typename EXPR, typename STMT, typename ELEM>
82class TProgramVisitor {
Michael Ludwig8f3a8362020-06-29 17:27:00 -040083public:
John Stiles70b82422020-09-30 10:55:12 -040084 virtual ~TProgramVisitor() = default;
Michael Ludwig8f3a8362020-06-29 17:27:00 -040085
Michael Ludwig8f3a8362020-06-29 17:27:00 -040086protected:
John Stiles70b82422020-09-30 10:55:12 -040087 virtual bool visitExpression(EXPR expression);
88 virtual bool visitStatement(STMT statement);
89 virtual bool visitProgramElement(ELEM programElement);
Michael Ludwig8f3a8362020-06-29 17:27:00 -040090};
91
John Stiles70b82422020-09-30 10:55:12 -040092// Squelch bogus Clang warning about template vtables: https://bugs.llvm.org/show_bug.cgi?id=18733
93#if defined(__clang__)
94#pragma clang diagnostic push
95#pragma clang diagnostic ignored "-Wweak-template-vtables"
96#endif
97extern template class TProgramVisitor<const Program&, const Expression&,
98 const Statement&, const ProgramElement&>;
99extern template class TProgramVisitor<Program&, Expression&, Statement&, ProgramElement&>;
100#if defined(__clang__)
101#pragma clang diagnostic pop
102#endif
103
Brian Osman133724c2020-10-28 14:14:39 -0400104class ProgramVisitor : public TProgramVisitor<const Program&,
105 const Expression&,
106 const Statement&,
107 const ProgramElement&> {
108public:
109 bool visit(const Program& program);
110};
111
John Stiles70b82422020-09-30 10:55:12 -0400112using ProgramWriter = TProgramVisitor<Program&, Expression&, Statement&, ProgramElement&>;
113
John Stilesa6841be2020-08-06 14:11:56 -0400114} // namespace SkSL
Michael Ludwig8f3a8362020-06-29 17:27:00 -0400115
116#endif