blob: 572e32ba7acfd1e373d877778fc4ec79f4137ec0 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/SkSLByteCode.h"
16#include "src/sksl/SkSLCodeGenerator.h"
17#include "src/sksl/SkSLMemoryLayout.h"
18#include "src/sksl/ir/SkSLBinaryExpression.h"
19#include "src/sksl/ir/SkSLBlock.h"
20#include "src/sksl/ir/SkSLBoolLiteral.h"
21#include "src/sksl/ir/SkSLBreakStatement.h"
22#include "src/sksl/ir/SkSLConstructor.h"
23#include "src/sksl/ir/SkSLContinueStatement.h"
24#include "src/sksl/ir/SkSLDoStatement.h"
25#include "src/sksl/ir/SkSLExpressionStatement.h"
26#include "src/sksl/ir/SkSLFieldAccess.h"
27#include "src/sksl/ir/SkSLFloatLiteral.h"
28#include "src/sksl/ir/SkSLForStatement.h"
29#include "src/sksl/ir/SkSLFunctionCall.h"
30#include "src/sksl/ir/SkSLFunctionDeclaration.h"
31#include "src/sksl/ir/SkSLFunctionDefinition.h"
32#include "src/sksl/ir/SkSLIfStatement.h"
33#include "src/sksl/ir/SkSLIndexExpression.h"
34#include "src/sksl/ir/SkSLIntLiteral.h"
35#include "src/sksl/ir/SkSLInterfaceBlock.h"
36#include "src/sksl/ir/SkSLNullLiteral.h"
37#include "src/sksl/ir/SkSLPostfixExpression.h"
38#include "src/sksl/ir/SkSLPrefixExpression.h"
39#include "src/sksl/ir/SkSLProgramElement.h"
40#include "src/sksl/ir/SkSLReturnStatement.h"
41#include "src/sksl/ir/SkSLStatement.h"
42#include "src/sksl/ir/SkSLSwitchStatement.h"
43#include "src/sksl/ir/SkSLSwizzle.h"
44#include "src/sksl/ir/SkSLTernaryExpression.h"
45#include "src/sksl/ir/SkSLVarDeclarations.h"
46#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
47#include "src/sksl/ir/SkSLVariableReference.h"
48#include "src/sksl/ir/SkSLWhileStatement.h"
49#include "src/sksl/spirv.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040050
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
Ethan Nicholas9764ebd2019-05-01 14:43:54 -040086 void align(int divisor, int remainder);
87
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040088 void write8(uint8_t b);
89
90 void write16(uint16_t b);
91
92 void write32(uint32_t b);
93
94 void write(ByteCodeInstruction inst);
95
96 /**
97 * Based on 'type', writes the s (signed), u (unsigned), or f (float) instruction.
98 */
99 void writeTypedInstruction(const Type& type, ByteCodeInstruction s, ByteCodeInstruction u,
100 ByteCodeInstruction f);
101
102 /**
103 * Pushes the storage location of an lvalue to the stack.
104 */
105 void writeTarget(const Expression& expr);
106
107private:
108 // reserves 16 bits in the output code, to be filled in later with an address once we determine
109 // it
110 class DeferredLocation {
111 public:
112 DeferredLocation(ByteCodeGenerator* generator)
113 : fGenerator(*generator)
114 , fOffset(generator->fCode->size()) {
115 generator->write16(0);
116 }
117
118#ifdef SK_DEBUG
119 ~DeferredLocation() {
120 SkASSERT(fSet);
121 }
122#endif
123
124 void set() {
125 int target = fGenerator.fCode->size();
126 SkASSERT(target <= 65535);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400127 (*fGenerator.fCode)[fOffset] = target;
128 (*fGenerator.fCode)[fOffset + 1] = target >> 8;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400129#ifdef SK_DEBUG
130 fSet = true;
131#endif
132 }
133
134 private:
135 ByteCodeGenerator& fGenerator;
136 size_t fOffset;
137#ifdef SK_DEBUG
138 bool fSet = false;
139#endif
140 };
141
Brian Osman226668a2019-05-14 16:47:30 -0400142 class DeferredCallTarget {
143 public:
144 DeferredCallTarget(ByteCodeGenerator* generator, const FunctionDeclaration& function)
145 : fGenerator(*generator)
146 , fCode(generator->fCode)
147 , fOffset(generator->fCode->size())
148 , fFunction(function) {
149 generator->write8(0);
150 }
151
152 bool set() {
153 size_t idx;
154 const auto& functions(fGenerator.fOutput->fFunctions);
155 for (idx = 0; idx < functions.size(); ++idx) {
156 if (fFunction.matches(functions[idx]->fDeclaration)) {
157 break;
158 }
159 }
160 if (idx > 255 || idx > functions.size()) {
161 SkASSERT(false);
162 return false;
163 }
164 (*fCode)[fOffset] = idx;
165 return true;
166 }
167
168 private:
169 ByteCodeGenerator& fGenerator;
170 std::vector<uint8_t>* fCode;
171 size_t fOffset;
172 const FunctionDeclaration& fFunction;
173 };
174
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400175 /**
176 * Returns the local slot into which var should be stored, allocating a new slot if it has not
177 * already been assigned one. Compound variables (e.g. vectors) will consume more than one local
178 * slot, with the getLocation return value indicating where the first element should be stored.
179 */
180 int getLocation(const Variable& var);
181
182 std::unique_ptr<ByteCodeFunction> writeFunction(const FunctionDefinition& f);
183
184 void writeVarDeclarations(const VarDeclarations& decl);
185
186 void writeVariableReference(const VariableReference& ref);
187
188 void writeExpression(const Expression& expr);
189
190 /**
191 * Pushes whatever values are required by the lvalue onto the stack, and returns an LValue
192 * permitting loads and stores to it.
193 */
194 std::unique_ptr<LValue> getLValue(const Expression& expr);
195
196 void writeFunctionCall(const FunctionCall& c);
197
198 void writeConstructor(const Constructor& c);
199
200 void writeFieldAccess(const FieldAccess& f);
201
202 void writeSwizzle(const Swizzle& swizzle);
203
204 void writeBinaryExpression(const BinaryExpression& b);
205
206 void writeTernaryExpression(const TernaryExpression& t);
207
208 void writeIndexExpression(const IndexExpression& expr);
209
210 void writeLogicalAnd(const BinaryExpression& b);
211
212 void writeLogicalOr(const BinaryExpression& o);
213
214 void writeNullLiteral(const NullLiteral& n);
215
216 void writePrefixExpression(const PrefixExpression& p);
217
218 void writePostfixExpression(const PostfixExpression& p);
219
220 void writeBoolLiteral(const BoolLiteral& b);
221
222 void writeIntLiteral(const IntLiteral& i);
223
224 void writeFloatLiteral(const FloatLiteral& f);
225
226 void writeStatement(const Statement& s);
227
228 void writeBlock(const Block& b);
229
230 void writeBreakStatement(const BreakStatement& b);
231
232 void writeContinueStatement(const ContinueStatement& c);
233
234 void writeIfStatement(const IfStatement& stmt);
235
236 void writeForStatement(const ForStatement& f);
237
238 void writeWhileStatement(const WhileStatement& w);
239
240 void writeDoStatement(const DoStatement& d);
241
242 void writeSwitchStatement(const SwitchStatement& s);
243
244 void writeReturnStatement(const ReturnStatement& r);
245
246 // updates the current set of breaks to branch to the current location
247 void setBreakTargets();
248
249 // updates the current set of continues to branch to the current location
250 void setContinueTargets();
251
252 const Context& fContext;
253
254 ByteCode* fOutput;
255
256 const FunctionDefinition* fFunction;
257
258 std::vector<uint8_t>* fCode;
259
260 std::vector<const Variable*> fLocals;
261
262 std::stack<std::vector<DeferredLocation>> fContinueTargets;
263
264 std::stack<std::vector<DeferredLocation>> fBreakTargets;
265
Brian Osman226668a2019-05-14 16:47:30 -0400266 std::vector<DeferredCallTarget> fCallTargets;
267
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400268 int fParameterCount;
269
270 friend class DeferredLocation;
271 friend class ByteCodeVariableLValue;
272
273 typedef CodeGenerator INHERITED;
274};
275
276}
277
278#endif