blob: 90a9dbb2835fc2c9fa5a19244c1b4f35fdac08c4 [file] [log] [blame]
Brian Osmanb380e712019-07-24 17:02:39 -04001/*
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04002 * 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
10namespace SkSL {
11
Ethan Nicholasb962eff2020-01-23 16:49:41 -050012ByteCodeGenerator::ByteCodeGenerator(const Program* program, ErrorReporter* errors,
13 ByteCode* output)
Ethan Nicholas82162ee2019-05-21 16:05:08 -040014 : INHERITED(program, errors, nullptr)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040015 , fOutput(output)
16 , fIntrinsics {
Ethan Nicholasb962eff2020-01-23 16:49:41 -050017 { "cos", ByteCode::Instruction::kCos },
Brian Osman886af0d2019-07-26 15:12:56 -040018 { "dot", SpecialIntrinsic::kDot },
Ethan Nicholasb962eff2020-01-23 16:49:41 -050019 { "inverse", SpecialIntrinsic::kInverse },
20 { "print", ByteCode::Instruction::kPrint },
21 { "sin", ByteCode::Instruction::kSin },
22 { "sqrt", ByteCode::Instruction::kSqrt },
23 { "tan", ByteCode::Instruction::kTan },
24 } {}
Ethan Nicholas82162ee2019-05-21 16:05:08 -040025
Brian Osman07c117b2019-05-23 12:51:06 -070026int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040027 if (type.kind() == Type::kOther_Kind) {
28 return 0;
29 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070030 int slots = 0;
31 for (const auto& f : type.fields()) {
32 slots += SlotCount(*f.fType);
33 }
34 SkASSERT(slots <= 255);
35 return slots;
36 } else if (type.kind() == Type::kArray_Kind) {
37 int columns = type.columns();
38 SkASSERT(columns >= 0);
39 int slots = columns * SlotCount(type.componentType());
40 SkASSERT(slots <= 255);
41 return slots;
42 } else {
43 return type.columns() * type.rows();
44 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040045}
46
Brian Osman1c110a02019-10-01 14:53:32 -040047static inline bool is_uniform(const SkSL::Variable& var) {
48 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
49}
50
Brian Osmaneadfeb92020-01-09 12:43:03 -050051static inline bool is_in(const SkSL::Variable& var) {
52 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
53}
Ethan Nicholasb962eff2020-01-23 16:49:41 -050054ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
55 // given that we seldom have more than a couple of variables, linear search is probably the most
56 // efficient way to handle lookups
57 switch (var.fStorage) {
58 case Variable::kLocal_Storage: {
59 for (int i = fLocals.size() - 1; i >= 0; --i) {
60 if (fLocals[i] == &var) {
61 return ByteCode::Pointer{(uint16_t) (i + fParameterCount)};
Ben Wagner470e0ac2020-01-22 16:59:21 -050062 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -050063 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -050064 int result = fLocals.size() + fParameterCount;
65 fLocals.push_back(&var);
66 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
67 fLocals.push_back(nullptr);
68 }
69 SkASSERT(result <= ByteCode::kPointerMax);
70 return ByteCode::Pointer{(uint16_t) result};
71 }
72 case Variable::kParameter_Storage: {
73 int offset = 0;
74 for (const auto& p : fFunction->fDeclaration.fParameters) {
75 if (p == &var) {
76 SkASSERT(offset <= ByteCode::kPointerMax);
77 return ByteCode::Pointer{(uint16_t) offset};
78 }
79 offset += SlotCount(p->fType);
80 }
81 SkASSERT(false);
82 return ByteCode::Pointer{0};
83 }
84 case Variable::kGlobal_Storage: {
85 if (is_in(var)) {
86 // If you trip this assert, it means the program is using raw 'in' variables. You
87 // should either specialize the program (Compiler::specialize) to bake in the final
88 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
89 // 'uniform' instead?).
90 SkASSERT(false);
91 return ByteCode::Pointer{0};
92 }
93 bool isUniform = is_uniform(var);
94 int offset = isUniform ? fOutput->getGlobalSlotCount() : 0;
95 for (const auto& e : fProgram) {
96 if (e.fKind == ProgramElement::kVar_Kind) {
97 VarDeclarations& decl = (VarDeclarations&) e;
98 for (const auto& v : decl.fVars) {
99 const Variable* declVar = ((VarDeclaration&) *v).fVar;
100 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
101 continue;
102 }
103 if (isUniform != is_uniform(*declVar)) {
104 continue;
105 }
106 if (declVar == &var) {
107 SkASSERT(offset <= ByteCode::kPointerMax);
108 return ByteCode::Pointer{(uint16_t) offset};
109 }
110 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400111 }
112 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400113 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500114 SkASSERT(false);
115 return ByteCode::Pointer{0};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400116 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500117 default:
118 SkASSERT(false);
119 return ByteCode::Pointer{0};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400120 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400121}
122
Brian Osman0785db02019-05-24 14:19:11 -0400123// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
124// that references consecutive values, such that it can be implemented using normal load/store ops
125// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
126static bool swizzle_is_simple(const Swizzle& s) {
127 switch (s.fBase->fKind) {
128 case Expression::kFieldAccess_Kind:
129 case Expression::kIndex_Kind:
130 case Expression::kVariableReference_Kind:
131 break;
132 default:
133 return false;
134 }
135
136 for (size_t i = 1; i < s.fComponents.size(); ++i) {
137 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
138 return false;
139 }
140 }
141 return true;
142}
143
Brian Osman1c110a02019-10-01 14:53:32 -0400144ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700145 switch (expr.fKind) {
146 case Expression::kFieldAccess_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500147 const FieldAccess& f = (const FieldAccess&) expr;
148 Location result = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700149 int offset = 0;
150 for (int i = 0; i < f.fFieldIndex; ++i) {
151 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
152 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500153 return result.offset(*this, offset);
Ethan Nicholas99c54f02020-01-21 16:06:47 +0000154 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500155 case Expression::kIndex_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500156 const IndexExpression& idx = (const IndexExpression&) expr;
157 int stride = SlotCount(idx.fType);
158 int length = idx.fBase->fType.columns();
159 Location result = this->getLocation(*idx.fBase);
160 if (idx.fIndex->isConstant()) {
161 int64_t index = idx.fIndex->getConstantInt();
Ben Wagner470e0ac2020-01-22 16:59:21 -0500162 if (index < 0 || index >= length) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500163 fErrors.error(idx.fIndex->fOffset, "Array index out of bounds");
164 return result;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500165 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500166 return result.offset(*this, index * stride);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500167 } else {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500168 ByteCode::Register index = this->next(1);
169 this->writeExpression(*idx.fIndex, index);
170 this->write(ByteCode::Instruction::kBoundsCheck);
171 this->write(index);
172 this->write(length);
173 ByteCode::Register imm = this->next(1);
174 this->write(ByteCode::Instruction::kImmediate);
175 this->write(imm);
176 this->write(ByteCode::Immediate{stride});
177 ByteCode::Register offset = this->next(1);
178 this->write(ByteCode::Instruction::kMultiplyI);
179 this->write(offset);
180 this->write(index);
181 this->write(imm);
182 return result.offset(*this, offset);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500183 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500184 }
Brian Osman0785db02019-05-24 14:19:11 -0400185 case Expression::kSwizzle_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500186 const Swizzle& s = (const Swizzle&) expr;
Brian Osman0785db02019-05-24 14:19:11 -0400187 SkASSERT(swizzle_is_simple(s));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500188 return this->getLocation(*s.fBase).offset(*this, s.fComponents[0]);
Brian Osman0785db02019-05-24 14:19:11 -0400189 }
Brian Osman07c117b2019-05-23 12:51:06 -0700190 case Expression::kVariableReference_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500191 const Variable& var = ((const VariableReference&) expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700192 return this->getLocation(var);
193 }
194 default:
195 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500196 return ByteCode::Pointer{0};
Brian Osman07c117b2019-05-23 12:51:06 -0700197 }
198}
199
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500200Variable::Storage ByteCodeGenerator::getStorage(const Expression& expr) {
201 switch (expr.fKind) {
202 case Expression::kFieldAccess_Kind: {
203 const FieldAccess& f = (const FieldAccess&) expr;
204 return this->getStorage(*f.fBase);
Ethan Nicholas7deb1c22020-01-22 10:31:55 -0500205 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500206 case Expression::kIndex_Kind: {
207 const IndexExpression& idx = (const IndexExpression&) expr;
208 return this->getStorage(*idx.fBase);
Ethan Nicholas7deb1c22020-01-22 10:31:55 -0500209 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500210 case Expression::kSwizzle_Kind: {
211 const Swizzle& s = (const Swizzle&) expr;
212 return this->getStorage(*s.fBase);
Ethan Nicholas7deb1c22020-01-22 10:31:55 -0500213 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500214 case Expression::kVariableReference_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500215 const Variable& var = ((const VariableReference&) expr).fVariable;
216 return var.fStorage;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500217 }
218 default:
Ben Wagner470e0ac2020-01-22 16:59:21 -0500219 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500220 return Variable::kLocal_Storage;
Ethan Nicholas99c54f02020-01-21 16:06:47 +0000221 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500222}
223
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500224ByteCode::Instruction ByteCodeGenerator::getLoadInstruction(ByteCodeGenerator::Location location,
225 Variable::Storage storage) {
226 switch (storage) {
227 case Variable::kGlobal_Storage:
228 switch (location.fKind) {
229 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadDirect;
230 case Location::kRegister_Kind: return ByteCode::Instruction::kLoad;
231 }
232 case Variable::kParameter_Storage:
233 switch (location.fKind) {
234 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadParameterDirect;
235 case Location::kRegister_Kind: return ByteCode::Instruction::kLoadParameter;
236 }
237 case Variable::kLocal_Storage:
238 switch (location.fKind) {
239 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadStackDirect;
240 case Location::kRegister_Kind: return ByteCode::Instruction::kLoadStack;
241 }
242 default:
243 break;
244 }
245 SkASSERT(false);
246 return ByteCode::Instruction::kNop;
247}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500248
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500249ByteCode::Instruction ByteCodeGenerator::getStoreInstruction(ByteCodeGenerator::Location location,
250 Variable::Storage storage) {
251 switch (storage) {
252 case Variable::kGlobal_Storage:
253 switch (location.fKind) {
254 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreDirect;
255 case Location::kRegister_Kind: return ByteCode::Instruction::kStore;
256 }
257 case Variable::kParameter_Storage:
258 switch (location.fKind) {
259 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreParameterDirect;
260 case Location::kRegister_Kind: return ByteCode::Instruction::kStoreParameter;
261 }
262 case Variable::kLocal_Storage:
263 switch (location.fKind) {
264 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreStackDirect;
265 case Location::kRegister_Kind: return ByteCode::Instruction::kStoreStack;
266 }
267 default:
268 break;
269 }
270 SkASSERT(false);
271 return ByteCode::Instruction::kNop;
272}
273
Ethan Nicholas2329da02020-01-24 15:49:33 -0500274#define VEC(inst) ((ByteCode::Instruction) ((uint16_t) inst + 1))
275
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500276class ByteCodeSimpleLValue : public ByteCodeGenerator::LValue {
277public:
278 ByteCodeSimpleLValue(ByteCodeGenerator* generator, ByteCodeGenerator::Location location,
279 int count, ByteCode::Instruction load, ByteCode::Instruction store)
280 : INHERITED(*generator)
281 , fLocation(location)
Ethan Nicholas2329da02020-01-24 15:49:33 -0500282 , fCount((uint8_t) count)
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500283 , fLoad(load)
284 , fStore(store) {}
285
286 void load(ByteCode::Register result) override {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500287 fGenerator.write(fLoad, fCount);
288 fGenerator.write(result);
289 fGenerator.write(fLocation);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500290 }
291
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500292 void store(ByteCode::Register src) override {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500293 fGenerator.write(fStore, fCount);
294 fGenerator.write(fLocation);
295 fGenerator.write(src);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500296 }
297
298private:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500299 ByteCodeGenerator::Location fLocation;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500300
Ethan Nicholas2329da02020-01-24 15:49:33 -0500301 uint8_t fCount;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500302
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500303 ByteCode::Instruction fLoad;
304
305 ByteCode::Instruction fStore;
306
307 typedef ByteCodeGenerator::LValue INHERITED;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500308};
309
310class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
311public:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500312 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle* swizzle)
Ben Wagner470e0ac2020-01-22 16:59:21 -0500313 : INHERITED(*generator)
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500314 , fSwizzle(*swizzle) {}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500315
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500316 void load(ByteCode::Register result) override {
317 fGenerator.writeSwizzle(fSwizzle, result);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500318 }
319
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500320 void store(ByteCode::Register src) override {
321 ByteCodeGenerator::Location target = fGenerator.getLocation(*fSwizzle.fBase);
322 ByteCode::Instruction inst = fGenerator.getStoreInstruction(
323 target,
324 fGenerator.getStorage(*fSwizzle.fBase));
325 for (size_t i = 0; i < fSwizzle.fComponents.size(); ++i) {
326 ByteCodeGenerator::Location final = target.offset(fGenerator, fSwizzle.fComponents[i]);
327 fGenerator.write(inst);
328 fGenerator.write(final);
329 fGenerator.write(src + i);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500330 }
331 }
332
333private:
334 const Swizzle& fSwizzle;
335
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500336 typedef ByteCodeGenerator::LValue INHERITED;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500337};
338
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500339class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
Ben Wagner470e0ac2020-01-22 16:59:21 -0500340public:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500341 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
Ben Wagner470e0ac2020-01-22 16:59:21 -0500342 : INHERITED(*generator)
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500343 , fIndex(index)
344 , fSlotCount(ByteCodeGenerator::SlotCount(value.type())) {
345 SkASSERT(fSlotCount <= 4);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500346 }
347
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500348 void load(ByteCode::Register result) override {
349 fGenerator.write(ByteCode::Instruction::kReadExternal);
350 fGenerator.write(result);
351 fGenerator.write((uint8_t) fSlotCount);
352 fGenerator.write((uint8_t) fIndex);
353 }
354
355 void store(ByteCode::Register src) override {
356 fGenerator.write(ByteCode::Instruction::kWriteExternal);
357 fGenerator.write((uint8_t) fIndex);
358 fGenerator.write((uint8_t) fSlotCount);
359 fGenerator.write(src);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500360 }
361
362private:
363 typedef LValue INHERITED;
364
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500365 int fIndex;
366
367 int fSlotCount;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500368};
369
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500370std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& expr) {
371 switch (expr.fKind) {
Ben Wagner470e0ac2020-01-22 16:59:21 -0500372 case Expression::kExternalValue_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500373 ExternalValue* value = ((ExternalValueReference&) expr).fValue;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500374 int index = fOutput->fExternalValues.size();
375 fOutput->fExternalValues.push_back(value);
376 SkASSERT(index <= 255);
377 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
378 }
379 case Expression::kFieldAccess_Kind:
380 case Expression::kIndex_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500381 case Expression::kVariableReference_Kind: {
382 Location location = this->getLocation(expr);
383 Variable::Storage storage = this->getStorage(expr);
384 ByteCode::Instruction loadInst = this->getLoadInstruction(location, storage);
385 ByteCode::Instruction storeInst = this->getStoreInstruction(location, storage);
386 return std::unique_ptr<LValue>(new ByteCodeSimpleLValue(this, location,
387 SlotCount(expr.fType),
388 loadInst, storeInst));
Ben Wagner470e0ac2020-01-22 16:59:21 -0500389 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500390 case Expression::kSwizzle_Kind:
391 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, &(Swizzle&) expr));
392 default:
393 ABORT("unsupported lvalue\n");
394 }
395}
396
397ByteCode::Register ByteCodeGenerator::next(int count) {
398 SkASSERT(fNextRegister + count <= ByteCode::kRegisterMax);
399 fNextRegister += count;
400 return ByteCode::Register{(uint16_t) (fNextRegister - count)};
401}
402
403static TypeCategory type_category(const Type& type) {
404 switch (type.kind()) {
405 case Type::Kind::kVector_Kind:
406 case Type::Kind::kMatrix_Kind:
407 return type_category(type.componentType());
408 default:
409 String name = type.displayName();
410 if (name == "bool") {
411 return TypeCategory::kBool;
412 } else if (name == "int" || name == "short") {
413 return TypeCategory::kSigned;
414 } else if (name == "uint" || name == "ushort") {
415 return TypeCategory::kUnsigned;
416 } else {
417 SkASSERT(name == "float" || name == "half");
418 return TypeCategory::kFloat;
419 }
420 ABORT("unsupported type: %s\n", name.c_str());
421 }
422}
423
Ethan Nicholas2329da02020-01-24 15:49:33 -0500424void ByteCodeGenerator::write(ByteCode::Instruction inst, int count) {
425 SkASSERT(count <= 255);
426 if (count > 1) {
427 this->write(VEC(inst));
428 this->write((uint8_t) count);
429 }
430 else {
431 this->write(inst);
432 }
433}
434
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500435void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCode::Instruction s,
436 ByteCode::Instruction u, ByteCode::Instruction f) {
437 switch (type_category(type)) {
438 case TypeCategory::kSigned:
439 this->write(s);
440 break;
441 case TypeCategory::kUnsigned:
442 this->write(u);
443 break;
444 case TypeCategory::kFloat: {
445 this->write(f);
446 break;
447 }
448 default:
449 SkASSERT(false);
450 }
451}
452
Ethan Nicholas2329da02020-01-24 15:49:33 -0500453void ByteCodeGenerator::writeVectorBinaryInstruction(const Type& operandType,
454 ByteCode::Register left,
455 ByteCode::Register right,
456 ByteCode::Instruction s,
457 ByteCode::Instruction u,
458 ByteCode::Instruction f,
459 ByteCode::Register result) {
460 uint8_t count = (uint8_t) SlotCount(operandType);
461 if (count == 1) {
462 this->writeTypedInstruction(operandType, s, u, f);
463 }
464 else {
465 this->writeTypedInstruction(operandType, VEC(s), VEC(u), VEC(f));
466 this->write(count);
467 }
468 this->write(result);
469 this->write(left);
470 this->write(right);
471}
472
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500473void ByteCodeGenerator::writeBinaryInstruction(const Type& operandType,
474 ByteCode::Register left,
475 ByteCode::Register right,
476 ByteCode::Instruction s,
477 ByteCode::Instruction u,
478 ByteCode::Instruction f,
479 ByteCode::Register result) {
480 for (int i = 0; i < SlotCount(operandType); ++i) {
481 this->writeTypedInstruction(operandType, s, u, f);
482 this->write(result + i);
483 this->write(left + i);
484 this->write(right + i);
485 }
486}
487
488void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
489 ByteCode::Register result) {
490 if (b.fOperator == Token::Kind::EQ) {
491 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
492 this->writeExpression(*b.fRight, result);
493 lvalue->store(result);
494 return;
495 }
496 const Type& lType = b.fLeft->fType;
497 const Type& rType = b.fRight->fType;
498 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
499 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
500 const Type* operandType;
501 if (!lVecOrMtx && rVecOrMtx) {
502 operandType = &rType;
503 } else {
504 operandType = &lType;
505 }
506 Token::Kind op;
507 std::unique_ptr<LValue> lvalue;
508 ByteCode::Register left;
509 switch (b.fOperator) {
510 case Token::Kind::LOGICALAND:
511 case Token::Kind::LOGICALANDEQ:
512 case Token::Kind::LOGICALOR:
513 case Token::Kind::LOGICALOREQ:
514 left = result;
515 break;
516 default:
517 left = this->next(SlotCount(*operandType));
518 }
519 if (is_assignment(b.fOperator)) {
520 lvalue = this->getLValue(*b.fLeft);
521 lvalue->load(left);
522 op = remove_assignment(b.fOperator);
523 } else {
524 this->writeExpression(*b.fLeft, left);
525 op = b.fOperator;
526 if (!lVecOrMtx && rVecOrMtx) {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500527 this->write(ByteCode::Instruction::kSplat);
528 this->write((uint8_t) (SlotCount(rType) - 1));
529 this->write(left + 1);
530 this->write(left);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500531 }
532 }
533 SkDEBUGCODE(TypeCategory tc = type_category(lType));
534 int count = std::max(SlotCount(lType), SlotCount(rType));
535 switch (op) {
536 case Token::Kind::LOGICALAND: {
537 SkASSERT(left.fIndex == result.fIndex);
538 this->write(ByteCode::Instruction::kMaskPush);
539 ++fConditionCount;
540 this->write(left);
541 this->write(ByteCode::Instruction::kBranchIfAllFalse);
542 DeferredLocation falseLocation(this);
543 SkASSERT(SlotCount(b.fRight->fType) == 1);
544 ByteCode::Register right = this->next(1);
545 this->writeExpression(*b.fRight, right);
546 this->write(ByteCode::Instruction::kAnd);
547 this->write(result);
548 this->write(left);
549 this->write(right);
550 falseLocation.set();
551 --fConditionCount;
552 this->write(ByteCode::Instruction::kMaskPop);
553 return;
554 }
555 case Token::Kind::LOGICALOR: {
556 SkASSERT(left.fIndex == result.fIndex);
557 ByteCode::Register mask = this->next(1);
558 this->write(ByteCode::Instruction::kNot);
559 this->write(mask);
560 this->write(left);
561 this->write(ByteCode::Instruction::kMaskPush);
562 ++fConditionCount;
563 this->write(mask);
564 this->write(ByteCode::Instruction::kBranchIfAllFalse);
565 DeferredLocation falseLocation(this);
566 SkASSERT(SlotCount(b.fRight->fType) == 1);
567 ByteCode::Register right = this->next(1);
568 this->writeExpression(*b.fRight, right);
569 this->write(ByteCode::Instruction::kOr);
570 this->write(result);
571 this->write(left);
572 this->write(right);
573 falseLocation.set();
574 --fConditionCount;
575 this->write(ByteCode::Instruction::kMaskPop);
576 return;
577 }
578 case Token::Kind::SHL:
579 case Token::Kind::SHR: {
580 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
581 tc == SkSL::TypeCategory::kUnsigned));
582 if (!b.fRight->isConstant()) {
583 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
584 return;
585 }
586 int64_t shift = b.fRight->getConstantInt();
587 if (shift < 0 || shift > 31) {
588 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
589 return;
590 }
591
592 if (op == Token::Kind::SHL) {
593 this->write(ByteCode::Instruction::kShiftLeft);
594 } else {
595 this->write(type_category(lType) == TypeCategory::kSigned
596 ? ByteCode::Instruction::kShiftRightS
597 : ByteCode::Instruction::kShiftRightU);
598 }
599 this->write(result);
600 this->write(left);
601 this->write((uint8_t) shift);
602 return;
603 }
604 case Token::Kind::STAR:
605 // Special case for M*V, V*M, M*M (but not V*V!)
606 if (lType.columns() > 1 && rType.columns() > 1 &&
607 (lType.rows() > 1 || rType.rows() > 1)) {
608 ByteCode::Register right = this->next(SlotCount(rType));
609 this->writeExpression(*b.fRight, right);
610 int rCols = rType.columns(),
611 rRows = rType.rows(),
612 lCols = lType.columns(),
613 lRows = lType.rows();
614 // M*V treats the vector as a column
615 if (rType.kind() == Type::kVector_Kind) {
616 std::swap(rCols, rRows);
617 }
618 SkASSERT(lCols == rRows);
619 SkASSERT(SlotCount(b.fType) == lRows * rCols);
620 this->write(ByteCode::Instruction::kMatrixMultiply);
621 this->write(result);
622 this->write(left);
623 this->write(right);
624 this->write((uint8_t) lCols);
625 this->write((uint8_t) lRows);
626 this->write((uint8_t) rCols);
627 return;
628 }
629
630 default:
631 break;
632 }
633 ByteCode::Register right = this->next(SlotCount(*operandType));
634 this->writeExpression(*b.fRight, right);
635 if (lVecOrMtx && !rVecOrMtx) {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500636 this->write(ByteCode::Instruction::kSplat);
637 this->write((uint8_t) (SlotCount(*operandType) - 1));
638 this->write(right + 1);
639 this->write(right);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500640 }
641 switch (op) {
642 case Token::Kind::EQEQ:
643 this->writeBinaryInstruction(*operandType, left, right,
644 ByteCode::Instruction::kCompareEQI,
645 ByteCode::Instruction::kCompareEQI,
646 ByteCode::Instruction::kCompareEQF,
647 result);
648 // Collapse to a single bool
649 for (int i = 1; i < count; ++i) {
650 this->write(ByteCode::Instruction::kAnd);
651 this->write(result);
652 this->write(result);
653 this->write(result + i);
654 }
655 break;
656 case Token::Kind::GT:
657 this->writeBinaryInstruction(*operandType, left, right,
658 ByteCode::Instruction::kCompareGTS,
659 ByteCode::Instruction::kCompareGTU,
660 ByteCode::Instruction::kCompareGTF,
661 result);
662 break;
663 case Token::Kind::GTEQ:
664 this->writeBinaryInstruction(*operandType, left, right,
665 ByteCode::Instruction::kCompareGTEQS,
666 ByteCode::Instruction::kCompareGTEQU,
667 ByteCode::Instruction::kCompareGTEQF,
668 result);
669 break;
670 case Token::Kind::LT:
671 this->writeBinaryInstruction(*operandType, left, right,
672 ByteCode::Instruction::kCompareLTS,
673 ByteCode::Instruction::kCompareLTU,
674 ByteCode::Instruction::kCompareLTF,
675 result);
676 break;
677 case Token::Kind::LTEQ:
678 this->writeBinaryInstruction(*operandType, left, right,
679 ByteCode::Instruction::kCompareLTEQS,
680 ByteCode::Instruction::kCompareLTEQU,
681 ByteCode::Instruction::kCompareLTEQF,
682 result);
683 break;
684 case Token::Kind::MINUS:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500685 this->writeVectorBinaryInstruction(*operandType, left, right,
686 ByteCode::Instruction::kSubtractI,
687 ByteCode::Instruction::kSubtractI,
688 ByteCode::Instruction::kSubtractF,
689 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500690 break;
691 case Token::Kind::NEQ:
692 this->writeBinaryInstruction(*operandType, left, right,
693 ByteCode::Instruction::kCompareNEQI,
694 ByteCode::Instruction::kCompareNEQI,
695 ByteCode::Instruction::kCompareNEQF,
696 result);
697 // Collapse to a single bool
698 for (int i = 1; i < count; ++i) {
699 this->write(ByteCode::Instruction::kOr);
700 this->write(result);
701 this->write(result);
702 this->write(result + i);
703 }
704 break;
705 case Token::Kind::PERCENT:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500706 this->writeVectorBinaryInstruction(*operandType, left, right,
707 ByteCode::Instruction::kRemainderS,
708 ByteCode::Instruction::kRemainderU,
709 ByteCode::Instruction::kRemainderF,
710 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500711 break;
712 case Token::Kind::PLUS:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500713 this->writeVectorBinaryInstruction(*operandType, left, right,
714 ByteCode::Instruction::kAddI,
715 ByteCode::Instruction::kAddI,
716 ByteCode::Instruction::kAddF,
717 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500718 break;
719 case Token::Kind::SLASH:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500720 this->writeVectorBinaryInstruction(*operandType, left, right,
721 ByteCode::Instruction::kDivideS,
722 ByteCode::Instruction::kDivideU,
723 ByteCode::Instruction::kDivideF,
724 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500725 break;
726 case Token::Kind::STAR:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500727 this->writeVectorBinaryInstruction(*operandType, left, right,
728 ByteCode::Instruction::kMultiplyI,
729 ByteCode::Instruction::kMultiplyI,
730 ByteCode::Instruction::kMultiplyF,
731 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500732 break;
733 case Token::Kind::LOGICALXOR: {
734 SkASSERT(tc == SkSL::TypeCategory::kBool);
735 this->write(ByteCode::Instruction::kXor);
736 this->write(result);
737 this->write(left);
738 this->write(right);
739 break;
740 }
741 case Token::Kind::BITWISEAND: {
742 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
743 this->write(ByteCode::Instruction::kAnd);
744 this->write(result);
745 this->write(left);
746 this->write(right);
747 break;
748 }
749 case Token::Kind::BITWISEOR: {
750 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
751 this->write(ByteCode::Instruction::kOr);
752 this->write(result);
753 this->write(left);
754 this->write(right);
755 break;
756 }
757 case Token::Kind::BITWISEXOR: {
758 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
759 this->write(ByteCode::Instruction::kXor);
760 this->write(result);
761 this->write(left);
762 this->write(right);
763 break;
764 }
765 default:
766 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
767 Compiler::OperatorName(op)));
768 break;
769 }
770 if (lvalue) {
771 lvalue->store(result);
772 }
773}
774
775void ByteCodeGenerator::writeConstructor(const Constructor& c, ByteCode::Register result) {
776 if (c.fType.rows() > 1) {
777 if (c.fArguments.size() == 1) {
778 if (SlotCount(c.fArguments[0]->fType) == 1) {
779 ByteCode::Register v = this->next(1);
780 this->writeExpression(*c.fArguments[0], v);
781 this->write(ByteCode::Instruction::kScalarToMatrix);
782 this->write(result);
783 this->write(v);
784 this->write((uint8_t) c.fType.columns());
785 this->write((uint8_t) c.fType.rows());
786 return;
787 } else if (c.fArguments[0]->fType.rows() > 1) {
788 ByteCode::Register v = this->next(SlotCount(c.fArguments[0]->fType));
789 this->writeExpression(*c.fArguments[0], v);
790 this->write(ByteCode::Instruction::kMatrixToMatrix);
791 this->write(result);
792 this->write(v);
793 this->write((uint8_t) c.fArguments[0]->fType.columns());
794 this->write((uint8_t) c.fArguments[0]->fType.rows());
795 this->write((uint8_t) c.fType.columns());
796 this->write((uint8_t) c.fType.rows());
797 return;
798 }
799 }
800 int offset = 0;
801 for (const auto& arg : c.fArguments) {
802 this->writeExpression(*arg, ByteCode::Register{(uint16_t) (result.fIndex + offset)});
803 offset += SlotCount(arg->fType);
804 }
805 return;
806 }
807 if (c.fArguments.size() == 1 && c.fArguments[0]->fType.columns() == 1 &&
808 c.fType.columns() > 1) {
809 SkASSERT(SlotCount(c.fArguments[0]->fType) == 1);
810 ByteCode::Register v = result;
811 this->writeExpression(*c.fArguments[0], v);
Ethan Nicholas2329da02020-01-24 15:49:33 -0500812 this->write(ByteCode::Instruction::kSplat);
813 this->write((uint8_t) (c.fType.columns() - 1));
814 this->write(v + 1);
815 this->write(v);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500816 return;
817 }
818 ByteCode::Instruction inst;
819 switch (type_category(c.fArguments[0]->fType)) {
820 case TypeCategory::kSigned:
821 if (type_category(c.fType) == TypeCategory::kFloat) {
822 inst = ByteCode::Instruction::kSignedToFloat;
823 } else {
824 inst = ByteCode::Instruction::kNop;
825 }
826 break;
827 case TypeCategory::kUnsigned:
828 if (type_category(c.fType) == TypeCategory::kFloat) {
829 inst = ByteCode::Instruction::kUnsignedToFloat;
830 } else {
831 inst = ByteCode::Instruction::kNop;
832 }
833 break;
834 case TypeCategory::kFloat:
835 if (type_category(c.fType) == TypeCategory::kSigned) {
836 inst = ByteCode::Instruction::kFloatToSigned;
837 } else if (type_category(c.fType) == TypeCategory::kUnsigned) {
838 inst = ByteCode::Instruction::kFloatToUnsigned;
839 } else {
840 inst = ByteCode::Instruction::kNop;
841 }
842 break;
843 default:
844 SkASSERT(false);
845 return;
846 }
847 ByteCode::Register values;
848 if (inst == ByteCode::Instruction::kNop) {
849 values = result;
850 } else {
851 values = this->next(SlotCount(c.fType));
852 }
853 ByteCode::Register v = values;
854 for (size_t i = 0; i < c.fArguments.size(); ++i) {
855 this->writeExpression(*c.fArguments[i], v);
856 v.fIndex += SlotCount(c.fArguments[i]->fType);
857 }
858 if (inst != ByteCode::Instruction::kNop) {
859 v = values;
860 ByteCode::Register target = result;
861 for (size_t i = 0; i < c.fArguments.size(); ++i) {
862 int count = SlotCount(c.fArguments[i]->fType);
863 for (int j = 0; j < count; ++j) {
864 this->write(inst);
865 this->write(target);
866 ++target.fIndex;
867 this->write(v + j);
868 }
869 }
870 }
871}
872
873void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f,
874 ByteCode::Register result) {
875 int argumentCount = 0;
876 for (const auto& arg : f.fArguments) {
877 argumentCount += SlotCount(arg->fType);
878 }
879 ByteCode::Register args = this->next(argumentCount);
880 argumentCount = 0;
881 for (const auto& arg : f.fArguments) {
882 this->writeExpression(*arg, args + argumentCount);
883 argumentCount += SlotCount(arg->fType);
884 }
885 this->write(ByteCode::Instruction::kCallExternal);
886 this->write(result);
887 int index = fOutput->fExternalValues.size();
888 fOutput->fExternalValues.push_back(f.fFunction);
889 SkASSERT(index <= 255);
890 this->write((uint8_t) index);
891 SkASSERT(SlotCount(f.fType) <= 255);
892 this->write((uint8_t) SlotCount(f.fType));
893 this->write(args);
894 SkASSERT(argumentCount <= 255);
895 this->write((uint8_t) argumentCount);
896}
897
898void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e,
899 ByteCode::Register result) {
900 this->write(ByteCode::Instruction::kReadExternal);
901 this->write(result);
902 this->write((uint8_t) SlotCount(e.fValue->type()));
903 int index = fOutput->fExternalValues.size();
904 fOutput->fExternalValues.push_back(e.fValue);
905 SkASSERT(index <= 255);
906 this->write((uint8_t) index);
907}
908
909void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c, Intrinsic intrinsic,
910 ByteCode::Register result) {
911 if (intrinsic.fIsSpecial) {
912 switch (intrinsic.fValue.fSpecial) {
913 case SpecialIntrinsic::kDot: {
914 SkASSERT(c.fArguments.size() == 2);
915 int count = SlotCount(c.fArguments[0]->fType);
916 ByteCode::Register left = this->next(count);
917 this->writeExpression(*c.fArguments[0], left);
918 ByteCode::Register right = this->next(count);
919 this->writeExpression(*c.fArguments[1], right);
920 ByteCode::Register product = this->next(count);
Ethan Nicholas2329da02020-01-24 15:49:33 -0500921 this->writeTypedInstruction(c.fType,
922 ByteCode::Instruction::kMultiplyIN,
923 ByteCode::Instruction::kMultiplyIN,
924 ByteCode::Instruction::kMultiplyFN);
925 this->write((uint8_t) count);
926 this->write(product);
927 this->write(left);
928 this->write(right);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500929 ByteCode::Register total = product;
930 for (int i = 1; i < count; ++i) {
931 this->writeTypedInstruction(c.fType,
932 ByteCode::Instruction::kAddI,
933 ByteCode::Instruction::kAddI,
934 ByteCode::Instruction::kAddF);
935 ByteCode::Register sum = i == count - 1 ? result : this->next(1);
936 this->write(sum);
937 this->write(total);
938 this->write(product + i);
939 total = sum;
940 }
941 break;
942 }
943 case SpecialIntrinsic::kInverse: {
944 SkASSERT(c.fArguments.size() == 1);
945 int count = SlotCount(c.fArguments[0]->fType);
946 ByteCode::Register arg = this->next(count);
947 this->writeExpression(*c.fArguments[0], arg);
948 switch (SlotCount(c.fArguments[0]->fType)) {
949 case 4: this->write(ByteCode::Instruction::kInverse2x2); break;
950 case 9: this->write(ByteCode::Instruction::kInverse3x3); break;
951 case 16: this->write(ByteCode::Instruction::kInverse4x4); break;
952 default: SkASSERT(false);
953 }
954 this->write(result);
955 this->write(arg);
956 break;
957 }
958 }
959 } else {
960 std::vector<ByteCode::Register> argRegs;
961 for (const auto& expr : c.fArguments) {
962 ByteCode::Register reg = this->next(SlotCount(expr->fType));
963 this->writeExpression(*expr, reg);
964 argRegs.push_back(reg);
965 }
966 this->write(intrinsic.fValue.fInstruction);
967 if (c.fType.fName != "void") {
968 this->write(result);
969 }
970 for (ByteCode::Register arg : argRegs) {
971 this->write(arg);
972 }
973 }
974}
975
976void ByteCodeGenerator::writeFunctionCall(const FunctionCall& c, ByteCode::Register result) {
977 auto found = fIntrinsics.find(c.fFunction.fName);
978 if (found != fIntrinsics.end()) {
979 return this->writeIntrinsicCall(c, found->second, result);
980 }
981 int argCount = c.fArguments.size();
982 std::vector<std::unique_ptr<LValue>> lvalues;
983 int parameterSlotCount = 0;
984 for (const auto& p : c.fFunction.fParameters) {
985 parameterSlotCount += SlotCount(p->fType);
986 }
987 ByteCode::Register argStart = this->next(parameterSlotCount);
988 ByteCode::Register nextArg = argStart;
989 for (int i = 0; i < argCount; ++i) {
990 const auto& param = c.fFunction.fParameters[i];
991 const auto& arg = c.fArguments[i];
992 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
993 lvalues.emplace_back(this->getLValue(*arg));
994 lvalues.back()->load(nextArg);
995 } else {
996 this->writeExpression(*arg, nextArg);
997 }
998 nextArg.fIndex += SlotCount(arg->fType);
999 }
1000 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1001 // before they're defined. This is an easy-to-understand rule that prevents recursion.
1002 size_t idx;
1003 for (idx = 0; idx < fFunctions.size(); ++idx) {
1004 if (c.fFunction.matches(fFunctions[idx]->fDeclaration)) {
1005 break;
1006 }
1007 }
1008 if (idx > 255) {
1009 fErrors.error(c.fOffset, "Function count limit exceeded");
1010 return;
1011 } else if (idx >= fOutput->fFunctions.size()) {
1012 fErrors.error(c.fOffset, "Call to undefined function");
1013 return;
1014 }
1015
1016 this->write(ByteCode::Instruction::kCall);
1017 this->write(result);
1018 this->write((uint8_t) idx);
1019 this->write(argStart);
1020 nextArg = argStart;
1021 auto lvalue = lvalues.begin();
1022 for (int i = 0; i < argCount; ++i) {
1023 const auto& param = c.fFunction.fParameters[i];
1024 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1025 (*(lvalue++))->store(nextArg);
1026 }
1027 nextArg.fIndex += SlotCount(param->fType);
1028 }
1029}
1030
1031void ByteCodeGenerator::incOrDec(Token::Kind op, Expression& operand, bool prefix,
1032 ByteCode::Register result) {
1033 SkASSERT(op == Token::Kind::PLUSPLUS || op == Token::Kind::MINUSMINUS);
1034 std::unique_ptr<LValue> lvalue = this->getLValue(operand);
1035 SkASSERT(SlotCount(operand.fType) == 1);
1036 ByteCode::Register value;
1037 if (prefix) {
1038 value = this->next(1);
1039 } else {
1040 value = result;
1041 }
1042 lvalue->load(value);
1043 ByteCode::Register one = this->next(1);
1044 this->write(ByteCode::Instruction::kImmediate);
1045 this->write(one);
1046 if (type_category(operand.fType) == TypeCategory::kFloat) {
1047 this->write(ByteCode::Immediate(1.0f));
1048 } else {
1049 this->write(ByteCode::Immediate((int32_t) 1));
1050 }
1051 if (op == Token::Kind::PLUSPLUS) {
1052 this->writeTypedInstruction(operand.fType,
1053 ByteCode::Instruction::kAddI,
1054 ByteCode::Instruction::kAddI,
1055 ByteCode::Instruction::kAddF);
1056 } else {
1057 this->writeTypedInstruction(operand.fType,
1058 ByteCode::Instruction::kSubtractI,
1059 ByteCode::Instruction::kSubtractI,
1060 ByteCode::Instruction::kSubtractF);
1061 }
1062 if (prefix) {
1063 this->write(result);
1064 this->write(value);
1065 this->write(one);
1066 lvalue->store(result);
1067 } else {
1068 ByteCode::Register temp = this->next(1);
1069 this->write(temp);
1070 this->write(value);
1071 this->write(one);
1072 lvalue->store(temp);
1073 }
1074}
1075
1076void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p,
1077 ByteCode::Register result) {
1078 this->incOrDec(p.fOperator, *p.fOperand, false, result);
1079}
1080
1081void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p,
1082 ByteCode::Register result) {
1083 switch (p.fOperator) {
1084 case Token::Kind::PLUSPLUS:
1085 case Token::Kind::MINUSMINUS: {
1086 return this->incOrDec(p.fOperator, *p.fOperand, true, result);
1087 }
1088 case Token::Kind::MINUS: {
1089 ByteCode::Register src = this->next(SlotCount(p.fType));
1090 this->writeExpression(*p.fOperand, src);
1091 for (int i = 0; i < SlotCount(p.fType); ++i) {
1092 this->writeTypedInstruction(p.fType,
1093 ByteCode::Instruction::kNegateS,
1094 ByteCode::Instruction::kNegateS,
1095 ByteCode::Instruction::kNegateF);
1096 this->write(result + i);
1097 this->write(src + i);
1098 }
1099 break;
1100 }
1101 case Token::Kind::LOGICALNOT:
1102 case Token::Kind::BITWISENOT: {
1103 ByteCode::Register src = this->next(SlotCount(p.fType));
1104 this->writeExpression(*p.fOperand, src);
1105 for (int i = 0; i < SlotCount(p.fType); ++i) {
1106 this->write(ByteCode::Instruction::kNot);
1107 this->write(result + i);
1108 this->write(src + i);
1109 }
1110 break;
1111 }
1112 default:
1113 SkASSERT(false);
1114 }
1115}
1116
1117void ByteCodeGenerator::writeSwizzle(const Swizzle& s, ByteCode::Register result) {
1118 if (swizzle_is_simple(s)) {
1119 this->writeVariableExpression(s, result);
1120 return;
1121 }
1122 ByteCode::Register base = this->writeExpression(*s.fBase);
1123 for (int i = 0; i < (int) s.fComponents.size(); ++i) {
1124 this->write(ByteCode::Instruction::kCopy);
1125 this->write(result + i);
1126 this->write(base + s.fComponents[i]);
1127 }
1128}
1129
1130void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
1131 ByteCode::Register result) {
1132 int count = SlotCount(t.fType);
1133 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1134 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1135
1136 ByteCode::Register test = this->writeExpression(*t.fTest);
1137 this->write(ByteCode::Instruction::kMaskPush);
1138 ++fConditionCount;
1139 this->write(test);
1140 ByteCode::Register ifTrue = this->writeExpression(*t.fIfTrue);
1141 this->write(ByteCode::Instruction::kMaskNegate);
1142 ByteCode::Register ifFalse = this->writeExpression(*t.fIfFalse);
1143 --fConditionCount;
1144 this->write(ByteCode::Instruction::kMaskPop);
1145 for (int i = 0; i < count; ++i) {
1146 this->write(ByteCode::Instruction::kSelect);
1147 this->write(result + i);
1148 this->write(test);
1149 this->write(ifTrue + i);
1150 this->write(ifFalse + i);
1151 }
1152}
1153
1154void ByteCodeGenerator::writeVariableExpression(const Expression& expr,
1155 ByteCode::Register result) {
1156 ByteCodeGenerator::Location location = this->getLocation(expr);
1157 int count = SlotCount(expr.fType);
Ethan Nicholas2329da02020-01-24 15:49:33 -05001158 ByteCode::Instruction load = this->getLoadInstruction(location, this->getStorage(expr));
1159 this->write(load, count);
1160 this->write(result);
1161 this->write(location);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001162}
1163
1164void ByteCodeGenerator::writeExpression(const Expression& expr, ByteCode::Register result) {
1165 switch (expr.fKind) {
1166 case Expression::kBoolLiteral_Kind: {
1167 this->write(ByteCode::Instruction::kImmediate);
1168 this->write(result);
1169 this->write(ByteCode::Immediate((int32_t) (((BoolLiteral&) expr).fValue ? -1 : 0)));
1170 break;
1171 }
1172 case Expression::kBinary_Kind: {
1173 this->writeBinaryExpression((BinaryExpression&) expr, result);
1174 break;
1175 }
1176 case Expression::kConstructor_Kind: {
1177 this->writeConstructor((Constructor&) expr, result);
1178 break;
1179 }
1180 case Expression::kExternalFunctionCall_Kind:
1181 this->writeExternalFunctionCall((ExternalFunctionCall&) expr, result);
1182 break;
1183 case Expression::kExternalValue_Kind:
1184 this->writeExternalValue((ExternalValueReference&) expr, result);
1185 break;
1186 case Expression::kFloatLiteral_Kind: {
1187 this->write(ByteCode::Instruction::kImmediate);
1188 this->write(result);
1189 this->write(ByteCode::Immediate((float) ((FloatLiteral&) expr).fValue));
1190 break;
1191 }
1192 case Expression::kFunctionCall_Kind: {
1193 this->writeFunctionCall((FunctionCall&) expr, result);
1194 break;
1195 }
1196 case Expression::kIntLiteral_Kind: {
1197 this->write(ByteCode::Instruction::kImmediate);
1198 this->write(result);
1199 this->write(ByteCode::Immediate((int32_t) ((IntLiteral&) expr).fValue));
1200 break;
1201 }
1202 case Expression::kPostfix_Kind:
1203 this->writePostfixExpression((PostfixExpression&) expr, result);
1204 break;
1205 case Expression::kPrefix_Kind:
1206 this->writePrefixExpression((PrefixExpression&) expr, result);
1207 break;
1208 case Expression::kSwizzle_Kind:
1209 this->writeSwizzle((Swizzle&) expr, result);
1210 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001211 case Expression::kTernary_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001212 this->writeTernaryExpression((TernaryExpression&) expr, result);
1213 break;
1214 case Expression::kFieldAccess_Kind:
1215 case Expression::kIndex_Kind:
1216 case Expression::kVariableReference_Kind:
1217 this->writeVariableExpression(expr, result);
1218 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001219 default:
1220#ifdef SK_DEBUG
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001221 ABORT("unsupported lvalue %s\n", expr.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001222#endif
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001223 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001224 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001225}
1226
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001227ByteCode::Register ByteCodeGenerator::writeExpression(const Expression& expr) {
1228 ByteCode::Register result = this->next(SlotCount(expr.fType));
1229 this->writeExpression(expr, result);
1230 return result;
1231}
1232
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001233void ByteCodeGenerator::writeBlock(const Block& b) {
1234 for (const auto& s : b.fStatements) {
1235 this->writeStatement(*s);
1236 }
1237}
1238
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001239void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001240 this->write(ByteCode::Instruction::kLoopBegin);
1241 ++fConditionCount;
1242 SkASSERT(fCode->size() < ByteCode::kPointerMax);
1243 ByteCode::Pointer start{(uint16_t) fCode->size()};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001244 this->writeStatement(*d.fStatement);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001245 ByteCode::Register test = this->writeExpression(*d.fTest);
1246 this->write(ByteCode::Instruction::kLoopNext);
1247 this->write(ByteCode::Instruction::kLoopMask);
1248 this->write(test);
1249 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001250 DeferredLocation endLocation(this);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001251 this->write(ByteCode::Instruction::kBranch);
1252 this->write(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001253 endLocation.set();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001254 --fConditionCount;
1255 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001256}
1257
1258void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001259 if (f.fInitializer) {
1260 this->writeStatement(*f.fInitializer);
1261 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001262 this->write(ByteCode::Instruction::kLoopBegin);
1263 ++fConditionCount;
1264 ByteCode::Pointer start{(uint16_t) fCode->size()};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001265 if (f.fTest) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001266 ByteCode::Register test = this->writeExpression(*f.fTest);
1267 this->write(ByteCode::Instruction::kLoopMask);
1268 this->write(test);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001269 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001270 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001271 DeferredLocation endLocation(this);
1272 this->writeStatement(*f.fStatement);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001273 this->write(ByteCode::Instruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001274 if (f.fNext) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001275 this->writeExpression(*f.fNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001276 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001277 this->write(ByteCode::Instruction::kBranch);
1278 this->write(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001279 endLocation.set();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001280 --fConditionCount;
1281 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001282}
1283
1284void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001285 ByteCode::Register test = this->writeExpression(*i.fTest);
1286 this->write(ByteCode::Instruction::kMaskPush);
1287 ++fConditionCount;
1288 this->write(test);
1289 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001290 DeferredLocation falseLocation(this);
1291 this->writeStatement(*i.fIfTrue);
1292 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001293 if (i.fIfFalse) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001294 this->write(ByteCode::Instruction::kMaskNegate);
1295 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001296 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001297 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001298 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001299 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001300 --fConditionCount;
1301 this->write(ByteCode::Instruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001302}
1303
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001304void ByteCodeGenerator::writeReturn(const ReturnStatement& r) {
1305 if (fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001306 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1307 return;
1308 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001309 if (r.fExpression) {
1310 ByteCode::Register value = this->writeExpression(*r.fExpression);
1311 this->write(ByteCode::Instruction::kReturnValue);
1312 this->write(value);
1313 }
1314 else {
1315 this->write(ByteCode::Instruction::kReturn);
1316 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001317}
1318
1319void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1320 for (const auto& declStatement : v.fVars) {
1321 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001322 // we need to grab the location even if we don't use it, to ensure it
1323 // has been allocated
1324 ByteCodeGenerator::Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001325 if (decl.fValue) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001326 ByteCode::Register src = this->writeExpression(*decl.fValue);
Ethan Nicholas2329da02020-01-24 15:49:33 -05001327 uint8_t count = (uint8_t) SlotCount(decl.fVar->fType);
1328 this->write(ByteCode::Instruction::kStoreStackDirect, count);
1329 this->write(location);
1330 this->write(src);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001331 }
1332 }
1333}
1334
1335void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001336 this->write(ByteCode::Instruction::kLoopBegin);
1337 ++fConditionCount;
1338 SkASSERT(fCode->size() < ByteCode::kPointerMax);
1339 ByteCode::Pointer start{(uint16_t) fCode->size()};
1340 ByteCode::Register test = this->writeExpression(*w.fTest);
1341 this->write(ByteCode::Instruction::kLoopMask);
1342 this->write(test);
1343 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001344 DeferredLocation endLocation(this);
1345 this->writeStatement(*w.fStatement);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001346 this->write(ByteCode::Instruction::kLoopNext);
1347 this->write(ByteCode::Instruction::kBranch);
1348 this->write(start);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001349 endLocation.set();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001350 --fConditionCount;
1351 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001352}
1353
1354void ByteCodeGenerator::writeStatement(const Statement& s) {
1355 switch (s.fKind) {
1356 case Statement::kBlock_Kind:
1357 this->writeBlock((Block&) s);
1358 break;
1359 case Statement::kBreak_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001360 this->write(ByteCode::Instruction::kBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001361 break;
1362 case Statement::kContinue_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001363 this->write(ByteCode::Instruction::kContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001364 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001365 case Statement::kDo_Kind:
1366 this->writeDoStatement((DoStatement&) s);
1367 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001368 case Statement::kExpression_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001369 this->writeExpression(*((ExpressionStatement&) s).fExpression);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001370 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001371 case Statement::kFor_Kind:
1372 this->writeForStatement((ForStatement&) s);
1373 break;
1374 case Statement::kIf_Kind:
1375 this->writeIfStatement((IfStatement&) s);
1376 break;
1377 case Statement::kNop_Kind:
1378 break;
1379 case Statement::kReturn_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001380 this->writeReturn((ReturnStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001381 break;
1382 case Statement::kVarDeclarations_Kind:
1383 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1384 break;
1385 case Statement::kWhile_Kind:
1386 this->writeWhileStatement((WhileStatement&) s);
1387 break;
1388 default:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001389 ABORT("unsupported statement\n");
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001390 }
1391}
1392
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001393void ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
1394 fFunction = &f;
1395 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
1396 result->fReturnSlotCount = SlotCount(f.fDeclaration.fReturnType);
Brian Osman80164412019-06-07 13:00:23 -04001397 fParameterCount = 0;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001398 fConditionCount = 0;
1399 for (const auto& p : f.fDeclaration.fParameters) {
1400 int count = SlotCount(p->fType);
1401 bool isOut = ((p->fModifiers.fFlags & Modifiers::kOut_Flag) != 0);
1402 result->fParameters.push_back(ByteCodeFunction::Parameter{count, isOut});
1403 fParameterCount += count;
1404 }
1405 result->fParameterSlotCount = fParameterCount;
1406 fCode = &result->fCode;
1407 this->writeStatement(*f.fBody);
1408 result->fStackSlotCount = fLocals.size();
1409 if (f.fDeclaration.fReturnType.fName == "void") {
1410 this->write(ByteCode::Instruction::kReturn);
1411 } else {
1412 this->write(ByteCode::Instruction::kAbort);
1413 }
1414 fOutput->fFunctions.push_back(std::move(result));
1415 SkASSERT(fConditionCount == 0);
1416}
1417
1418void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
1419 if (type.kind() == Type::kOther_Kind) {
1420 return;
1421 } else if (type.kind() == Type::kStruct_Kind) {
1422 for (const auto& f : type.fields()) {
1423 this->gatherUniforms(*f.fType, name + "." + f.fName);
1424 }
1425 } else if (type.kind() == Type::kArray_Kind) {
1426 for (int i = 0; i < type.columns(); ++i) {
1427 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
1428 }
1429 } else {
1430 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
1431 fOutput->fUniformSlotCount });
1432 fOutput->fUniformSlotCount += type.columns() * type.rows();
Brian Osman80164412019-06-07 13:00:23 -04001433 }
1434}
1435
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001436bool ByteCodeGenerator::generateCode() {
1437 fOutput->fGlobalSlotCount = 0;
1438 fOutput->fUniformSlotCount = 0;
1439 for (const auto& pe : fProgram) {
1440 if (pe.fKind == ProgramElement::kVar_Kind) {
1441 VarDeclarations& decl = (VarDeclarations&) pe;
1442 for (const auto& v : decl.fVars) {
1443 const Variable* declVar = ((VarDeclaration&) *v).fVar;
1444 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
1445 continue;
1446 }
1447 if (is_uniform(*declVar)) {
1448 this->gatherUniforms(declVar->fType, declVar->fName);
1449 } else {
1450 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
1451 }
1452 }
1453 }
1454 }
1455 for (const auto& pe : fProgram) {
1456 if (pe.fKind == ProgramElement::kFunction_Kind) {
1457 FunctionDefinition& f = (FunctionDefinition&) pe;
1458 fFunctions.push_back(&f);
1459 this->writeFunction(f);
1460 }
1461 }
1462 return fErrors.errorCount() == 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001463}
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001464
1465} // namespace