blob: fccfff473bdf23e4e1c249c9a570ef33fba1fbd5 [file] [log] [blame]
Ethan Nicholas762466e2017-06-29 10:03:38 -04001/*
2 * Copyright 2017 Google Inc.
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 SKSL_SECTIONANDPARAMETERHELPER
9#define SKSL_SECTIONANDPARAMETERHELPER
10
11#include "SkSLErrorReporter.h"
12#include "ir/SkSLProgram.h"
13#include "ir/SkSLSection.h"
14#include "ir/SkSLVarDeclarations.h"
15#include <unordered_map>
16#include <vector>
17
18namespace SkSL {
19
20#define CLASS_SECTION "class"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -040021#define CLONE_SECTION "clone"
Ethan Nicholas68990be2017-07-13 09:36:52 -040022#define CONSTRUCTOR_SECTION "constructor"
23#define CONSTRUCTOR_CODE_SECTION "constructorCode"
24#define CONSTRUCTOR_PARAMS_SECTION "constructorParams"
25#define COORD_TRANSFORM_SECTION "coordTransform"
Ethan Nicholas762466e2017-06-29 10:03:38 -040026#define CPP_SECTION "cpp"
Ethan Nicholas9fb036f2017-07-05 16:19:09 -040027#define CPP_END_SECTION "cppEnd"
Ethan Nicholas762466e2017-06-29 10:03:38 -040028#define HEADER_SECTION "header"
Ethan Nicholas9fb036f2017-07-05 16:19:09 -040029#define HEADER_END_SECTION "headerEnd"
Ethan Nicholas762466e2017-06-29 10:03:38 -040030#define EMIT_CODE_SECTION "emitCode"
31#define FIELDS_SECTION "fields"
Ethan Nicholas68990be2017-07-13 09:36:52 -040032#define INITIALIZERS_SECTION "initializers"
Ethan Nicholas762466e2017-06-29 10:03:38 -040033#define MAKE_SECTION "make"
34#define OPTIMIZATION_FLAGS_SECTION "optimizationFlags"
Ethan Nicholas68990be2017-07-13 09:36:52 -040035#define SAMPLER_PARAMS_SECTION "samplerParams"
Ethan Nicholas762466e2017-06-29 10:03:38 -040036#define SET_DATA_SECTION "setData"
37#define TEST_CODE_SECTION "test"
38
39class SectionAndParameterHelper {
40public:
41 SectionAndParameterHelper(const Program& program, ErrorReporter& errors) {
42 for (const auto& p : program.fElements) {
43 switch (p->fKind) {
44 case ProgramElement::kVar_Kind: {
Ethan Nicholas82a62d22017-11-07 14:42:10 +000045 const VarDeclarations* decls = (const VarDeclarations*) p.get();
46 for (const auto& raw : decls->fVars) {
47 const VarDeclaration& decl = (VarDeclaration&) *raw;
48 if (IsParameter(*decl.fVar)) {
49 fParameters.push_back(decl.fVar);
Ethan Nicholas762466e2017-06-29 10:03:38 -040050 }
51 }
52 break;
53 }
54 case ProgramElement::kSection_Kind: {
55 const Section* s = (const Section*) p.get();
56 if (IsSupportedSection(s->fName.c_str())) {
57 if (SectionAcceptsArgument(s->fName.c_str())) {
58 if (!s->fArgument.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070059 errors.error(s->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040060 ("section '@" + s->fName +
61 "' requires one parameter").c_str());
62 }
63 } else if (s->fArgument.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070064 errors.error(s->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040065 ("section '@" + s->fName + "' has no parameters").c_str());
66 }
67 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070068 errors.error(s->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040069 ("unsupported section '@" + s->fName + "'").c_str());
70 }
Ethan Nicholas68990be2017-07-13 09:36:52 -040071 if (!SectionPermitsDuplicates(s->fName.c_str()) &&
72 fSections.find(s->fName) != fSections.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070073 errors.error(s->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040074 ("duplicate section '@" + s->fName + "'").c_str());
75 }
Ethan Nicholas68990be2017-07-13 09:36:52 -040076 fSections[s->fName].push_back(s);
Ethan Nicholas762466e2017-06-29 10:03:38 -040077 break;
78 }
79 default:
80 break;
81 }
82 }
83 }
84
Ethan Nicholas68990be2017-07-13 09:36:52 -040085 const Section* getSection(const char* name) {
86 ASSERT(!SectionPermitsDuplicates(name));
87 auto found = fSections.find(name);
88 if (found == fSections.end()) {
89 return nullptr;
90 }
91 ASSERT(found->second.size() == 1);
92 return found->second[0];
93 }
94
95 std::vector<const Section*> getSections(const char* name) {
96 auto found = fSections.find(name);
97 if (found == fSections.end()) {
98 return std::vector<const Section*>();
99 }
100 return found->second;
101 }
102
103 const std::vector<const Variable*>& getParameters() {
104 return fParameters;
105 }
106
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107 static bool IsParameter(const Variable& var) {
108 return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
109 -1 == var.fModifiers.fLayout.fBuiltin;
110 }
111
112 static bool IsSupportedSection(const char* name) {
113 return !strcmp(name, CLASS_SECTION) ||
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400114 !strcmp(name, CLONE_SECTION) ||
Ethan Nicholas762466e2017-06-29 10:03:38 -0400115 !strcmp(name, CONSTRUCTOR_SECTION) ||
116 !strcmp(name, CONSTRUCTOR_CODE_SECTION) ||
117 !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) ||
Ethan Nicholas68990be2017-07-13 09:36:52 -0400118 !strcmp(name, COORD_TRANSFORM_SECTION) ||
119 !strcmp(name, CPP_SECTION) ||
120 !strcmp(name, CPP_END_SECTION) ||
Ethan Nicholas762466e2017-06-29 10:03:38 -0400121 !strcmp(name, EMIT_CODE_SECTION) ||
122 !strcmp(name, FIELDS_SECTION) ||
Ethan Nicholas68990be2017-07-13 09:36:52 -0400123 !strcmp(name, HEADER_SECTION) ||
124 !strcmp(name, HEADER_END_SECTION) ||
Ethan Nicholas762466e2017-06-29 10:03:38 -0400125 !strcmp(name, INITIALIZERS_SECTION) ||
126 !strcmp(name, MAKE_SECTION) ||
127 !strcmp(name, OPTIMIZATION_FLAGS_SECTION) ||
Ethan Nicholas68990be2017-07-13 09:36:52 -0400128 !strcmp(name, SAMPLER_PARAMS_SECTION) ||
Ethan Nicholas762466e2017-06-29 10:03:38 -0400129 !strcmp(name, SET_DATA_SECTION) ||
130 !strcmp(name, TEST_CODE_SECTION);
131 }
132
133 static bool SectionAcceptsArgument(const char* name) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400134 return !strcmp(name, COORD_TRANSFORM_SECTION) ||
135 !strcmp(name, SAMPLER_PARAMS_SECTION) ||
136 !strcmp(name, SET_DATA_SECTION) ||
Ethan Nicholas762466e2017-06-29 10:03:38 -0400137 !strcmp(name, TEST_CODE_SECTION);
138 }
139
Ethan Nicholas68990be2017-07-13 09:36:52 -0400140 static bool SectionPermitsDuplicates(const char* name) {
141 return !strcmp(name, COORD_TRANSFORM_SECTION) ||
142 !strcmp(name, SAMPLER_PARAMS_SECTION);
143 }
144
145private:
Ethan Nicholas762466e2017-06-29 10:03:38 -0400146 std::vector<const Variable*> fParameters;
Ethan Nicholas68990be2017-07-13 09:36:52 -0400147 std::unordered_map<String, std::vector<const Section*>> fSections;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400148};
149
150} // namespace SkSL
151
152#endif