blob: 75b3d22a0ec9bbf29b3ea1b49678d753cc0699c9 [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 Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -050017 { "cos", ByteCode::Instruction::kCos },
Brian Osman886af0d2019-07-26 15:12:56 -040018 { "dot", SpecialIntrinsic::kDot },
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -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)};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040062 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040063 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -0500114 SkASSERT(false);
115 return ByteCode::Pointer{0};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400116 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -0500153 return result.offset(*this, offset);
Brian Osman07c117b2019-05-23 12:51:06 -0700154 }
155 case Expression::kIndex_Kind: {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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();
Brian Osman869a3e82019-07-18 17:00:34 -0400162 if (index < 0 || index >= length) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500163 fErrors.error(idx.fIndex->fOffset, "Array index out of bounds");
164 return result;
Brian Osman869a3e82019-07-18 17:00:34 -0400165 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500166 return result.offset(*this, index * stride);
Brian Osman07c117b2019-05-23 12:51:06 -0700167 } else {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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);
Brian Osman07c117b2019-05-23 12:51:06 -0700183 }
Brian Osman07c117b2019-05-23 12:51:06 -0700184 }
Brian Osman0785db02019-05-24 14:19:11 -0400185 case Expression::kSwizzle_Kind: {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500186 const Swizzle& s = (const Swizzle&) expr;
Brian Osman0785db02019-05-24 14:19:11 -0400187 SkASSERT(swizzle_is_simple(s));
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -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 Nicholas2cde3a12020-01-21 09:23:13 -0500196 return ByteCode::Pointer{0};
Brian Osman07c117b2019-05-23 12:51:06 -0700197 }
198}
199
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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);
Brian Osman1e855b22019-05-29 15:21:52 -0400205 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500206 case Expression::kIndex_Kind: {
207 const IndexExpression& idx = (const IndexExpression&) expr;
208 return this->getStorage(*idx.fBase);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500210 case Expression::kSwizzle_Kind: {
211 const Swizzle& s = (const Swizzle&) expr;
212 return this->getStorage(*s.fBase);
Ethan Nicholasd166d2e2019-09-23 11:43:45 -0400213 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400214 case Expression::kVariableReference_Kind: {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500215 const Variable& var = ((const VariableReference&) expr).fVariable;
216 return var.fStorage;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400217 }
218 default:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400219 SkASSERT(false);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500220 return Variable::kLocal_Storage;
Brian Osman3e29f1d2019-05-28 09:35:05 -0400221 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400222}
223
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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}
Ethan Nicholas91164d12019-05-15 15:29:54 -0400248
Ethan Nicholas2cde3a12020-01-21 09:23:13 -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
274class ByteCodeSimpleLValue : public ByteCodeGenerator::LValue {
275public:
276 ByteCodeSimpleLValue(ByteCodeGenerator* generator, ByteCodeGenerator::Location location,
277 int count, ByteCode::Instruction load, ByteCode::Instruction store)
278 : INHERITED(*generator)
279 , fLocation(location)
280 , fCount(count)
281 , fLoad(load)
282 , fStore(store) {}
283
284 void load(ByteCode::Register result) override {
285 for (int i = 0; i < fCount; ++i) {
286 ByteCodeGenerator::Location final = fLocation.offset(fGenerator, i);
287 fGenerator.write(fLoad);
288 fGenerator.write(result + i);
289 fGenerator.write(final);
290 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400291 }
292
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500293 void store(ByteCode::Register src) override {
294 for (int i = 0; i < fCount; ++i) {
295 ByteCodeGenerator::Location final = fLocation.offset(fGenerator, i);
296 fGenerator.write(fStore);
297 fGenerator.write(final);
298 fGenerator.write(src + i);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400299 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400300 }
301
302private:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500303 ByteCodeGenerator::Location fLocation;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400304
305 int fCount;
306
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500307 ByteCode::Instruction fLoad;
308
309 ByteCode::Instruction fStore;
310
311 typedef ByteCodeGenerator::LValue INHERITED;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400312};
313
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400314class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
315public:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500316 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle* swizzle)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400317 : INHERITED(*generator)
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500318 , fSwizzle(*swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400319
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500320 void load(ByteCode::Register result) override {
321 fGenerator.writeSwizzle(fSwizzle, result);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400322 }
323
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500324 void store(ByteCode::Register src) override {
325 ByteCodeGenerator::Location target = fGenerator.getLocation(*fSwizzle.fBase);
326 ByteCode::Instruction inst = fGenerator.getStoreInstruction(
327 target,
328 fGenerator.getStorage(*fSwizzle.fBase));
329 for (size_t i = 0; i < fSwizzle.fComponents.size(); ++i) {
330 ByteCodeGenerator::Location final = target.offset(fGenerator, fSwizzle.fComponents[i]);
331 fGenerator.write(inst);
332 fGenerator.write(final);
333 fGenerator.write(src + i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400334 }
335 }
336
337private:
338 const Swizzle& fSwizzle;
339
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500340 typedef ByteCodeGenerator::LValue INHERITED;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400341};
342
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500343class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400344public:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500345 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400346 : INHERITED(*generator)
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500347 , fIndex(index)
348 , fSlotCount(ByteCodeGenerator::SlotCount(value.type())) {
349 SkASSERT(fSlotCount <= 4);
Brian Osman1091f022019-05-16 09:42:16 -0400350 }
351
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500352 void load(ByteCode::Register result) override {
353 fGenerator.write(ByteCode::Instruction::kReadExternal);
354 fGenerator.write(result);
355 fGenerator.write((uint8_t) fSlotCount);
356 fGenerator.write((uint8_t) fIndex);
357 }
358
359 void store(ByteCode::Register src) override {
360 fGenerator.write(ByteCode::Instruction::kWriteExternal);
361 fGenerator.write((uint8_t) fIndex);
362 fGenerator.write((uint8_t) fSlotCount);
363 fGenerator.write(src);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400364 }
365
366private:
367 typedef LValue INHERITED;
368
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500369 int fIndex;
370
371 int fSlotCount;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400372};
373
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500374std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& expr) {
375 switch (expr.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400376 case Expression::kExternalValue_Kind: {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500377 ExternalValue* value = ((ExternalValueReference&) expr).fValue;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400378 int index = fOutput->fExternalValues.size();
379 fOutput->fExternalValues.push_back(value);
380 SkASSERT(index <= 255);
381 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
382 }
Brian Osman07c117b2019-05-23 12:51:06 -0700383 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400384 case Expression::kIndex_Kind:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500385 case Expression::kVariableReference_Kind: {
386 Location location = this->getLocation(expr);
387 Variable::Storage storage = this->getStorage(expr);
388 ByteCode::Instruction loadInst = this->getLoadInstruction(location, storage);
389 ByteCode::Instruction storeInst = this->getStoreInstruction(location, storage);
390 return std::unique_ptr<LValue>(new ByteCodeSimpleLValue(this, location,
391 SlotCount(expr.fType),
392 loadInst, storeInst));
Brian Osman0785db02019-05-24 14:19:11 -0400393 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500394 case Expression::kSwizzle_Kind:
395 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, &(Swizzle&) expr));
396 default:
397 ABORT("unsupported lvalue\n");
398 }
399}
400
401ByteCode::Register ByteCodeGenerator::next(int count) {
402 SkASSERT(fNextRegister + count <= ByteCode::kRegisterMax);
403 fNextRegister += count;
404 return ByteCode::Register{(uint16_t) (fNextRegister - count)};
405}
406
407static TypeCategory type_category(const Type& type) {
408 switch (type.kind()) {
409 case Type::Kind::kVector_Kind:
410 case Type::Kind::kMatrix_Kind:
411 return type_category(type.componentType());
412 default:
413 String name = type.displayName();
414 if (name == "bool") {
415 return TypeCategory::kBool;
416 } else if (name == "int" || name == "short") {
417 return TypeCategory::kSigned;
418 } else if (name == "uint" || name == "ushort") {
419 return TypeCategory::kUnsigned;
420 } else {
421 SkASSERT(name == "float" || name == "half");
422 return TypeCategory::kFloat;
423 }
424 ABORT("unsupported type: %s\n", name.c_str());
425 }
426}
427
428void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCode::Instruction s,
429 ByteCode::Instruction u, ByteCode::Instruction f) {
430 switch (type_category(type)) {
431 case TypeCategory::kSigned:
432 this->write(s);
433 break;
434 case TypeCategory::kUnsigned:
435 this->write(u);
436 break;
437 case TypeCategory::kFloat: {
438 this->write(f);
439 break;
440 }
441 default:
442 SkASSERT(false);
443 }
444}
445
446void ByteCodeGenerator::writeBinaryInstruction(const Type& operandType,
447 ByteCode::Register left,
448 ByteCode::Register right,
449 ByteCode::Instruction s,
450 ByteCode::Instruction u,
451 ByteCode::Instruction f,
452 ByteCode::Register result) {
453 for (int i = 0; i < SlotCount(operandType); ++i) {
454 this->writeTypedInstruction(operandType, s, u, f);
455 this->write(result + i);
456 this->write(left + i);
457 this->write(right + i);
458 }
459}
460
461void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
462 ByteCode::Register result) {
463 if (b.fOperator == Token::Kind::EQ) {
464 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
465 this->writeExpression(*b.fRight, result);
466 lvalue->store(result);
467 return;
468 }
469 const Type& lType = b.fLeft->fType;
470 const Type& rType = b.fRight->fType;
471 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
472 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
473 const Type* operandType;
474 if (!lVecOrMtx && rVecOrMtx) {
475 operandType = &rType;
476 } else {
477 operandType = &lType;
478 }
479 Token::Kind op;
480 std::unique_ptr<LValue> lvalue;
481 ByteCode::Register left;
482 switch (b.fOperator) {
483 case Token::Kind::LOGICALAND:
484 case Token::Kind::LOGICALANDEQ:
485 case Token::Kind::LOGICALOR:
486 case Token::Kind::LOGICALOREQ:
487 left = result;
488 break;
489 default:
490 left = this->next(SlotCount(*operandType));
491 }
492 if (is_assignment(b.fOperator)) {
493 lvalue = this->getLValue(*b.fLeft);
494 lvalue->load(left);
495 op = remove_assignment(b.fOperator);
496 } else {
497 this->writeExpression(*b.fLeft, left);
498 op = b.fOperator;
499 if (!lVecOrMtx && rVecOrMtx) {
500 for (int i = 1; i < SlotCount(rType); ++i) {
501 this->write(ByteCode::Instruction::kCopy);
502 this->write(left + i);
503 this->write(left);
504 }
505 }
506 }
507 SkDEBUGCODE(TypeCategory tc = type_category(lType));
508 int count = std::max(SlotCount(lType), SlotCount(rType));
509 switch (op) {
510 case Token::Kind::LOGICALAND: {
511 SkASSERT(left.fIndex == result.fIndex);
512 this->write(ByteCode::Instruction::kMaskPush);
513 ++fConditionCount;
514 this->write(left);
515 this->write(ByteCode::Instruction::kBranchIfAllFalse);
516 DeferredLocation falseLocation(this);
517 SkASSERT(SlotCount(b.fRight->fType) == 1);
518 ByteCode::Register right = this->next(1);
519 this->writeExpression(*b.fRight, right);
520 this->write(ByteCode::Instruction::kAnd);
521 this->write(result);
522 this->write(left);
523 this->write(right);
524 falseLocation.set();
525 --fConditionCount;
526 this->write(ByteCode::Instruction::kMaskPop);
527 return;
528 }
529 case Token::Kind::LOGICALOR: {
530 SkASSERT(left.fIndex == result.fIndex);
531 ByteCode::Register mask = this->next(1);
532 this->write(ByteCode::Instruction::kNot);
533 this->write(mask);
534 this->write(left);
535 this->write(ByteCode::Instruction::kMaskPush);
536 ++fConditionCount;
537 this->write(mask);
538 this->write(ByteCode::Instruction::kBranchIfAllFalse);
539 DeferredLocation falseLocation(this);
540 SkASSERT(SlotCount(b.fRight->fType) == 1);
541 ByteCode::Register right = this->next(1);
542 this->writeExpression(*b.fRight, right);
543 this->write(ByteCode::Instruction::kOr);
544 this->write(result);
545 this->write(left);
546 this->write(right);
547 falseLocation.set();
548 --fConditionCount;
549 this->write(ByteCode::Instruction::kMaskPop);
550 return;
551 }
552 case Token::Kind::SHL:
553 case Token::Kind::SHR: {
554 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
555 tc == SkSL::TypeCategory::kUnsigned));
556 if (!b.fRight->isConstant()) {
557 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
558 return;
559 }
560 int64_t shift = b.fRight->getConstantInt();
561 if (shift < 0 || shift > 31) {
562 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
563 return;
564 }
565
566 if (op == Token::Kind::SHL) {
567 this->write(ByteCode::Instruction::kShiftLeft);
568 } else {
569 this->write(type_category(lType) == TypeCategory::kSigned
570 ? ByteCode::Instruction::kShiftRightS
571 : ByteCode::Instruction::kShiftRightU);
572 }
573 this->write(result);
574 this->write(left);
575 this->write((uint8_t) shift);
576 return;
577 }
578 case Token::Kind::STAR:
579 // Special case for M*V, V*M, M*M (but not V*V!)
580 if (lType.columns() > 1 && rType.columns() > 1 &&
581 (lType.rows() > 1 || rType.rows() > 1)) {
582 ByteCode::Register right = this->next(SlotCount(rType));
583 this->writeExpression(*b.fRight, right);
584 int rCols = rType.columns(),
585 rRows = rType.rows(),
586 lCols = lType.columns(),
587 lRows = lType.rows();
588 // M*V treats the vector as a column
589 if (rType.kind() == Type::kVector_Kind) {
590 std::swap(rCols, rRows);
591 }
592 SkASSERT(lCols == rRows);
593 SkASSERT(SlotCount(b.fType) == lRows * rCols);
594 this->write(ByteCode::Instruction::kMatrixMultiply);
595 this->write(result);
596 this->write(left);
597 this->write(right);
598 this->write((uint8_t) lCols);
599 this->write((uint8_t) lRows);
600 this->write((uint8_t) rCols);
601 return;
602 }
603
604 default:
605 break;
606 }
607 ByteCode::Register right = this->next(SlotCount(*operandType));
608 this->writeExpression(*b.fRight, right);
609 if (lVecOrMtx && !rVecOrMtx) {
610 for (int i = 1; i < SlotCount(*operandType); ++i) {
611 this->write(ByteCode::Instruction::kCopy);
612 this->write(right + i);
613 this->write(right);
614 }
615 }
616 switch (op) {
617 case Token::Kind::EQEQ:
618 this->writeBinaryInstruction(*operandType, left, right,
619 ByteCode::Instruction::kCompareEQI,
620 ByteCode::Instruction::kCompareEQI,
621 ByteCode::Instruction::kCompareEQF,
622 result);
623 // Collapse to a single bool
624 for (int i = 1; i < count; ++i) {
625 this->write(ByteCode::Instruction::kAnd);
626 this->write(result);
627 this->write(result);
628 this->write(result + i);
629 }
630 break;
631 case Token::Kind::GT:
632 this->writeBinaryInstruction(*operandType, left, right,
633 ByteCode::Instruction::kCompareGTS,
634 ByteCode::Instruction::kCompareGTU,
635 ByteCode::Instruction::kCompareGTF,
636 result);
637 break;
638 case Token::Kind::GTEQ:
639 this->writeBinaryInstruction(*operandType, left, right,
640 ByteCode::Instruction::kCompareGTEQS,
641 ByteCode::Instruction::kCompareGTEQU,
642 ByteCode::Instruction::kCompareGTEQF,
643 result);
644 break;
645 case Token::Kind::LT:
646 this->writeBinaryInstruction(*operandType, left, right,
647 ByteCode::Instruction::kCompareLTS,
648 ByteCode::Instruction::kCompareLTU,
649 ByteCode::Instruction::kCompareLTF,
650 result);
651 break;
652 case Token::Kind::LTEQ:
653 this->writeBinaryInstruction(*operandType, left, right,
654 ByteCode::Instruction::kCompareLTEQS,
655 ByteCode::Instruction::kCompareLTEQU,
656 ByteCode::Instruction::kCompareLTEQF,
657 result);
658 break;
659 case Token::Kind::MINUS:
660 this->writeBinaryInstruction(*operandType, left, right,
661 ByteCode::Instruction::kSubtractI,
662 ByteCode::Instruction::kSubtractI,
663 ByteCode::Instruction::kSubtractF,
664 result);
665 break;
666 case Token::Kind::NEQ:
667 this->writeBinaryInstruction(*operandType, left, right,
668 ByteCode::Instruction::kCompareNEQI,
669 ByteCode::Instruction::kCompareNEQI,
670 ByteCode::Instruction::kCompareNEQF,
671 result);
672 // Collapse to a single bool
673 for (int i = 1; i < count; ++i) {
674 this->write(ByteCode::Instruction::kOr);
675 this->write(result);
676 this->write(result);
677 this->write(result + i);
678 }
679 break;
680 case Token::Kind::PERCENT:
681 this->writeBinaryInstruction(*operandType, left, right,
682 ByteCode::Instruction::kRemainderS,
683 ByteCode::Instruction::kRemainderU,
684 ByteCode::Instruction::kRemainderF,
685 result);
686 break;
687 case Token::Kind::PLUS:
688 this->writeBinaryInstruction(*operandType, left, right,
689 ByteCode::Instruction::kAddI,
690 ByteCode::Instruction::kAddI,
691 ByteCode::Instruction::kAddF,
692 result);
693 break;
694 case Token::Kind::SLASH:
695 this->writeBinaryInstruction(*operandType, left, right,
696 ByteCode::Instruction::kDivideS,
697 ByteCode::Instruction::kDivideU,
698 ByteCode::Instruction::kDivideF,
699 result);
700 break;
701 case Token::Kind::STAR:
702 this->writeBinaryInstruction(*operandType, left, right,
703 ByteCode::Instruction::kMultiplyI,
704 ByteCode::Instruction::kMultiplyI,
705 ByteCode::Instruction::kMultiplyF,
706 result);
707 break;
708 case Token::Kind::LOGICALXOR: {
709 SkASSERT(tc == SkSL::TypeCategory::kBool);
710 this->write(ByteCode::Instruction::kXor);
711 this->write(result);
712 this->write(left);
713 this->write(right);
714 break;
715 }
716 case Token::Kind::BITWISEAND: {
717 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
718 this->write(ByteCode::Instruction::kAnd);
719 this->write(result);
720 this->write(left);
721 this->write(right);
722 break;
723 }
724 case Token::Kind::BITWISEOR: {
725 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
726 this->write(ByteCode::Instruction::kOr);
727 this->write(result);
728 this->write(left);
729 this->write(right);
730 break;
731 }
732 case Token::Kind::BITWISEXOR: {
733 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
734 this->write(ByteCode::Instruction::kXor);
735 this->write(result);
736 this->write(left);
737 this->write(right);
738 break;
739 }
740 default:
741 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
742 Compiler::OperatorName(op)));
743 break;
744 }
745 if (lvalue) {
746 lvalue->store(result);
747 }
748}
749
750void ByteCodeGenerator::writeConstructor(const Constructor& c, ByteCode::Register result) {
751 if (c.fType.rows() > 1) {
752 if (c.fArguments.size() == 1) {
753 if (SlotCount(c.fArguments[0]->fType) == 1) {
754 ByteCode::Register v = this->next(1);
755 this->writeExpression(*c.fArguments[0], v);
756 this->write(ByteCode::Instruction::kScalarToMatrix);
757 this->write(result);
758 this->write(v);
759 this->write((uint8_t) c.fType.columns());
760 this->write((uint8_t) c.fType.rows());
761 return;
762 } else if (c.fArguments[0]->fType.rows() > 1) {
763 ByteCode::Register v = this->next(SlotCount(c.fArguments[0]->fType));
764 this->writeExpression(*c.fArguments[0], v);
765 this->write(ByteCode::Instruction::kMatrixToMatrix);
766 this->write(result);
767 this->write(v);
768 this->write((uint8_t) c.fArguments[0]->fType.columns());
769 this->write((uint8_t) c.fArguments[0]->fType.rows());
770 this->write((uint8_t) c.fType.columns());
771 this->write((uint8_t) c.fType.rows());
772 return;
773 }
774 }
775 int offset = 0;
776 for (const auto& arg : c.fArguments) {
777 this->writeExpression(*arg, ByteCode::Register{(uint16_t) (result.fIndex + offset)});
778 offset += SlotCount(arg->fType);
779 }
780 return;
781 }
782 if (c.fArguments.size() == 1 && c.fArguments[0]->fType.columns() == 1 &&
783 c.fType.columns() > 1) {
784 SkASSERT(SlotCount(c.fArguments[0]->fType) == 1);
785 ByteCode::Register v = result;
786 this->writeExpression(*c.fArguments[0], v);
787 for (int i = 1; i < c.fType.columns(); ++i) {
788 this->write(ByteCode::Instruction::kCopy);
789 this->write(v + i);
790 this->write(v);
791 }
792 return;
793 }
794 ByteCode::Instruction inst;
795 switch (type_category(c.fArguments[0]->fType)) {
796 case TypeCategory::kSigned:
797 if (type_category(c.fType) == TypeCategory::kFloat) {
798 inst = ByteCode::Instruction::kSignedToFloat;
799 } else {
800 inst = ByteCode::Instruction::kNop;
801 }
802 break;
803 case TypeCategory::kUnsigned:
804 if (type_category(c.fType) == TypeCategory::kFloat) {
805 inst = ByteCode::Instruction::kUnsignedToFloat;
806 } else {
807 inst = ByteCode::Instruction::kNop;
808 }
809 break;
810 case TypeCategory::kFloat:
811 if (type_category(c.fType) == TypeCategory::kSigned) {
812 inst = ByteCode::Instruction::kFloatToSigned;
813 } else if (type_category(c.fType) == TypeCategory::kUnsigned) {
814 inst = ByteCode::Instruction::kFloatToUnsigned;
815 } else {
816 inst = ByteCode::Instruction::kNop;
817 }
818 break;
819 default:
820 SkASSERT(false);
821 return;
822 }
823 ByteCode::Register values;
824 if (inst == ByteCode::Instruction::kNop) {
825 values = result;
826 } else {
827 values = this->next(SlotCount(c.fType));
828 }
829 ByteCode::Register v = values;
830 for (size_t i = 0; i < c.fArguments.size(); ++i) {
831 this->writeExpression(*c.fArguments[i], v);
832 v.fIndex += SlotCount(c.fArguments[i]->fType);
833 }
834 if (inst != ByteCode::Instruction::kNop) {
835 v = values;
836 ByteCode::Register target = result;
837 for (size_t i = 0; i < c.fArguments.size(); ++i) {
838 int count = SlotCount(c.fArguments[i]->fType);
839 for (int j = 0; j < count; ++j) {
840 this->write(inst);
841 this->write(target);
842 ++target.fIndex;
843 this->write(v + j);
844 }
845 }
846 }
847}
848
849void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f,
850 ByteCode::Register result) {
851 int argumentCount = 0;
852 for (const auto& arg : f.fArguments) {
853 argumentCount += SlotCount(arg->fType);
854 }
855 ByteCode::Register args = this->next(argumentCount);
856 argumentCount = 0;
857 for (const auto& arg : f.fArguments) {
858 this->writeExpression(*arg, args + argumentCount);
859 argumentCount += SlotCount(arg->fType);
860 }
861 this->write(ByteCode::Instruction::kCallExternal);
862 this->write(result);
863 int index = fOutput->fExternalValues.size();
864 fOutput->fExternalValues.push_back(f.fFunction);
865 SkASSERT(index <= 255);
866 this->write((uint8_t) index);
867 SkASSERT(SlotCount(f.fType) <= 255);
868 this->write((uint8_t) SlotCount(f.fType));
869 this->write(args);
870 SkASSERT(argumentCount <= 255);
871 this->write((uint8_t) argumentCount);
872}
873
874void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e,
875 ByteCode::Register result) {
876 this->write(ByteCode::Instruction::kReadExternal);
877 this->write(result);
878 this->write((uint8_t) SlotCount(e.fValue->type()));
879 int index = fOutput->fExternalValues.size();
880 fOutput->fExternalValues.push_back(e.fValue);
881 SkASSERT(index <= 255);
882 this->write((uint8_t) index);
883}
884
885void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c, Intrinsic intrinsic,
886 ByteCode::Register result) {
887 if (intrinsic.fIsSpecial) {
888 switch (intrinsic.fValue.fSpecial) {
889 case SpecialIntrinsic::kDot: {
890 SkASSERT(c.fArguments.size() == 2);
891 int count = SlotCount(c.fArguments[0]->fType);
892 ByteCode::Register left = this->next(count);
893 this->writeExpression(*c.fArguments[0], left);
894 ByteCode::Register right = this->next(count);
895 this->writeExpression(*c.fArguments[1], right);
896 ByteCode::Register product = this->next(count);
897 for (int i = 0; i < count; ++i) {
898 this->writeTypedInstruction(c.fType,
899 ByteCode::Instruction::kMultiplyI,
900 ByteCode::Instruction::kMultiplyI,
901 ByteCode::Instruction::kMultiplyF);
902 this->write(product + i);
903 this->write(left + i);
904 this->write(right + i);
905 }
906 ByteCode::Register total = product;
907 for (int i = 1; i < count; ++i) {
908 this->writeTypedInstruction(c.fType,
909 ByteCode::Instruction::kAddI,
910 ByteCode::Instruction::kAddI,
911 ByteCode::Instruction::kAddF);
912 ByteCode::Register sum = i == count - 1 ? result : this->next(1);
913 this->write(sum);
914 this->write(total);
915 this->write(product + i);
916 total = sum;
917 }
918 break;
919 }
920 case SpecialIntrinsic::kInverse: {
921 SkASSERT(c.fArguments.size() == 1);
922 int count = SlotCount(c.fArguments[0]->fType);
923 ByteCode::Register arg = this->next(count);
924 this->writeExpression(*c.fArguments[0], arg);
925 switch (SlotCount(c.fArguments[0]->fType)) {
926 case 4: this->write(ByteCode::Instruction::kInverse2x2); break;
927 case 9: this->write(ByteCode::Instruction::kInverse3x3); break;
928 case 16: this->write(ByteCode::Instruction::kInverse4x4); break;
929 default: SkASSERT(false);
930 }
931 this->write(result);
932 this->write(arg);
933 break;
934 }
935 }
936 } else {
937 std::vector<ByteCode::Register> argRegs;
938 for (const auto& expr : c.fArguments) {
939 ByteCode::Register reg = this->next(SlotCount(expr->fType));
940 this->writeExpression(*expr, reg);
941 argRegs.push_back(reg);
942 }
943 this->write(intrinsic.fValue.fInstruction);
944 if (c.fType.fName != "void") {
945 this->write(result);
946 }
947 for (ByteCode::Register arg : argRegs) {
948 this->write(arg);
949 }
950 }
951}
952
953void ByteCodeGenerator::writeFunctionCall(const FunctionCall& c, ByteCode::Register result) {
954 auto found = fIntrinsics.find(c.fFunction.fName);
955 if (found != fIntrinsics.end()) {
956 return this->writeIntrinsicCall(c, found->second, result);
957 }
958 int argCount = c.fArguments.size();
959 std::vector<std::unique_ptr<LValue>> lvalues;
960 int parameterSlotCount = 0;
961 for (const auto& p : c.fFunction.fParameters) {
962 parameterSlotCount += SlotCount(p->fType);
963 }
964 ByteCode::Register argStart = this->next(parameterSlotCount);
965 ByteCode::Register nextArg = argStart;
966 for (int i = 0; i < argCount; ++i) {
967 const auto& param = c.fFunction.fParameters[i];
968 const auto& arg = c.fArguments[i];
969 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
970 lvalues.emplace_back(this->getLValue(*arg));
971 lvalues.back()->load(nextArg);
972 } else {
973 this->writeExpression(*arg, nextArg);
974 }
975 nextArg.fIndex += SlotCount(arg->fType);
976 }
977 // Find the index of the function we're calling. We explicitly do not allow calls to functions
978 // before they're defined. This is an easy-to-understand rule that prevents recursion.
979 size_t idx;
980 for (idx = 0; idx < fFunctions.size(); ++idx) {
981 if (c.fFunction.matches(fFunctions[idx]->fDeclaration)) {
982 break;
983 }
984 }
985 if (idx > 255) {
986 fErrors.error(c.fOffset, "Function count limit exceeded");
987 return;
988 } else if (idx >= fOutput->fFunctions.size()) {
989 fErrors.error(c.fOffset, "Call to undefined function");
990 return;
991 }
992
993 this->write(ByteCode::Instruction::kCall);
994 this->write(result);
995 this->write((uint8_t) idx);
996 this->write(argStart);
997 nextArg = argStart;
998 auto lvalue = lvalues.begin();
999 for (int i = 0; i < argCount; ++i) {
1000 const auto& param = c.fFunction.fParameters[i];
1001 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1002 (*(lvalue++))->store(nextArg);
1003 }
1004 nextArg.fIndex += SlotCount(param->fType);
1005 }
1006}
1007
1008void ByteCodeGenerator::incOrDec(Token::Kind op, Expression& operand, bool prefix,
1009 ByteCode::Register result) {
1010 SkASSERT(op == Token::Kind::PLUSPLUS || op == Token::Kind::MINUSMINUS);
1011 std::unique_ptr<LValue> lvalue = this->getLValue(operand);
1012 SkASSERT(SlotCount(operand.fType) == 1);
1013 ByteCode::Register value;
1014 if (prefix) {
1015 value = this->next(1);
1016 } else {
1017 value = result;
1018 }
1019 lvalue->load(value);
1020 ByteCode::Register one = this->next(1);
1021 this->write(ByteCode::Instruction::kImmediate);
1022 this->write(one);
1023 if (type_category(operand.fType) == TypeCategory::kFloat) {
1024 this->write(ByteCode::Immediate(1.0f));
1025 } else {
1026 this->write(ByteCode::Immediate((int32_t) 1));
1027 }
1028 if (op == Token::Kind::PLUSPLUS) {
1029 this->writeTypedInstruction(operand.fType,
1030 ByteCode::Instruction::kAddI,
1031 ByteCode::Instruction::kAddI,
1032 ByteCode::Instruction::kAddF);
1033 } else {
1034 this->writeTypedInstruction(operand.fType,
1035 ByteCode::Instruction::kSubtractI,
1036 ByteCode::Instruction::kSubtractI,
1037 ByteCode::Instruction::kSubtractF);
1038 }
1039 if (prefix) {
1040 this->write(result);
1041 this->write(value);
1042 this->write(one);
1043 lvalue->store(result);
1044 } else {
1045 ByteCode::Register temp = this->next(1);
1046 this->write(temp);
1047 this->write(value);
1048 this->write(one);
1049 lvalue->store(temp);
1050 }
1051}
1052
1053void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p,
1054 ByteCode::Register result) {
1055 this->incOrDec(p.fOperator, *p.fOperand, false, result);
1056}
1057
1058void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p,
1059 ByteCode::Register result) {
1060 switch (p.fOperator) {
1061 case Token::Kind::PLUSPLUS:
1062 case Token::Kind::MINUSMINUS: {
1063 return this->incOrDec(p.fOperator, *p.fOperand, true, result);
1064 }
1065 case Token::Kind::MINUS: {
1066 ByteCode::Register src = this->next(SlotCount(p.fType));
1067 this->writeExpression(*p.fOperand, src);
1068 for (int i = 0; i < SlotCount(p.fType); ++i) {
1069 this->writeTypedInstruction(p.fType,
1070 ByteCode::Instruction::kNegateS,
1071 ByteCode::Instruction::kNegateS,
1072 ByteCode::Instruction::kNegateF);
1073 this->write(result + i);
1074 this->write(src + i);
1075 }
1076 break;
1077 }
1078 case Token::Kind::LOGICALNOT:
1079 case Token::Kind::BITWISENOT: {
1080 ByteCode::Register src = this->next(SlotCount(p.fType));
1081 this->writeExpression(*p.fOperand, src);
1082 for (int i = 0; i < SlotCount(p.fType); ++i) {
1083 this->write(ByteCode::Instruction::kNot);
1084 this->write(result + i);
1085 this->write(src + i);
1086 }
1087 break;
1088 }
1089 default:
1090 SkASSERT(false);
1091 }
1092}
1093
1094void ByteCodeGenerator::writeSwizzle(const Swizzle& s, ByteCode::Register result) {
1095 if (swizzle_is_simple(s)) {
1096 this->writeVariableExpression(s, result);
1097 return;
1098 }
1099 ByteCode::Register base = this->writeExpression(*s.fBase);
1100 for (int i = 0; i < (int) s.fComponents.size(); ++i) {
1101 this->write(ByteCode::Instruction::kCopy);
1102 this->write(result + i);
1103 this->write(base + s.fComponents[i]);
1104 }
1105}
1106
1107void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
1108 ByteCode::Register result) {
1109 int count = SlotCount(t.fType);
1110 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1111 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1112
1113 ByteCode::Register test = this->writeExpression(*t.fTest);
1114 this->write(ByteCode::Instruction::kMaskPush);
1115 ++fConditionCount;
1116 this->write(test);
1117 ByteCode::Register ifTrue = this->writeExpression(*t.fIfTrue);
1118 this->write(ByteCode::Instruction::kMaskNegate);
1119 ByteCode::Register ifFalse = this->writeExpression(*t.fIfFalse);
1120 --fConditionCount;
1121 this->write(ByteCode::Instruction::kMaskPop);
1122 for (int i = 0; i < count; ++i) {
1123 this->write(ByteCode::Instruction::kSelect);
1124 this->write(result + i);
1125 this->write(test);
1126 this->write(ifTrue + i);
1127 this->write(ifFalse + i);
1128 }
1129}
1130
1131void ByteCodeGenerator::writeVariableExpression(const Expression& expr,
1132 ByteCode::Register result) {
1133 ByteCodeGenerator::Location location = this->getLocation(expr);
1134 int count = SlotCount(expr.fType);
1135 for (int i = 0; i < count; ++i) {
1136 ByteCodeGenerator::Location final = location.offset(*this, i);
1137 this->write(this->getLoadInstruction(location, this->getStorage(expr)));
1138 this->write(result + i);
1139 this->write(final);
1140 }
1141}
1142
1143void ByteCodeGenerator::writeExpression(const Expression& expr, ByteCode::Register result) {
1144 switch (expr.fKind) {
1145 case Expression::kBoolLiteral_Kind: {
1146 this->write(ByteCode::Instruction::kImmediate);
1147 this->write(result);
1148 this->write(ByteCode::Immediate((int32_t) (((BoolLiteral&) expr).fValue ? -1 : 0)));
1149 break;
1150 }
1151 case Expression::kBinary_Kind: {
1152 this->writeBinaryExpression((BinaryExpression&) expr, result);
1153 break;
1154 }
1155 case Expression::kConstructor_Kind: {
1156 this->writeConstructor((Constructor&) expr, result);
1157 break;
1158 }
1159 case Expression::kExternalFunctionCall_Kind:
1160 this->writeExternalFunctionCall((ExternalFunctionCall&) expr, result);
1161 break;
1162 case Expression::kExternalValue_Kind:
1163 this->writeExternalValue((ExternalValueReference&) expr, result);
1164 break;
1165 case Expression::kFloatLiteral_Kind: {
1166 this->write(ByteCode::Instruction::kImmediate);
1167 this->write(result);
1168 this->write(ByteCode::Immediate((float) ((FloatLiteral&) expr).fValue));
1169 break;
1170 }
1171 case Expression::kFunctionCall_Kind: {
1172 this->writeFunctionCall((FunctionCall&) expr, result);
1173 break;
1174 }
1175 case Expression::kIntLiteral_Kind: {
1176 this->write(ByteCode::Instruction::kImmediate);
1177 this->write(result);
1178 this->write(ByteCode::Immediate((int32_t) ((IntLiteral&) expr).fValue));
1179 break;
1180 }
1181 case Expression::kPostfix_Kind:
1182 this->writePostfixExpression((PostfixExpression&) expr, result);
1183 break;
1184 case Expression::kPrefix_Kind:
1185 this->writePrefixExpression((PrefixExpression&) expr, result);
1186 break;
1187 case Expression::kSwizzle_Kind:
1188 this->writeSwizzle((Swizzle&) expr, result);
1189 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001190 case Expression::kTernary_Kind:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001191 this->writeTernaryExpression((TernaryExpression&) expr, result);
1192 break;
1193 case Expression::kFieldAccess_Kind:
1194 case Expression::kIndex_Kind:
1195 case Expression::kVariableReference_Kind:
1196 this->writeVariableExpression(expr, result);
1197 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001198 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001199#ifdef SK_DEBUG
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001200 ABORT("unsupported lvalue %s\n", expr.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001201#endif
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001202 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001203 }
1204}
1205
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001206ByteCode::Register ByteCodeGenerator::writeExpression(const Expression& expr) {
1207 ByteCode::Register result = this->next(SlotCount(expr.fType));
1208 this->writeExpression(expr, result);
1209 return result;
1210}
1211
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001212void ByteCodeGenerator::writeBlock(const Block& b) {
1213 for (const auto& s : b.fStatements) {
1214 this->writeStatement(*s);
1215 }
1216}
1217
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001218void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001219 this->write(ByteCode::Instruction::kLoopBegin);
1220 ++fConditionCount;
1221 SkASSERT(fCode->size() < ByteCode::kPointerMax);
1222 ByteCode::Pointer start{(uint16_t) fCode->size()};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001223 this->writeStatement(*d.fStatement);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001224 ByteCode::Register test = this->writeExpression(*d.fTest);
1225 this->write(ByteCode::Instruction::kLoopNext);
1226 this->write(ByteCode::Instruction::kLoopMask);
1227 this->write(test);
1228 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001229 DeferredLocation endLocation(this);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001230 this->write(ByteCode::Instruction::kBranch);
1231 this->write(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001232 endLocation.set();
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001233 --fConditionCount;
1234 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001235}
1236
1237void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001238 if (f.fInitializer) {
1239 this->writeStatement(*f.fInitializer);
1240 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001241 this->write(ByteCode::Instruction::kLoopBegin);
1242 ++fConditionCount;
1243 ByteCode::Pointer start{(uint16_t) fCode->size()};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001244 if (f.fTest) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001245 ByteCode::Register test = this->writeExpression(*f.fTest);
1246 this->write(ByteCode::Instruction::kLoopMask);
1247 this->write(test);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001248 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001249 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001250 DeferredLocation endLocation(this);
1251 this->writeStatement(*f.fStatement);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001252 this->write(ByteCode::Instruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001253 if (f.fNext) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001254 this->writeExpression(*f.fNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001255 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001256 this->write(ByteCode::Instruction::kBranch);
1257 this->write(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001258 endLocation.set();
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001259 --fConditionCount;
1260 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001261}
1262
1263void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001264 ByteCode::Register test = this->writeExpression(*i.fTest);
1265 this->write(ByteCode::Instruction::kMaskPush);
1266 ++fConditionCount;
1267 this->write(test);
1268 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001269 DeferredLocation falseLocation(this);
1270 this->writeStatement(*i.fIfTrue);
1271 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001272 if (i.fIfFalse) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001273 this->write(ByteCode::Instruction::kMaskNegate);
1274 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001275 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001276 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001277 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001278 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001279 --fConditionCount;
1280 this->write(ByteCode::Instruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001281}
1282
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001283void ByteCodeGenerator::writeReturn(const ReturnStatement& r) {
1284 if (fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001285 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1286 return;
1287 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001288 if (r.fExpression) {
1289 ByteCode::Register value = this->writeExpression(*r.fExpression);
1290 this->write(ByteCode::Instruction::kReturnValue);
1291 this->write(value);
1292 }
1293 else {
1294 this->write(ByteCode::Instruction::kReturn);
1295 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001296}
1297
1298void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1299 for (const auto& declStatement : v.fVars) {
1300 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001301 // we need to grab the location even if we don't use it, to ensure it
1302 // has been allocated
1303 ByteCodeGenerator::Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001304 if (decl.fValue) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001305 ByteCode::Register src = this->writeExpression(*decl.fValue);
1306 for (int i = 0; i < SlotCount(decl.fVar->fType); ++i) {
1307 ByteCodeGenerator::Location final = location.offset(*this, i);
1308 this->write(ByteCode::Instruction::kStoreStackDirect);
1309 this->write(final);
1310 this->write(src + i);
Brian Osman07c117b2019-05-23 12:51:06 -07001311 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001312 }
1313 }
1314}
1315
1316void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001317 this->write(ByteCode::Instruction::kLoopBegin);
1318 ++fConditionCount;
1319 SkASSERT(fCode->size() < ByteCode::kPointerMax);
1320 ByteCode::Pointer start{(uint16_t) fCode->size()};
1321 ByteCode::Register test = this->writeExpression(*w.fTest);
1322 this->write(ByteCode::Instruction::kLoopMask);
1323 this->write(test);
1324 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001325 DeferredLocation endLocation(this);
1326 this->writeStatement(*w.fStatement);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001327 this->write(ByteCode::Instruction::kLoopNext);
1328 this->write(ByteCode::Instruction::kBranch);
1329 this->write(start);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001330 endLocation.set();
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001331 --fConditionCount;
1332 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001333}
1334
1335void ByteCodeGenerator::writeStatement(const Statement& s) {
1336 switch (s.fKind) {
1337 case Statement::kBlock_Kind:
1338 this->writeBlock((Block&) s);
1339 break;
1340 case Statement::kBreak_Kind:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001341 this->write(ByteCode::Instruction::kBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001342 break;
1343 case Statement::kContinue_Kind:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001344 this->write(ByteCode::Instruction::kContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001345 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001346 case Statement::kDo_Kind:
1347 this->writeDoStatement((DoStatement&) s);
1348 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001349 case Statement::kExpression_Kind:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001350 this->writeExpression(*((ExpressionStatement&) s).fExpression);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001351 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001352 case Statement::kFor_Kind:
1353 this->writeForStatement((ForStatement&) s);
1354 break;
1355 case Statement::kIf_Kind:
1356 this->writeIfStatement((IfStatement&) s);
1357 break;
1358 case Statement::kNop_Kind:
1359 break;
1360 case Statement::kReturn_Kind:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001361 this->writeReturn((ReturnStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001362 break;
1363 case Statement::kVarDeclarations_Kind:
1364 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1365 break;
1366 case Statement::kWhile_Kind:
1367 this->writeWhileStatement((WhileStatement&) s);
1368 break;
1369 default:
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001370 ABORT("unsupported statement\n");
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001371 }
1372}
1373
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001374void ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
1375 fFunction = &f;
1376 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
1377 result->fReturnSlotCount = SlotCount(f.fDeclaration.fReturnType);
Brian Osman80164412019-06-07 13:00:23 -04001378 fParameterCount = 0;
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001379 fConditionCount = 0;
1380 for (const auto& p : f.fDeclaration.fParameters) {
1381 int count = SlotCount(p->fType);
1382 bool isOut = ((p->fModifiers.fFlags & Modifiers::kOut_Flag) != 0);
1383 result->fParameters.push_back(ByteCodeFunction::Parameter{count, isOut});
1384 fParameterCount += count;
1385 }
1386 result->fParameterSlotCount = fParameterCount;
1387 fCode = &result->fCode;
1388 this->writeStatement(*f.fBody);
1389 result->fStackSlotCount = fLocals.size();
1390 if (f.fDeclaration.fReturnType.fName == "void") {
1391 this->write(ByteCode::Instruction::kReturn);
1392 } else {
1393 this->write(ByteCode::Instruction::kAbort);
1394 }
1395 fOutput->fFunctions.push_back(std::move(result));
1396 SkASSERT(fConditionCount == 0);
1397}
1398
1399void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
1400 if (type.kind() == Type::kOther_Kind) {
1401 return;
1402 } else if (type.kind() == Type::kStruct_Kind) {
1403 for (const auto& f : type.fields()) {
1404 this->gatherUniforms(*f.fType, name + "." + f.fName);
1405 }
1406 } else if (type.kind() == Type::kArray_Kind) {
1407 for (int i = 0; i < type.columns(); ++i) {
1408 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
1409 }
1410 } else {
1411 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
1412 fOutput->fUniformSlotCount });
1413 fOutput->fUniformSlotCount += type.columns() * type.rows();
Brian Osman80164412019-06-07 13:00:23 -04001414 }
1415}
1416
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001417bool ByteCodeGenerator::generateCode() {
1418 fOutput->fGlobalSlotCount = 0;
1419 fOutput->fUniformSlotCount = 0;
1420 for (const auto& pe : fProgram) {
1421 if (pe.fKind == ProgramElement::kVar_Kind) {
1422 VarDeclarations& decl = (VarDeclarations&) pe;
1423 for (const auto& v : decl.fVars) {
1424 const Variable* declVar = ((VarDeclaration&) *v).fVar;
1425 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
1426 continue;
1427 }
1428 if (is_uniform(*declVar)) {
1429 this->gatherUniforms(declVar->fType, declVar->fName);
1430 } else {
1431 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
1432 }
1433 }
1434 }
1435 }
1436 for (const auto& pe : fProgram) {
1437 if (pe.fKind == ProgramElement::kFunction_Kind) {
1438 FunctionDefinition& f = (FunctionDefinition&) pe;
1439 fFunctions.push_back(&f);
1440 this->writeFunction(f);
1441 }
1442 }
1443 return fErrors.errorCount() == 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001444}
Ethan Nicholas2cde3a12020-01-21 09:23:13 -05001445
1446} // namespace