aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLSectionAndParameterHelper.h
blob: f3242c3967a1eb164f8dc585b29b0135791d6926 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SKSL_SECTIONANDPARAMETERHELPER
#define SKSL_SECTIONANDPARAMETERHELPER

#include "SkSLErrorReporter.h"
#include "ir/SkSLProgram.h"
#include "ir/SkSLSection.h"
#include "ir/SkSLVarDeclarations.h"
#include <unordered_map>
#include <vector>

namespace SkSL {

#define CLASS_SECTION              "class"
#define CPP_SECTION                "cpp"
#define CPP_END_SECTION            "cppEnd"
#define HEADER_SECTION             "header"
#define HEADER_END_SECTION         "headerEnd"
#define CONSTRUCTOR_PARAMS_SECTION "constructorParams"
#define CONSTRUCTOR_SECTION        "constructor"
#define CONSTRUCTOR_CODE_SECTION   "constructorCode"
#define INITIALIZERS_SECTION       "initializers"
#define EMIT_CODE_SECTION          "emitCode"
#define FIELDS_SECTION             "fields"
#define MAKE_SECTION               "make"
#define OPTIMIZATION_FLAGS_SECTION "optimizationFlags"
#define SET_DATA_SECTION           "setData"
#define TEST_CODE_SECTION          "test"

class SectionAndParameterHelper {
public:
    SectionAndParameterHelper(const Program& program, ErrorReporter& errors) {
        for (const auto& p : program.fElements) {
            switch (p->fKind) {
                case ProgramElement::kVar_Kind: {
                    const VarDeclarations* decls = (const VarDeclarations*) p.get();
                    for (const auto& raw : decls->fVars) {
                        const VarDeclaration& decl = (VarDeclaration&) *raw;
                        if (IsParameter(*decl.fVar)) {
                            fParameters.push_back(decl.fVar);
                        }
                    }
                    break;
                }
                case ProgramElement::kSection_Kind: {
                    const Section* s = (const Section*) p.get();
                    if (IsSupportedSection(s->fName.c_str())) {
                        if (SectionAcceptsArgument(s->fName.c_str())) {
                            if (!s->fArgument.size()) {
                                errors.error(s->fPosition,
                                             ("section '@" + s->fName +
                                              "' requires one parameter").c_str());
                            }
                        } else if (s->fArgument.size()) {
                            errors.error(s->fPosition,
                                         ("section '@" + s->fName + "' has no parameters").c_str());
                        }
                    } else {
                        errors.error(s->fPosition,
                                     ("unsupported section '@" + s->fName + "'").c_str());
                    }
                    if (fSections.find(s->fName) != fSections.end()) {
                        errors.error(s->fPosition,
                                     ("duplicate section '@" + s->fName + "'").c_str());
                    }
                    fSections[s->fName] = s;
                    break;
                }
                default:
                    break;
            }
        }
    }

    static bool IsParameter(const Variable& var) {
        return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
               -1 == var.fModifiers.fLayout.fBuiltin;
    }

    static bool IsSupportedSection(const char* name) {
        return !strcmp(name, CLASS_SECTION) ||
               !strcmp(name, CPP_SECTION) ||
               !strcmp(name, CPP_END_SECTION) ||
               !strcmp(name, HEADER_SECTION) ||
               !strcmp(name, HEADER_END_SECTION) ||
               !strcmp(name, CONSTRUCTOR_SECTION) ||
               !strcmp(name, CONSTRUCTOR_CODE_SECTION) ||
               !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) ||
               !strcmp(name, EMIT_CODE_SECTION) ||
               !strcmp(name, FIELDS_SECTION) ||
               !strcmp(name, INITIALIZERS_SECTION) ||
               !strcmp(name, MAKE_SECTION) ||
               !strcmp(name, OPTIMIZATION_FLAGS_SECTION) ||
               !strcmp(name, SET_DATA_SECTION) ||
               !strcmp(name, TEST_CODE_SECTION);
    }

    static bool SectionAcceptsArgument(const char* name) {
        return !strcmp(name, SET_DATA_SECTION) ||
               !strcmp(name, TEST_CODE_SECTION);
    }

    std::vector<const Variable*> fParameters;
    std::unordered_map<String, const Section*> fSections;
};

} // namespace SkSL

#endif