aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLCompiler.h
blob: eb2fc45b5161532ccdf1fe04fdae4ad0e65367a8 (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
/*
 * 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_FRAGCOORD_BUILTIN              15
#define SK_VERTEXID_BUILTIN                5
#define SK_INSTANCEID_BUILTIN              6
#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 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;
    }

    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::shared_ptr<SymbolTable> fTypes;
    IRGenerator* fIRGenerator;
    String fSkiaVertText; // FIXME store parsed version instead
    int fFlags;

    const String* fSource;
    Context fContext;
    int fErrorCount;
    String fErrorText;
};

} // namespace

#endif