1 /*
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 <algorithm>
12 #include <stack>
13 #include <unordered_map>
14
15 #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/SkSLExternalFunctionCall.h"
27 #include "src/sksl/ir/SkSLExternalValueReference.h"
28 #include "src/sksl/ir/SkSLFieldAccess.h"
29 #include "src/sksl/ir/SkSLFloatLiteral.h"
30 #include "src/sksl/ir/SkSLForStatement.h"
31 #include "src/sksl/ir/SkSLFunctionCall.h"
32 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
33 #include "src/sksl/ir/SkSLFunctionDefinition.h"
34 #include "src/sksl/ir/SkSLIfStatement.h"
35 #include "src/sksl/ir/SkSLIndexExpression.h"
36 #include "src/sksl/ir/SkSLIntLiteral.h"
37 #include "src/sksl/ir/SkSLInterfaceBlock.h"
38 #include "src/sksl/ir/SkSLNullLiteral.h"
39 #include "src/sksl/ir/SkSLPostfixExpression.h"
40 #include "src/sksl/ir/SkSLPrefixExpression.h"
41 #include "src/sksl/ir/SkSLProgramElement.h"
42 #include "src/sksl/ir/SkSLReturnStatement.h"
43 #include "src/sksl/ir/SkSLStatement.h"
44 #include "src/sksl/ir/SkSLSwitchStatement.h"
45 #include "src/sksl/ir/SkSLSwizzle.h"
46 #include "src/sksl/ir/SkSLTernaryExpression.h"
47 #include "src/sksl/ir/SkSLVarDeclarations.h"
48 #include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
49 #include "src/sksl/ir/SkSLVariableReference.h"
50 #include "src/sksl/ir/SkSLWhileStatement.h"
51 #include "src/sksl/spirv.h"
52
53 namespace SkSL {
54
55 class ByteCodeGenerator : public CodeGenerator {
56 public:
57 ByteCodeGenerator(const Program* program, ErrorReporter* errors, ByteCode* output);
58
59 bool generateCode() override;
60
61 private:
62 // Intrinsics which do not simply map to a single opcode
63 enum class SpecialIntrinsic {
64 kDot,
65 kInverse,
66 };
67
68 struct Intrinsic {
IntrinsicIntrinsic69 Intrinsic(ByteCode::Instruction instruction)
70 : fIsSpecial(false)
71 , fValue(instruction) {}
72
IntrinsicIntrinsic73 Intrinsic(SpecialIntrinsic special)
74 : fIsSpecial(true)
75 , fValue(special) {}
76
77 bool fIsSpecial;
78
79 union Value {
Value(ByteCode::Instruction instruction)80 Value(ByteCode::Instruction instruction)
81 : fInstruction(instruction) {}
82
Value(SpecialIntrinsic special)83 Value(SpecialIntrinsic special)
84 : fSpecial(special) {}
85
86 ByteCode::Instruction fInstruction;
87 SpecialIntrinsic fSpecial;
88 } fValue;
89 };
90
91 class LValue {
92 public:
LValue(ByteCodeGenerator & generator)93 LValue(ByteCodeGenerator& generator)
94 : fGenerator(generator) {}
95
~LValue()96 virtual ~LValue() {}
97
98 virtual void load(ByteCode::Register result) = 0;
99
100 virtual void store(ByteCode::Register src) = 0;
101
102 protected:
103 ByteCodeGenerator& fGenerator;
104 };
105
106 struct Location {
107 enum {
108 kPointer_Kind,
109 kRegister_Kind
110 } fKind;
111
112 union {
113 ByteCode::Pointer fPointer;
114 ByteCode::Register fRegister;
115 };
116
LocationLocation117 Location(ByteCode::Pointer p)
118 : fKind(kPointer_Kind)
119 , fPointer(p) {}
120
LocationLocation121 Location(ByteCode::Register r)
122 : fKind(kRegister_Kind)
123 , fRegister(r) {}
124
125 /**
126 * Returns this location offset by 'offset' bytes. For pointers, this is a compile-time
127 * operation, while for registers there will be CPU instructions output to handle the
128 * runtime calculation of the address.
129 */
offsetLocation130 Location offset(ByteCodeGenerator& generator, int offset) {
131 if (!offset) {
132 return *this;
133 }
134 if (fKind == kPointer_Kind) {
135 return Location(fPointer + offset);
136 }
137 ByteCode::Register a = generator.next(1);
138 generator.write(ByteCode::Instruction::kImmediate);
139 generator.write(a);
140 generator.write(ByteCode::Immediate{offset});
141 ByteCode::Register result = generator.next(1);
142 generator.write(ByteCode::Instruction::kAddI);
143 generator.write(result);
144 generator.write(fRegister);
145 generator.write(a);
146 return result;
147 }
148
149 /**
150 * Returns this location offset by the number of bytes stored in the 'offset' register. This
151 * will output the necessary CPU instructions to perform the math and return a new register
152 * location.
153 */
offsetLocation154 Location offset(ByteCodeGenerator& generator, ByteCode::Register offset) {
155 ByteCode::Register current;
156 switch (fKind) {
157 case kPointer_Kind:
158 current = generator.next(1);
159 generator.write(ByteCode::Instruction::kImmediate);
160 generator.write(current);
161 generator.write(ByteCode::Immediate{fPointer.fAddress});
162 break;
163 case kRegister_Kind:
164 current = fRegister;
165 }
166 ByteCode::Register result = generator.next(1);
167 generator.write(ByteCode::Instruction::kAddI);
168 generator.write(result);
169 generator.write(current);
170 generator.write(offset);
171 return result;
172 }
173 };
174
175 // reserves 16 bits in the output code, to be filled in later with an address once we determine
176 // it
177 class DeferredLocation {
178 public:
DeferredLocation(ByteCodeGenerator * generator)179 explicit DeferredLocation(ByteCodeGenerator* generator)
180 : fGenerator(*generator)
181 , fOffset(generator->fCode->size()) {
182 generator->write(ByteCode::Pointer{65535});
183 }
184
set()185 void set() {
186 SkASSERT(fGenerator.fCode->size() <= ByteCode::kPointerMax);
187 static_assert(sizeof(ByteCode::Pointer) == 2,
188 "failed assumption that ByteCode::Pointer is uint16_t");
189 void* dst = &(*fGenerator.fCode)[fOffset];
190 // ensure that the placeholder value 65535 hasn't been modified yet
191 SkASSERT(((uint8_t*) dst)[0] == 255 && ((uint8_t*) dst)[1] == 255);
192 ByteCode::Pointer target{(uint16_t) fGenerator.fCode->size()};
193 memcpy(dst, &target, sizeof(target));
194 }
195
196 private:
197 ByteCodeGenerator& fGenerator;
198 size_t fOffset;
199 };
200
201 template<typename T>
write(T value)202 void write(T value) {
203 size_t n = fCode->size();
204 fCode->resize(n + sizeof(value));
205 memcpy(fCode->data() + n, &value, sizeof(value));
206 }
207
208 ByteCode::Register next(int slotCount);
209
210 void write(ByteCode::Instruction inst, int count);
211
212 /**
213 * Based on 'type', writes the s (signed), u (unsigned), or f (float) instruction.
214 */
215 void writeTypedInstruction(const Type& type, ByteCode::Instruction s, ByteCode::Instruction u,
216 ByteCode::Instruction f);
217
218 ByteCode::Instruction getLoadInstruction(Location location, Variable::Storage storage);
219
220 ByteCode::Instruction getStoreInstruction(Location location, Variable::Storage storage);
221
222 static int SlotCount(const Type& type);
223
224 Location getLocation(const Variable& var);
225
226 Location getLocation(const Expression& expr);
227
228 Variable::Storage getStorage(const Expression& expr);
229
230 std::unique_ptr<LValue> getLValue(const Expression& expr);
231
232 void writeFunction(const FunctionDefinition& f);
233
234 // For compound values, the result argument specifies the first component. Subsequent components
235 // will be in subsequent registers.
236
237 void writeBinaryInstruction(const Type& operandType, ByteCode::Register left,
238 ByteCode::Register right, ByteCode::Instruction s,
239 ByteCode::Instruction u, ByteCode::Instruction f,
240 ByteCode::Register result);
241
242 void writeVectorBinaryInstruction(const Type& operandType, ByteCode::Register left,
243 ByteCode::Register right, ByteCode::Instruction s,
244 ByteCode::Instruction u, ByteCode::Instruction f,
245 ByteCode::Register result);
246
247 void writeBinaryExpression(const BinaryExpression& expr, ByteCode::Register result);
248
249 void writeConstructor(const Constructor& c, ByteCode::Register result);
250
251 void writeExternalFunctionCall(const ExternalFunctionCall& f, ByteCode::Register result);
252
253 void writeExternalValue(const ExternalValueReference& e, ByteCode::Register result);
254
255 void writeIntrinsicCall(const FunctionCall& c, Intrinsic intrinsic, ByteCode::Register result);
256
257 void writeFunctionCall(const FunctionCall& c, ByteCode::Register result);
258
259 void incOrDec(Token::Kind op, Expression& operand, bool prefix, ByteCode::Register result);
260
261 void writePostfixExpression(const PostfixExpression& p, ByteCode::Register result);
262
263 void writePrefixExpression(const PrefixExpression& p, ByteCode::Register result);
264
265 void writeSwizzle(const Swizzle& s, ByteCode::Register result);
266
267 void writeTernaryExpression(const TernaryExpression& t, ByteCode::Register result);
268
269 void writeVariableExpression(const Expression& e, ByteCode::Register result);
270
271 void writeExpression(const Expression& expr, ByteCode::Register result);
272
273 ByteCode::Register writeExpression(const Expression& expr);
274
275 void writeBlock(const Block& b);
276
277 void writeDoStatement(const DoStatement& d);
278
279 void writeForStatement(const ForStatement& f);
280
281 void writeIfStatement(const IfStatement& i);
282
283 void writeReturn(const ReturnStatement& r);
284
285 void writeVarDeclarations(const VarDeclarations& v);
286
287 void writeWhileStatement(const WhileStatement& w);
288
289 void writeStatement(const Statement& s);
290
291 void gatherUniforms(const Type& type, const String& name);
292
293 ByteCode* fOutput;
294
295 int fNextRegister = 0;
296
297 const FunctionDefinition* fFunction;
298
299 std::vector<const FunctionDefinition*> fFunctions;
300
301 std::vector<uint8_t>* fCode;
302
303 std::vector<const Variable*> fLocals;
304
305 int fParameterCount;
306
307 int fConditionCount;
308
309 const std::unordered_map<String, Intrinsic> fIntrinsics;
310
311 friend class DeferredLocation;
312 friend class ByteCodeExternalValueLValue;
313 friend class ByteCodeSimpleLValue;
314 friend class ByteCodeSwizzleLValue;
315
316 typedef CodeGenerator INHERITED;
317 };
318
319 template<>
write(ByteCodeGenerator::Location loc)320 inline void ByteCodeGenerator::write(ByteCodeGenerator::Location loc) {
321 switch (loc.fKind) {
322 case ByteCodeGenerator::Location::kPointer_Kind:
323 this->write(loc.fPointer);
324 break;
325 case ByteCodeGenerator::Location::kRegister_Kind:
326 this->write(loc.fRegister);
327 break;
328 }
329 }
330
331 }
332
333 #endif
334