Home | History | Annotate | Download | only in sksl
      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