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" 21 #define CLONE_SECTION "clone" 22 #define CONSTRUCTOR_SECTION "constructor" 23 #define CONSTRUCTOR_CODE_SECTION "constructorCode" 24 #define CONSTRUCTOR_PARAMS_SECTION "constructorParams" 25 #define COORD_TRANSFORM_SECTION "coordTransform" 26 #define CPP_SECTION "cpp" 27 #define CPP_END_SECTION "cppEnd" 28 #define HEADER_SECTION "header" 29 #define HEADER_END_SECTION "headerEnd" 30 #define EMIT_CODE_SECTION "emitCode" 31 #define FIELDS_SECTION "fields" 32 #define INITIALIZERS_SECTION "initializers" 33 #define MAKE_SECTION "make" 34 #define OPTIMIZATION_FLAGS_SECTION "optimizationFlags" 35 #define SAMPLER_PARAMS_SECTION "samplerParams" 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: { 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); 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()) { 59 errors.error(s->fOffset, 60 ("section '@" + s->fName + 61 "' requires one parameter").c_str()); 62 } 63 } else if (s->fArgument.size()) { 64 errors.error(s->fOffset, 65 ("section '@" + s->fName + "' has no parameters").c_str()); 66 } 67 } else { 68 errors.error(s->fOffset, 69 ("unsupported section '@" + s->fName + "'").c_str()); 70 } 71 if (!SectionPermitsDuplicates(s->fName.c_str()) && 72 fSections.find(s->fName) != fSections.end()) { 73 errors.error(s->fOffset, 74 ("duplicate section '@" + s->fName + "'").c_str()); 75 } 76 fSections[s->fName].push_back(s); 77 break; 78 } 79 default: 80 break; 81 } 82 } 83 } 84 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 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) || 114 !strcmp(name, CLONE_SECTION) || 115 !strcmp(name, CONSTRUCTOR_SECTION) || 116 !strcmp(name, CONSTRUCTOR_CODE_SECTION) || 117 !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) || 118 !strcmp(name, COORD_TRANSFORM_SECTION) || 119 !strcmp(name, CPP_SECTION) || 120 !strcmp(name, CPP_END_SECTION) || 121 !strcmp(name, EMIT_CODE_SECTION) || 122 !strcmp(name, FIELDS_SECTION) || 123 !strcmp(name, HEADER_SECTION) || 124 !strcmp(name, HEADER_END_SECTION) || 125 !strcmp(name, INITIALIZERS_SECTION) || 126 !strcmp(name, MAKE_SECTION) || 127 !strcmp(name, OPTIMIZATION_FLAGS_SECTION) || 128 !strcmp(name, SAMPLER_PARAMS_SECTION) || 129 !strcmp(name, SET_DATA_SECTION) || 130 !strcmp(name, TEST_CODE_SECTION); 131 } 132 133 static bool SectionAcceptsArgument(const char* name) { 134 return !strcmp(name, COORD_TRANSFORM_SECTION) || 135 !strcmp(name, SAMPLER_PARAMS_SECTION) || 136 !strcmp(name, SET_DATA_SECTION) || 137 !strcmp(name, TEST_CODE_SECTION); 138 } 139 140 static bool SectionPermitsDuplicates(const char* name) { 141 return !strcmp(name, COORD_TRANSFORM_SECTION) || 142 !strcmp(name, SAMPLER_PARAMS_SECTION); 143 } 144 145 private: 146 std::vector<const Variable*> fParameters; 147 std::unordered_map<String, std::vector<const Section*>> fSections; 148 }; 149 150 } // namespace SkSL 151 152 #endif 153