Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 1 | /* |
| 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 | |
| 18 | namespace SkSL { |
| 19 | |
| 20 | #define CLASS_SECTION "class" |
Ethan Nicholas | f57c0d6 | 2017-07-31 11:18:22 -0400 | [diff] [blame] | 21 | #define CLONE_SECTION "clone" |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 22 | #define CONSTRUCTOR_SECTION "constructor" |
| 23 | #define CONSTRUCTOR_CODE_SECTION "constructorCode" |
| 24 | #define CONSTRUCTOR_PARAMS_SECTION "constructorParams" |
| 25 | #define COORD_TRANSFORM_SECTION "coordTransform" |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 26 | #define CPP_SECTION "cpp" |
Ethan Nicholas | 9fb036f | 2017-07-05 16:19:09 -0400 | [diff] [blame] | 27 | #define CPP_END_SECTION "cppEnd" |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 28 | #define HEADER_SECTION "header" |
Ethan Nicholas | 9fb036f | 2017-07-05 16:19:09 -0400 | [diff] [blame] | 29 | #define HEADER_END_SECTION "headerEnd" |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 30 | #define EMIT_CODE_SECTION "emitCode" |
| 31 | #define FIELDS_SECTION "fields" |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 32 | #define INITIALIZERS_SECTION "initializers" |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 33 | #define MAKE_SECTION "make" |
| 34 | #define OPTIMIZATION_FLAGS_SECTION "optimizationFlags" |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 35 | #define SAMPLER_PARAMS_SECTION "samplerParams" |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 36 | #define SET_DATA_SECTION "setData" |
| 37 | #define TEST_CODE_SECTION "test" |
| 38 | |
| 39 | class SectionAndParameterHelper { |
| 40 | public: |
| 41 | SectionAndParameterHelper(const Program& program, ErrorReporter& errors) { |
| 42 | for (const auto& p : program.fElements) { |
| 43 | switch (p->fKind) { |
| 44 | case ProgramElement::kVar_Kind: { |
Ethan Nicholas | 82a62d2 | 2017-11-07 14:42:10 +0000 | [diff] [blame] | 45 | 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 Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 50 | } |
| 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 Nicholas | 5b5f096 | 2017-09-11 13:50:14 -0700 | [diff] [blame] | 59 | errors.error(s->fOffset, |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 60 | ("section '@" + s->fName + |
| 61 | "' requires one parameter").c_str()); |
| 62 | } |
| 63 | } else if (s->fArgument.size()) { |
Ethan Nicholas | 5b5f096 | 2017-09-11 13:50:14 -0700 | [diff] [blame] | 64 | errors.error(s->fOffset, |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 65 | ("section '@" + s->fName + "' has no parameters").c_str()); |
| 66 | } |
| 67 | } else { |
Ethan Nicholas | 5b5f096 | 2017-09-11 13:50:14 -0700 | [diff] [blame] | 68 | errors.error(s->fOffset, |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 69 | ("unsupported section '@" + s->fName + "'").c_str()); |
| 70 | } |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 71 | if (!SectionPermitsDuplicates(s->fName.c_str()) && |
| 72 | fSections.find(s->fName) != fSections.end()) { |
Ethan Nicholas | 5b5f096 | 2017-09-11 13:50:14 -0700 | [diff] [blame] | 73 | errors.error(s->fOffset, |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 74 | ("duplicate section '@" + s->fName + "'").c_str()); |
| 75 | } |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 76 | fSections[s->fName].push_back(s); |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 77 | break; |
| 78 | } |
| 79 | default: |
| 80 | break; |
| 81 | } |
| 82 | } |
| 83 | } |
| 84 | |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 85 | 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 Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 107 | 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 Nicholas | f57c0d6 | 2017-07-31 11:18:22 -0400 | [diff] [blame] | 114 | !strcmp(name, CLONE_SECTION) || |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 115 | !strcmp(name, CONSTRUCTOR_SECTION) || |
| 116 | !strcmp(name, CONSTRUCTOR_CODE_SECTION) || |
| 117 | !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) || |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 118 | !strcmp(name, COORD_TRANSFORM_SECTION) || |
| 119 | !strcmp(name, CPP_SECTION) || |
| 120 | !strcmp(name, CPP_END_SECTION) || |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 121 | !strcmp(name, EMIT_CODE_SECTION) || |
| 122 | !strcmp(name, FIELDS_SECTION) || |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 123 | !strcmp(name, HEADER_SECTION) || |
| 124 | !strcmp(name, HEADER_END_SECTION) || |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 125 | !strcmp(name, INITIALIZERS_SECTION) || |
| 126 | !strcmp(name, MAKE_SECTION) || |
| 127 | !strcmp(name, OPTIMIZATION_FLAGS_SECTION) || |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 128 | !strcmp(name, SAMPLER_PARAMS_SECTION) || |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 129 | !strcmp(name, SET_DATA_SECTION) || |
| 130 | !strcmp(name, TEST_CODE_SECTION); |
| 131 | } |
| 132 | |
| 133 | static bool SectionAcceptsArgument(const char* name) { |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 134 | return !strcmp(name, COORD_TRANSFORM_SECTION) || |
| 135 | !strcmp(name, SAMPLER_PARAMS_SECTION) || |
| 136 | !strcmp(name, SET_DATA_SECTION) || |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 137 | !strcmp(name, TEST_CODE_SECTION); |
| 138 | } |
| 139 | |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 140 | static bool SectionPermitsDuplicates(const char* name) { |
| 141 | return !strcmp(name, COORD_TRANSFORM_SECTION) || |
| 142 | !strcmp(name, SAMPLER_PARAMS_SECTION); |
| 143 | } |
| 144 | |
| 145 | private: |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 146 | std::vector<const Variable*> fParameters; |
Ethan Nicholas | 68990be | 2017-07-13 09:36:52 -0400 | [diff] [blame] | 147 | std::unordered_map<String, std::vector<const Section*>> fSections; |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 148 | }; |
| 149 | |
| 150 | } // namespace SkSL |
| 151 | |
| 152 | #endif |