blob: e518861488f49e84881bfe930b850f906772fe8f [file] [log] [blame]
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001/*
2 * Copyright 2019 Google LLC
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_BYTECODEGENERATOR
9#define SKSL_BYTECODEGENERATOR
10
11#include <stack>
12#include <tuple>
13#include <unordered_map>
14
15#include "SkSLByteCode.h"
16#include "SkSLCodeGenerator.h"
17#include "SkSLMemoryLayout.h"
18#include "ir/SkSLBinaryExpression.h"
19#include "ir/SkSLBoolLiteral.h"
20#include "ir/SkSLBlock.h"
21#include "ir/SkSLBreakStatement.h"
22#include "ir/SkSLConstructor.h"
23#include "ir/SkSLContinueStatement.h"
24#include "ir/SkSLDoStatement.h"
25#include "ir/SkSLExpressionStatement.h"
26#include "ir/SkSLFloatLiteral.h"
27#include "ir/SkSLIfStatement.h"
28#include "ir/SkSLIndexExpression.h"
29#include "ir/SkSLInterfaceBlock.h"
30#include "ir/SkSLIntLiteral.h"
31#include "ir/SkSLFieldAccess.h"
32#include "ir/SkSLForStatement.h"
33#include "ir/SkSLFunctionCall.h"
34#include "ir/SkSLFunctionDeclaration.h"
35#include "ir/SkSLFunctionDefinition.h"
36#include "ir/SkSLNullLiteral.h"
37#include "ir/SkSLPrefixExpression.h"
38#include "ir/SkSLPostfixExpression.h"
39#include "ir/SkSLProgramElement.h"
40#include "ir/SkSLReturnStatement.h"
41#include "ir/SkSLStatement.h"
42#include "ir/SkSLSwitchStatement.h"
43#include "ir/SkSLSwizzle.h"
44#include "ir/SkSLTernaryExpression.h"
45#include "ir/SkSLVarDeclarations.h"
46#include "ir/SkSLVarDeclarationsStatement.h"
47#include "ir/SkSLVariableReference.h"
48#include "ir/SkSLWhileStatement.h"
49#include "spirv.h"
50
51namespace SkSL {
52
53class ByteCodeGenerator : public CodeGenerator {
54public:
55 class LValue {
56 public:
57 LValue(ByteCodeGenerator& generator)
58 : fGenerator(generator) {}
59
60 virtual ~LValue() {}
61
62 /**
63 * Stack before call: ... lvalue
64 * Stack after call: ... lvalue load
65 */
66 virtual void load() = 0;
67
68 /**
69 * Stack before call: ... lvalue value
70 * Stack after call: ...
71 */
72 virtual void store() = 0;
73
74 protected:
75 ByteCodeGenerator& fGenerator;
76 };
77
78 ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
79 ByteCode* output)
80 : INHERITED(program, errors, nullptr)
81 , fContext(*context)
82 , fOutput(output) {}
83
84 bool generateCode() override;
85
86 void write8(uint8_t b);
87
88 void write16(uint16_t b);
89
90 void write32(uint32_t b);
91
92 void write(ByteCodeInstruction inst);
93
94 /**
95 * Based on 'type', writes the s (signed), u (unsigned), or f (float) instruction.
96 */
97 void writeTypedInstruction(const Type& type, ByteCodeInstruction s, ByteCodeInstruction u,
98 ByteCodeInstruction f);
99
100 /**
101 * Pushes the storage location of an lvalue to the stack.
102 */
103 void writeTarget(const Expression& expr);
104
105private:
106 // reserves 16 bits in the output code, to be filled in later with an address once we determine
107 // it
108 class DeferredLocation {
109 public:
110 DeferredLocation(ByteCodeGenerator* generator)
111 : fGenerator(*generator)
112 , fOffset(generator->fCode->size()) {
113 generator->write16(0);
114 }
115
116#ifdef SK_DEBUG
117 ~DeferredLocation() {
118 SkASSERT(fSet);
119 }
120#endif
121
122 void set() {
123 int target = fGenerator.fCode->size();
124 SkASSERT(target <= 65535);
125 (*fGenerator.fCode)[fOffset] = target >> 8;
126 (*fGenerator.fCode)[fOffset + 1] = target;
127#ifdef SK_DEBUG
128 fSet = true;
129#endif
130 }
131
132 private:
133 ByteCodeGenerator& fGenerator;
134 size_t fOffset;
135#ifdef SK_DEBUG
136 bool fSet = false;
137#endif
138 };
139
140 /**
141 * Returns the local slot into which var should be stored, allocating a new slot if it has not
142 * already been assigned one. Compound variables (e.g. vectors) will consume more than one local
143 * slot, with the getLocation return value indicating where the first element should be stored.
144 */
145 int getLocation(const Variable& var);
146
147 std::unique_ptr<ByteCodeFunction> writeFunction(const FunctionDefinition& f);
148
149 void writeVarDeclarations(const VarDeclarations& decl);
150
151 void writeVariableReference(const VariableReference& ref);
152
153 void writeExpression(const Expression& expr);
154
155 /**
156 * Pushes whatever values are required by the lvalue onto the stack, and returns an LValue
157 * permitting loads and stores to it.
158 */
159 std::unique_ptr<LValue> getLValue(const Expression& expr);
160
161 void writeFunctionCall(const FunctionCall& c);
162
163 void writeConstructor(const Constructor& c);
164
165 void writeFieldAccess(const FieldAccess& f);
166
167 void writeSwizzle(const Swizzle& swizzle);
168
169 void writeBinaryExpression(const BinaryExpression& b);
170
171 void writeTernaryExpression(const TernaryExpression& t);
172
173 void writeIndexExpression(const IndexExpression& expr);
174
175 void writeLogicalAnd(const BinaryExpression& b);
176
177 void writeLogicalOr(const BinaryExpression& o);
178
179 void writeNullLiteral(const NullLiteral& n);
180
181 void writePrefixExpression(const PrefixExpression& p);
182
183 void writePostfixExpression(const PostfixExpression& p);
184
185 void writeBoolLiteral(const BoolLiteral& b);
186
187 void writeIntLiteral(const IntLiteral& i);
188
189 void writeFloatLiteral(const FloatLiteral& f);
190
191 void writeStatement(const Statement& s);
192
193 void writeBlock(const Block& b);
194
195 void writeBreakStatement(const BreakStatement& b);
196
197 void writeContinueStatement(const ContinueStatement& c);
198
199 void writeIfStatement(const IfStatement& stmt);
200
201 void writeForStatement(const ForStatement& f);
202
203 void writeWhileStatement(const WhileStatement& w);
204
205 void writeDoStatement(const DoStatement& d);
206
207 void writeSwitchStatement(const SwitchStatement& s);
208
209 void writeReturnStatement(const ReturnStatement& r);
210
211 // updates the current set of breaks to branch to the current location
212 void setBreakTargets();
213
214 // updates the current set of continues to branch to the current location
215 void setContinueTargets();
216
217 const Context& fContext;
218
219 ByteCode* fOutput;
220
221 const FunctionDefinition* fFunction;
222
223 std::vector<uint8_t>* fCode;
224
225 std::vector<const Variable*> fLocals;
226
227 std::stack<std::vector<DeferredLocation>> fContinueTargets;
228
229 std::stack<std::vector<DeferredLocation>> fBreakTargets;
230
231 int fParameterCount;
232
233 friend class DeferredLocation;
234 friend class ByteCodeVariableLValue;
235
236 typedef CodeGenerator INHERITED;
237};
238
239}
240
241#endif