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 "src/sksl/SkSLErrorReporter.h" 12 #include "src/sksl/ir/SkSLProgram.h" 13 #include "src/sksl/ir/SkSLSection.h" 14 #include "src/sksl/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: SectionAndParameterHelper(const Program & program,ErrorReporter & errors)41 SectionAndParameterHelper(const Program& program, ErrorReporter& errors) { 42 for (const auto& p : program) { 43 switch (p.fKind) { 44 case ProgramElement::kVar_Kind: { 45 const VarDeclarations& decls = (const VarDeclarations&) p; 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; 56 if (IsSupportedSection(s.fName.c_str())) { 57 if (SectionRequiresArgument(s.fName.c_str()) && !s.fArgument.size()) { 58 errors.error(s.fOffset, 59 ("section '@" + s.fName + 60 "' requires one parameter").c_str()); 61 } 62 if (!SectionAcceptsArgument(s.fName.c_str()) && s.fArgument.size()) { 63 errors.error(s.fOffset, 64 ("section '@" + s.fName + "' has no parameters").c_str()); 65 } 66 } else { 67 errors.error(s.fOffset, 68 ("unsupported section '@" + s.fName + "'").c_str()); 69 } 70 if (!SectionPermitsDuplicates(s.fName.c_str()) && 71 fSections.find(s.fName) != fSections.end()) { 72 errors.error(s.fOffset, 73 ("duplicate section '@" + s.fName + "'").c_str()); 74 } 75 fSections[s.fName].push_back(&s); 76 break; 77 } 78 default: 79 break; 80 } 81 } 82 } 83 getSection(const char * name)84 const Section* getSection(const char* name) { 85 SkASSERT(!SectionPermitsDuplicates(name)); 86 auto found = fSections.find(name); 87 if (found == fSections.end()) { 88 return nullptr; 89 } 90 SkASSERT(found->second.size() == 1); 91 return found->second[0]; 92 } 93 getSections(const char * name)94 std::vector<const Section*> getSections(const char* name) { 95 auto found = fSections.find(name); 96 if (found == fSections.end()) { 97 return std::vector<const Section*>(); 98 } 99 return found->second; 100 } 101 getParameters()102 const std::vector<const Variable*>& getParameters() { 103 return fParameters; 104 } 105 IsParameter(const Variable & var)106 static bool IsParameter(const Variable& var) { 107 return (var.fModifiers.fFlags & Modifiers::kIn_Flag) && 108 -1 == var.fModifiers.fLayout.fBuiltin; 109 } 110 IsSupportedSection(const char * name)111 static bool IsSupportedSection(const char* name) { 112 return !strcmp(name, CLASS_SECTION) || 113 !strcmp(name, CLONE_SECTION) || 114 !strcmp(name, CONSTRUCTOR_SECTION) || 115 !strcmp(name, CONSTRUCTOR_CODE_SECTION) || 116 !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) || 117 !strcmp(name, COORD_TRANSFORM_SECTION) || 118 !strcmp(name, CPP_SECTION) || 119 !strcmp(name, CPP_END_SECTION) || 120 !strcmp(name, EMIT_CODE_SECTION) || 121 !strcmp(name, FIELDS_SECTION) || 122 !strcmp(name, HEADER_SECTION) || 123 !strcmp(name, HEADER_END_SECTION) || 124 !strcmp(name, INITIALIZERS_SECTION) || 125 !strcmp(name, MAKE_SECTION) || 126 !strcmp(name, OPTIMIZATION_FLAGS_SECTION) || 127 !strcmp(name, SAMPLER_PARAMS_SECTION) || 128 !strcmp(name, SET_DATA_SECTION) || 129 !strcmp(name, TEST_CODE_SECTION); 130 } 131 SectionAcceptsArgument(const char * name)132 static bool SectionAcceptsArgument(const char* name) { 133 return !strcmp(name, COORD_TRANSFORM_SECTION) || 134 !strcmp(name, SAMPLER_PARAMS_SECTION) || 135 !strcmp(name, SET_DATA_SECTION) || 136 !strcmp(name, TEST_CODE_SECTION); 137 } 138 SectionRequiresArgument(const char * name)139 static bool SectionRequiresArgument(const char* name) { 140 return !strcmp(name, SAMPLER_PARAMS_SECTION) || 141 !strcmp(name, SET_DATA_SECTION) || 142 !strcmp(name, TEST_CODE_SECTION); 143 } 144 SectionPermitsDuplicates(const char * name)145 static bool SectionPermitsDuplicates(const char* name) { 146 return !strcmp(name, COORD_TRANSFORM_SECTION) || 147 !strcmp(name, SAMPLER_PARAMS_SECTION); 148 } 149 150 private: 151 std::vector<const Variable*> fParameters; 152 std::unordered_map<String, std::vector<const Section*>> fSections; 153 }; 154 155 } // namespace SkSL 156 157 #endif 158