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 CONSTRUCTOR_SECTION "constructor" 22 #define CONSTRUCTOR_CODE_SECTION "constructorCode" 23 #define CONSTRUCTOR_PARAMS_SECTION "constructorParams" 24 #define COORD_TRANSFORM_SECTION "coordTransform" 25 #define CPP_SECTION "cpp" 26 #define CPP_END_SECTION "cppEnd" 27 #define HEADER_SECTION "header" 28 #define HEADER_END_SECTION "headerEnd" 29 #define EMIT_CODE_SECTION "emitCode" 30 #define FIELDS_SECTION "fields" 31 #define INITIALIZERS_SECTION "initializers" 32 #define MAKE_SECTION "make" 33 #define OPTIMIZATION_FLAGS_SECTION "optimizationFlags" 34 #define SAMPLER_PARAMS_SECTION "samplerParams" 35 #define SET_DATA_SECTION "setData" 36 #define TEST_CODE_SECTION "test" 37 38 class SectionAndParameterHelper { 39 public: SectionAndParameterHelper(const Program & program,ErrorReporter & errors)40 SectionAndParameterHelper(const Program& program, ErrorReporter& errors) { 41 for (const auto& p : program.fElements) { 42 switch (p->fKind) { 43 case ProgramElement::kVar_Kind: { 44 const VarDeclarations* decls = (const VarDeclarations*) p.get(); 45 for (const auto& raw : decls->fVars) { 46 const VarDeclaration& decl = (VarDeclaration&) *raw; 47 if (IsParameter(*decl.fVar)) { 48 fParameters.push_back(decl.fVar); 49 } 50 } 51 break; 52 } 53 case ProgramElement::kSection_Kind: { 54 const Section* s = (const Section*) p.get(); 55 if (IsSupportedSection(s->fName.c_str())) { 56 if (SectionAcceptsArgument(s->fName.c_str())) { 57 if (!s->fArgument.size()) { 58 errors.error(s->fPosition, 59 ("section '@" + s->fName + 60 "' requires one parameter").c_str()); 61 } 62 } else if (s->fArgument.size()) { 63 errors.error(s->fPosition, 64 ("section '@" + s->fName + "' has no parameters").c_str()); 65 } 66 } else { 67 errors.error(s->fPosition, 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->fPosition, 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 ASSERT(!SectionPermitsDuplicates(name)); 86 auto found = fSections.find(name); 87 if (found == fSections.end()) { 88 return nullptr; 89 } 90 ASSERT(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, CONSTRUCTOR_SECTION) || 114 !strcmp(name, CONSTRUCTOR_CODE_SECTION) || 115 !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) || 116 !strcmp(name, COORD_TRANSFORM_SECTION) || 117 !strcmp(name, CPP_SECTION) || 118 !strcmp(name, CPP_END_SECTION) || 119 !strcmp(name, EMIT_CODE_SECTION) || 120 !strcmp(name, FIELDS_SECTION) || 121 !strcmp(name, HEADER_SECTION) || 122 !strcmp(name, HEADER_END_SECTION) || 123 !strcmp(name, INITIALIZERS_SECTION) || 124 !strcmp(name, MAKE_SECTION) || 125 !strcmp(name, OPTIMIZATION_FLAGS_SECTION) || 126 !strcmp(name, SAMPLER_PARAMS_SECTION) || 127 !strcmp(name, SET_DATA_SECTION) || 128 !strcmp(name, TEST_CODE_SECTION); 129 } 130 SectionAcceptsArgument(const char * name)131 static bool SectionAcceptsArgument(const char* name) { 132 return !strcmp(name, COORD_TRANSFORM_SECTION) || 133 !strcmp(name, SAMPLER_PARAMS_SECTION) || 134 !strcmp(name, SET_DATA_SECTION) || 135 !strcmp(name, TEST_CODE_SECTION); 136 } 137 SectionPermitsDuplicates(const char * name)138 static bool SectionPermitsDuplicates(const char* name) { 139 return !strcmp(name, COORD_TRANSFORM_SECTION) || 140 !strcmp(name, SAMPLER_PARAMS_SECTION); 141 } 142 143 private: 144 std::vector<const Variable*> fParameters; 145 std::unordered_map<String, std::vector<const Section*>> fSections; 146 }; 147 148 } // namespace SkSL 149 150 #endif 151