aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLCompiler.h
blob: c840bd800fdf024f7ddc389bbacbb3016988eee9 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SKSL_COMPILER
#define SKSL_COMPILER

#include <set>
#include <unordered_set>
#include <vector>
#include "ir/SkSLProgram.h"
#include "ir/SkSLSymbolTable.h"
#include "SkSLCFGGenerator.h"
#include "SkSLContext.h"
#include "SkSLErrorReporter.h"
#include "SkSLLexer.h"

#define SK_FRAGCOLOR_BUILTIN           10001
#define SK_IN_BUILTIN                  10002
#define SK_INCOLOR_BUILTIN             10003
#define SK_OUTCOLOR_BUILTIN            10004
#define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005
#define SK_TEXTURESAMPLERS_BUILTIN     10006
#define SK_OUT_BUILTIN                 10007
#define SK_LASTFRAGCOLOR_BUILTIN       10008
#define SK_FRAGCOORD_BUILTIN              15
#define SK_CLOCKWISE_BUILTIN              17
#define SK_VERTEXID_BUILTIN               42
#define SK_INSTANCEID_BUILTIN             43
#define SK_CLIPDISTANCE_BUILTIN            3
#define SK_INVOCATIONID_BUILTIN            8
#define SK_POSITION_BUILTIN                0

namespace SkSL {

class IRGenerator;

/**
 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
 * compiled output.
 *
 * See the README for information about SkSL.
 */
class Compiler : public ErrorReporter {
public:
    static constexpr const char* RTADJUST_NAME  = "sk_RTAdjust";
    static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";

    enum Flags {
        kNone_Flags = 0,
        // permits static if/switch statements to be used with non-constant tests. This is used when
        // producing H and CPP code; the static tests don't have to have constant values *yet*, but
        // the generated code will contain a static test which then does have to be a constant.
        kPermitInvalidStaticTests_Flag = 1,
    };

    Compiler(Flags flags = kNone_Flags);

    ~Compiler() override;

    std::unique_ptr<Program> convertProgram(Program::Kind kind, String text,
                                            const Program::Settings& settings);

    bool toSPIRV(const Program& program, OutputStream& out);

    bool toSPIRV(const Program& program, String* out);

    bool toGLSL(const Program& program, OutputStream& out);

    bool toGLSL(const Program& program, String* out);

    bool toMetal(const Program& program, OutputStream& out);

    bool toMetal(const Program& program, String* out);

    bool toCPP(const Program& program, String name, OutputStream& out);

    bool toH(const Program& program, String name, OutputStream& out);

    void error(int offset, String msg) override;

    String errorText();

    void writeErrorCount();

    int errorCount() override {
        return fErrorCount;
    }

    Context& context() {
        return *fContext;
    }

    static const char* OperatorName(Token::Kind token);

    static bool IsAssignment(Token::Kind token);

private:
    void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
                       DefinitionMap* definitions);

    void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);

    void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList);

    void computeDataFlow(CFG* cfg);

    /**
     * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if
     * possible.
     */
    void simplifyExpression(DefinitionMap& definitions,
                            BasicBlock& b,
                            std::vector<BasicBlock::Node>::iterator* iter,
                            std::unordered_set<const Variable*>* undefinedVariables,
                            bool* outUpdated,
                            bool* outNeedsRescan);

    /**
     * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if
     * possible.
     */
    void simplifyStatement(DefinitionMap& definitions,
                           BasicBlock& b,
                           std::vector<BasicBlock::Node>::iterator* iter,
                           std::unordered_set<const Variable*>* undefinedVariables,
                           bool* outUpdated,
                           bool* outNeedsRescan);

    void scanCFG(FunctionDefinition& f);

    Position position(int offset);

    std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
    std::shared_ptr<SymbolTable> fVertexSymbolTable;
    std::vector<std::unique_ptr<ProgramElement>> fFragmentInclude;
    std::shared_ptr<SymbolTable> fFragmentSymbolTable;
    std::vector<std::unique_ptr<ProgramElement>> fGeometryInclude;
    std::shared_ptr<SymbolTable> fGeometrySymbolTable;

    std::shared_ptr<SymbolTable> fTypes;
    IRGenerator* fIRGenerator;
    int fFlags;

    const String* fSource;
    std::shared_ptr<Context> fContext;
    int fErrorCount;
    String fErrorText;
};

} // namespace

#endif