blob: c853964fc75332b2961ef6693291ad1a65da20ef [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 Stilesb21fac22020-12-04 15:36:49 -050047
48 struct AssignmentInfo {
49 VariableReference* fAssignedVar = nullptr;
50 bool fIsSwizzled = false;
51 };
52 static bool IsAssignable(Expression& expr, AssignmentInfo* info,
John Stilesa976da72020-09-25 23:06:26 -040053 ErrorReporter* errors = nullptr);
John Stilesc30fbca2020-11-19 16:25:49 -050054
55 // A "trivial" expression is one where we'd feel comfortable cloning it multiple times in
56 // the code, without worrying about incurring a performance penalty. Examples:
57 // - true
58 // - 3.14159265
59 // - myIntVariable
60 // - myColor.rgb
61 // - myArray[123]
62 // - myStruct.myField
63 // - half4(0)
64 //
65 // Trivial-ness is stackable. Somewhat large expressions can occasionally make the cut:
66 // - half4(myColor.a)
67 // - myStruct.myArrayField[7].xyz
68 static bool IsTrivialExpression(const Expression& expr);
Michael Ludwig8f3a8362020-06-29 17:27:00 -040069};
70
71/**
72 * Utility class to visit every element, statement, and expression in an SkSL program IR.
73 * This is intended for simple analysis and accumulation, where custom visitation behavior is only
74 * needed for a limited set of expression kinds.
75 *
76 * Subclasses should override visitExpression/visitStatement/visitProgramElement as needed and
77 * intercept elements of interest. They can then invoke the base class's function to visit all
78 * sub expressions. They can also choose not to call the base function to arrest recursion, or
79 * implement custom recursion.
80 *
81 * The visit functions return a bool that determines how the default implementation recurses. Once
82 * any visit call returns true, the default behavior stops recursing and propagates true up the
83 * stack.
84 */
85
John Stiles70b82422020-09-30 10:55:12 -040086template <typename PROG, typename EXPR, typename STMT, typename ELEM>
87class TProgramVisitor {
Michael Ludwig8f3a8362020-06-29 17:27:00 -040088public:
John Stiles70b82422020-09-30 10:55:12 -040089 virtual ~TProgramVisitor() = default;
Michael Ludwig8f3a8362020-06-29 17:27:00 -040090
Michael Ludwig8f3a8362020-06-29 17:27:00 -040091protected:
John Stiles70b82422020-09-30 10:55:12 -040092 virtual bool visitExpression(EXPR expression);
93 virtual bool visitStatement(STMT statement);
94 virtual bool visitProgramElement(ELEM programElement);
Michael Ludwig8f3a8362020-06-29 17:27:00 -040095};
96
John Stiles70b82422020-09-30 10:55:12 -040097// Squelch bogus Clang warning about template vtables: https://bugs.llvm.org/show_bug.cgi?id=18733
98#if defined(__clang__)
99#pragma clang diagnostic push
100#pragma clang diagnostic ignored "-Wweak-template-vtables"
101#endif
102extern template class TProgramVisitor<const Program&, const Expression&,
103 const Statement&, const ProgramElement&>;
104extern template class TProgramVisitor<Program&, Expression&, Statement&, ProgramElement&>;
105#if defined(__clang__)
106#pragma clang diagnostic pop
107#endif
108
Brian Osman133724c2020-10-28 14:14:39 -0400109class ProgramVisitor : public TProgramVisitor<const Program&,
110 const Expression&,
111 const Statement&,
112 const ProgramElement&> {
113public:
114 bool visit(const Program& program);
115};
116
John Stiles70b82422020-09-30 10:55:12 -0400117using ProgramWriter = TProgramVisitor<Program&, Expression&, Statement&, ProgramElement&>;
118
John Stilesa6841be2020-08-06 14:11:56 -0400119} // namespace SkSL
Michael Ludwig8f3a8362020-06-29 17:27:00 -0400120
121#endif