blob: b8cd2acf2c2cd568e48648e17025dc3ad7e2c978 [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 {
Brian Osman838007f2020-02-26 12:18:03 -050017 // "Normal" intrinsics are all $genType f($genType [, $genType...])
18 // and all map to a single instruction (possibly with a vector version)
19 { "cos", { ByteCode::Instruction::kCos, false } },
20 { "mix", { ByteCode::Instruction::kSelect, true } },
21 { "not", { ByteCode::Instruction::kNot, false } },
22 { "sin", { ByteCode::Instruction::kSin, false } },
23 { "sqrt", { ByteCode::Instruction::kSqrt, false } },
24 { "tan", { ByteCode::Instruction::kTan, false } },
25
26 { "lessThan", { ByteCode::Instruction::kCompareLTF,
27 ByteCode::Instruction::kCompareLTS,
28 ByteCode::Instruction::kCompareLTU, true } },
29 { "lessThanEqual", { ByteCode::Instruction::kCompareLTEQF,
30 ByteCode::Instruction::kCompareLTEQS,
31 ByteCode::Instruction::kCompareLTEQU, true } },
32 { "greaterThan", { ByteCode::Instruction::kCompareGTF,
33 ByteCode::Instruction::kCompareGTS,
34 ByteCode::Instruction::kCompareGTU, true } },
35 { "greaterThanEqual", { ByteCode::Instruction::kCompareGTEQF,
36 ByteCode::Instruction::kCompareGTEQS,
37 ByteCode::Instruction::kCompareGTEQU, true } },
38 { "equal", { ByteCode::Instruction::kCompareEQF,
39 ByteCode::Instruction::kCompareEQI,
40 ByteCode::Instruction::kCompareEQI, true } },
41 { "notEqual", { ByteCode::Instruction::kCompareNEQF,
42 ByteCode::Instruction::kCompareNEQI,
43 ByteCode::Instruction::kCompareNEQI, true } },
Brian Osmandc2a9772020-02-21 17:00:43 -050044
45 // Special intrinsics have other signatures, or non-standard code-gen
Brian Osman838007f2020-02-26 12:18:03 -050046 { "all", SpecialIntrinsic::kAll },
47 { "any", SpecialIntrinsic::kAny },
Brian Osmandc2a9772020-02-21 17:00:43 -050048 { "inverse", SpecialIntrinsic::kInverse },
49 { "print", SpecialIntrinsic::kPrint },
Ethan Nicholasb962eff2020-01-23 16:49:41 -050050 } {}
Ethan Nicholas82162ee2019-05-21 16:05:08 -040051
Brian Osman07c117b2019-05-23 12:51:06 -070052int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040053 if (type.kind() == Type::kOther_Kind) {
54 return 0;
55 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070056 int slots = 0;
57 for (const auto& f : type.fields()) {
58 slots += SlotCount(*f.fType);
59 }
60 SkASSERT(slots <= 255);
61 return slots;
62 } else if (type.kind() == Type::kArray_Kind) {
63 int columns = type.columns();
64 SkASSERT(columns >= 0);
65 int slots = columns * SlotCount(type.componentType());
66 SkASSERT(slots <= 255);
67 return slots;
68 } else {
69 return type.columns() * type.rows();
70 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040071}
72
Brian Osman1c110a02019-10-01 14:53:32 -040073static inline bool is_uniform(const SkSL::Variable& var) {
74 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
75}
76
Brian Osmaneadfeb92020-01-09 12:43:03 -050077static inline bool is_in(const SkSL::Variable& var) {
78 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
79}
Ethan Nicholasb962eff2020-01-23 16:49:41 -050080ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
81 // given that we seldom have more than a couple of variables, linear search is probably the most
82 // efficient way to handle lookups
83 switch (var.fStorage) {
84 case Variable::kLocal_Storage: {
85 for (int i = fLocals.size() - 1; i >= 0; --i) {
86 if (fLocals[i] == &var) {
87 return ByteCode::Pointer{(uint16_t) (i + fParameterCount)};
Ben Wagner470e0ac2020-01-22 16:59:21 -050088 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -050089 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -050090 int result = fLocals.size() + fParameterCount;
91 fLocals.push_back(&var);
92 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
93 fLocals.push_back(nullptr);
94 }
95 SkASSERT(result <= ByteCode::kPointerMax);
96 return ByteCode::Pointer{(uint16_t) result};
97 }
98 case Variable::kParameter_Storage: {
99 int offset = 0;
100 for (const auto& p : fFunction->fDeclaration.fParameters) {
101 if (p == &var) {
102 SkASSERT(offset <= ByteCode::kPointerMax);
103 return ByteCode::Pointer{(uint16_t) offset};
104 }
105 offset += SlotCount(p->fType);
106 }
107 SkASSERT(false);
108 return ByteCode::Pointer{0};
109 }
110 case Variable::kGlobal_Storage: {
111 if (is_in(var)) {
Brian Osmana95f10c2020-02-21 13:27:06 -0500112 // If you see this error, it means the program is using raw 'in' variables. You
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500113 // should either specialize the program (Compiler::specialize) to bake in the final
114 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
115 // 'uniform' instead?).
Brian Osmana95f10c2020-02-21 13:27:06 -0500116 fErrors.error(var.fOffset,
117 "'in' variable is not specialized or has unsupported type");
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500118 return ByteCode::Pointer{0};
119 }
120 bool isUniform = is_uniform(var);
121 int offset = isUniform ? fOutput->getGlobalSlotCount() : 0;
122 for (const auto& e : fProgram) {
123 if (e.fKind == ProgramElement::kVar_Kind) {
124 VarDeclarations& decl = (VarDeclarations&) e;
125 for (const auto& v : decl.fVars) {
126 const Variable* declVar = ((VarDeclaration&) *v).fVar;
127 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
128 continue;
129 }
130 if (isUniform != is_uniform(*declVar)) {
131 continue;
132 }
133 if (declVar == &var) {
134 SkASSERT(offset <= ByteCode::kPointerMax);
135 return ByteCode::Pointer{(uint16_t) offset};
136 }
137 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400138 }
139 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500141 SkASSERT(false);
142 return ByteCode::Pointer{0};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400143 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500144 default:
145 SkASSERT(false);
146 return ByteCode::Pointer{0};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400147 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400148}
149
Brian Osman0785db02019-05-24 14:19:11 -0400150// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
151// that references consecutive values, such that it can be implemented using normal load/store ops
152// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
153static bool swizzle_is_simple(const Swizzle& s) {
154 switch (s.fBase->fKind) {
155 case Expression::kFieldAccess_Kind:
156 case Expression::kIndex_Kind:
157 case Expression::kVariableReference_Kind:
158 break;
159 default:
160 return false;
161 }
162
163 for (size_t i = 1; i < s.fComponents.size(); ++i) {
164 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
165 return false;
166 }
167 }
168 return true;
169}
170
Brian Osman1c110a02019-10-01 14:53:32 -0400171ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700172 switch (expr.fKind) {
173 case Expression::kFieldAccess_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500174 const FieldAccess& f = (const FieldAccess&) expr;
175 Location result = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700176 int offset = 0;
177 for (int i = 0; i < f.fFieldIndex; ++i) {
178 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
179 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500180 return result.offset(*this, offset);
Ethan Nicholas99c54f02020-01-21 16:06:47 +0000181 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500182 case Expression::kIndex_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500183 const IndexExpression& idx = (const IndexExpression&) expr;
184 int stride = SlotCount(idx.fType);
185 int length = idx.fBase->fType.columns();
186 Location result = this->getLocation(*idx.fBase);
187 if (idx.fIndex->isConstant()) {
188 int64_t index = idx.fIndex->getConstantInt();
Ben Wagner470e0ac2020-01-22 16:59:21 -0500189 if (index < 0 || index >= length) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500190 fErrors.error(idx.fIndex->fOffset, "Array index out of bounds");
191 return result;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500192 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500193 return result.offset(*this, index * stride);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500194 } else {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500195 ByteCode::Register index = this->next(1);
196 this->writeExpression(*idx.fIndex, index);
197 this->write(ByteCode::Instruction::kBoundsCheck);
198 this->write(index);
199 this->write(length);
200 ByteCode::Register imm = this->next(1);
201 this->write(ByteCode::Instruction::kImmediate);
202 this->write(imm);
203 this->write(ByteCode::Immediate{stride});
204 ByteCode::Register offset = this->next(1);
205 this->write(ByteCode::Instruction::kMultiplyI);
206 this->write(offset);
207 this->write(index);
208 this->write(imm);
209 return result.offset(*this, offset);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500210 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500211 }
Brian Osman0785db02019-05-24 14:19:11 -0400212 case Expression::kSwizzle_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500213 const Swizzle& s = (const Swizzle&) expr;
Brian Osman0785db02019-05-24 14:19:11 -0400214 SkASSERT(swizzle_is_simple(s));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500215 return this->getLocation(*s.fBase).offset(*this, s.fComponents[0]);
Brian Osman0785db02019-05-24 14:19:11 -0400216 }
Brian Osman07c117b2019-05-23 12:51:06 -0700217 case Expression::kVariableReference_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500218 const Variable& var = ((const VariableReference&) expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700219 return this->getLocation(var);
220 }
221 default:
222 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500223 return ByteCode::Pointer{0};
Brian Osman07c117b2019-05-23 12:51:06 -0700224 }
225}
226
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500227Variable::Storage ByteCodeGenerator::getStorage(const Expression& expr) {
228 switch (expr.fKind) {
229 case Expression::kFieldAccess_Kind: {
230 const FieldAccess& f = (const FieldAccess&) expr;
231 return this->getStorage(*f.fBase);
Ethan Nicholas7deb1c22020-01-22 10:31:55 -0500232 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500233 case Expression::kIndex_Kind: {
234 const IndexExpression& idx = (const IndexExpression&) expr;
235 return this->getStorage(*idx.fBase);
Ethan Nicholas7deb1c22020-01-22 10:31:55 -0500236 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500237 case Expression::kSwizzle_Kind: {
238 const Swizzle& s = (const Swizzle&) expr;
239 return this->getStorage(*s.fBase);
Ethan Nicholas7deb1c22020-01-22 10:31:55 -0500240 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500241 case Expression::kVariableReference_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500242 const Variable& var = ((const VariableReference&) expr).fVariable;
243 return var.fStorage;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500244 }
245 default:
Ben Wagner470e0ac2020-01-22 16:59:21 -0500246 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500247 return Variable::kLocal_Storage;
Ethan Nicholas99c54f02020-01-21 16:06:47 +0000248 }
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500249}
250
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500251ByteCode::Instruction ByteCodeGenerator::getLoadInstruction(ByteCodeGenerator::Location location,
252 Variable::Storage storage) {
253 switch (storage) {
254 case Variable::kGlobal_Storage:
255 switch (location.fKind) {
256 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadDirect;
257 case Location::kRegister_Kind: return ByteCode::Instruction::kLoad;
258 }
259 case Variable::kParameter_Storage:
260 switch (location.fKind) {
261 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadParameterDirect;
262 case Location::kRegister_Kind: return ByteCode::Instruction::kLoadParameter;
263 }
264 case Variable::kLocal_Storage:
265 switch (location.fKind) {
266 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadStackDirect;
267 case Location::kRegister_Kind: return ByteCode::Instruction::kLoadStack;
268 }
269 default:
270 break;
271 }
272 SkASSERT(false);
273 return ByteCode::Instruction::kNop;
274}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500275
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500276ByteCode::Instruction ByteCodeGenerator::getStoreInstruction(ByteCodeGenerator::Location location,
277 Variable::Storage storage) {
278 switch (storage) {
279 case Variable::kGlobal_Storage:
280 switch (location.fKind) {
281 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreDirect;
282 case Location::kRegister_Kind: return ByteCode::Instruction::kStore;
283 }
284 case Variable::kParameter_Storage:
285 switch (location.fKind) {
286 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreParameterDirect;
287 case Location::kRegister_Kind: return ByteCode::Instruction::kStoreParameter;
288 }
289 case Variable::kLocal_Storage:
290 switch (location.fKind) {
291 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreStackDirect;
292 case Location::kRegister_Kind: return ByteCode::Instruction::kStoreStack;
293 }
294 default:
295 break;
296 }
297 SkASSERT(false);
298 return ByteCode::Instruction::kNop;
299}
300
Ethan Nicholas2329da02020-01-24 15:49:33 -0500301#define VEC(inst) ((ByteCode::Instruction) ((uint16_t) inst + 1))
302
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500303class ByteCodeSimpleLValue : public ByteCodeGenerator::LValue {
304public:
305 ByteCodeSimpleLValue(ByteCodeGenerator* generator, ByteCodeGenerator::Location location,
306 int count, ByteCode::Instruction load, ByteCode::Instruction store)
307 : INHERITED(*generator)
308 , fLocation(location)
Ethan Nicholas2329da02020-01-24 15:49:33 -0500309 , fCount((uint8_t) count)
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500310 , fLoad(load)
311 , fStore(store) {}
312
313 void load(ByteCode::Register result) override {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500314 fGenerator.write(fLoad, fCount);
315 fGenerator.write(result);
316 fGenerator.write(fLocation);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500317 }
318
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500319 void store(ByteCode::Register src) override {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500320 fGenerator.write(fStore, fCount);
321 fGenerator.write(fLocation);
322 fGenerator.write(src);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500323 }
324
325private:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500326 ByteCodeGenerator::Location fLocation;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500327
Ethan Nicholas2329da02020-01-24 15:49:33 -0500328 uint8_t fCount;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500329
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500330 ByteCode::Instruction fLoad;
331
332 ByteCode::Instruction fStore;
333
334 typedef ByteCodeGenerator::LValue INHERITED;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500335};
336
337class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
338public:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500339 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle* swizzle)
Ben Wagner470e0ac2020-01-22 16:59:21 -0500340 : INHERITED(*generator)
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500341 , fSwizzle(*swizzle) {}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500342
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500343 void load(ByteCode::Register result) override {
344 fGenerator.writeSwizzle(fSwizzle, result);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500345 }
346
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500347 void store(ByteCode::Register src) override {
348 ByteCodeGenerator::Location target = fGenerator.getLocation(*fSwizzle.fBase);
349 ByteCode::Instruction inst = fGenerator.getStoreInstruction(
350 target,
351 fGenerator.getStorage(*fSwizzle.fBase));
352 for (size_t i = 0; i < fSwizzle.fComponents.size(); ++i) {
353 ByteCodeGenerator::Location final = target.offset(fGenerator, fSwizzle.fComponents[i]);
354 fGenerator.write(inst);
355 fGenerator.write(final);
356 fGenerator.write(src + i);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500357 }
358 }
359
360private:
361 const Swizzle& fSwizzle;
362
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500363 typedef ByteCodeGenerator::LValue INHERITED;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500364};
365
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500366class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
Ben Wagner470e0ac2020-01-22 16:59:21 -0500367public:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500368 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
Ben Wagner470e0ac2020-01-22 16:59:21 -0500369 : INHERITED(*generator)
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500370 , fIndex(index)
371 , fSlotCount(ByteCodeGenerator::SlotCount(value.type())) {
372 SkASSERT(fSlotCount <= 4);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500373 }
374
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500375 void load(ByteCode::Register result) override {
376 fGenerator.write(ByteCode::Instruction::kReadExternal);
377 fGenerator.write(result);
378 fGenerator.write((uint8_t) fSlotCount);
379 fGenerator.write((uint8_t) fIndex);
380 }
381
382 void store(ByteCode::Register src) override {
383 fGenerator.write(ByteCode::Instruction::kWriteExternal);
384 fGenerator.write((uint8_t) fIndex);
385 fGenerator.write((uint8_t) fSlotCount);
386 fGenerator.write(src);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500387 }
388
389private:
390 typedef LValue INHERITED;
391
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500392 int fIndex;
393
394 int fSlotCount;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500395};
396
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500397std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& expr) {
398 switch (expr.fKind) {
Ben Wagner470e0ac2020-01-22 16:59:21 -0500399 case Expression::kExternalValue_Kind: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500400 ExternalValue* value = ((ExternalValueReference&) expr).fValue;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500401 int index = fOutput->fExternalValues.size();
402 fOutput->fExternalValues.push_back(value);
403 SkASSERT(index <= 255);
404 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
405 }
406 case Expression::kFieldAccess_Kind:
407 case Expression::kIndex_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500408 case Expression::kVariableReference_Kind: {
409 Location location = this->getLocation(expr);
410 Variable::Storage storage = this->getStorage(expr);
411 ByteCode::Instruction loadInst = this->getLoadInstruction(location, storage);
412 ByteCode::Instruction storeInst = this->getStoreInstruction(location, storage);
413 return std::unique_ptr<LValue>(new ByteCodeSimpleLValue(this, location,
414 SlotCount(expr.fType),
415 loadInst, storeInst));
Ben Wagner470e0ac2020-01-22 16:59:21 -0500416 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500417 case Expression::kSwizzle_Kind:
418 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, &(Swizzle&) expr));
419 default:
420 ABORT("unsupported lvalue\n");
421 }
422}
423
424ByteCode::Register ByteCodeGenerator::next(int count) {
425 SkASSERT(fNextRegister + count <= ByteCode::kRegisterMax);
426 fNextRegister += count;
427 return ByteCode::Register{(uint16_t) (fNextRegister - count)};
428}
429
430static TypeCategory type_category(const Type& type) {
431 switch (type.kind()) {
432 case Type::Kind::kVector_Kind:
433 case Type::Kind::kMatrix_Kind:
434 return type_category(type.componentType());
435 default:
436 String name = type.displayName();
437 if (name == "bool") {
438 return TypeCategory::kBool;
439 } else if (name == "int" || name == "short") {
440 return TypeCategory::kSigned;
441 } else if (name == "uint" || name == "ushort") {
442 return TypeCategory::kUnsigned;
443 } else {
444 SkASSERT(name == "float" || name == "half");
445 return TypeCategory::kFloat;
446 }
447 ABORT("unsupported type: %s\n", name.c_str());
448 }
449}
450
Ethan Nicholas2329da02020-01-24 15:49:33 -0500451void ByteCodeGenerator::write(ByteCode::Instruction inst, int count) {
452 SkASSERT(count <= 255);
453 if (count > 1) {
454 this->write(VEC(inst));
455 this->write((uint8_t) count);
456 }
457 else {
458 this->write(inst);
459 }
460}
461
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500462void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCode::Instruction s,
463 ByteCode::Instruction u, ByteCode::Instruction f) {
464 switch (type_category(type)) {
465 case TypeCategory::kSigned:
466 this->write(s);
467 break;
468 case TypeCategory::kUnsigned:
469 this->write(u);
470 break;
471 case TypeCategory::kFloat: {
472 this->write(f);
473 break;
474 }
475 default:
476 SkASSERT(false);
477 }
478}
479
Ethan Nicholas2329da02020-01-24 15:49:33 -0500480void ByteCodeGenerator::writeVectorBinaryInstruction(const Type& operandType,
481 ByteCode::Register left,
482 ByteCode::Register right,
483 ByteCode::Instruction s,
484 ByteCode::Instruction u,
485 ByteCode::Instruction f,
486 ByteCode::Register result) {
487 uint8_t count = (uint8_t) SlotCount(operandType);
488 if (count == 1) {
489 this->writeTypedInstruction(operandType, s, u, f);
490 }
491 else {
492 this->writeTypedInstruction(operandType, VEC(s), VEC(u), VEC(f));
493 this->write(count);
494 }
495 this->write(result);
496 this->write(left);
497 this->write(right);
498}
499
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500500void ByteCodeGenerator::writeBinaryInstruction(const Type& operandType,
501 ByteCode::Register left,
502 ByteCode::Register right,
503 ByteCode::Instruction s,
504 ByteCode::Instruction u,
505 ByteCode::Instruction f,
506 ByteCode::Register result) {
507 for (int i = 0; i < SlotCount(operandType); ++i) {
508 this->writeTypedInstruction(operandType, s, u, f);
509 this->write(result + i);
510 this->write(left + i);
511 this->write(right + i);
512 }
513}
514
515void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
516 ByteCode::Register result) {
517 if (b.fOperator == Token::Kind::EQ) {
518 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
519 this->writeExpression(*b.fRight, result);
520 lvalue->store(result);
521 return;
522 }
523 const Type& lType = b.fLeft->fType;
524 const Type& rType = b.fRight->fType;
525 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
526 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
527 const Type* operandType;
528 if (!lVecOrMtx && rVecOrMtx) {
529 operandType = &rType;
530 } else {
531 operandType = &lType;
532 }
533 Token::Kind op;
534 std::unique_ptr<LValue> lvalue;
535 ByteCode::Register left;
536 switch (b.fOperator) {
537 case Token::Kind::LOGICALAND:
538 case Token::Kind::LOGICALANDEQ:
539 case Token::Kind::LOGICALOR:
540 case Token::Kind::LOGICALOREQ:
541 left = result;
542 break;
543 default:
544 left = this->next(SlotCount(*operandType));
545 }
546 if (is_assignment(b.fOperator)) {
547 lvalue = this->getLValue(*b.fLeft);
548 lvalue->load(left);
549 op = remove_assignment(b.fOperator);
550 } else {
551 this->writeExpression(*b.fLeft, left);
552 op = b.fOperator;
553 if (!lVecOrMtx && rVecOrMtx) {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500554 this->write(ByteCode::Instruction::kSplat);
555 this->write((uint8_t) (SlotCount(rType) - 1));
556 this->write(left + 1);
557 this->write(left);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500558 }
559 }
560 SkDEBUGCODE(TypeCategory tc = type_category(lType));
561 int count = std::max(SlotCount(lType), SlotCount(rType));
562 switch (op) {
563 case Token::Kind::LOGICALAND: {
564 SkASSERT(left.fIndex == result.fIndex);
565 this->write(ByteCode::Instruction::kMaskPush);
566 ++fConditionCount;
567 this->write(left);
568 this->write(ByteCode::Instruction::kBranchIfAllFalse);
569 DeferredLocation falseLocation(this);
570 SkASSERT(SlotCount(b.fRight->fType) == 1);
571 ByteCode::Register right = this->next(1);
572 this->writeExpression(*b.fRight, right);
573 this->write(ByteCode::Instruction::kAnd);
574 this->write(result);
575 this->write(left);
576 this->write(right);
577 falseLocation.set();
578 --fConditionCount;
579 this->write(ByteCode::Instruction::kMaskPop);
580 return;
581 }
582 case Token::Kind::LOGICALOR: {
583 SkASSERT(left.fIndex == result.fIndex);
584 ByteCode::Register mask = this->next(1);
585 this->write(ByteCode::Instruction::kNot);
586 this->write(mask);
587 this->write(left);
588 this->write(ByteCode::Instruction::kMaskPush);
589 ++fConditionCount;
590 this->write(mask);
591 this->write(ByteCode::Instruction::kBranchIfAllFalse);
592 DeferredLocation falseLocation(this);
593 SkASSERT(SlotCount(b.fRight->fType) == 1);
594 ByteCode::Register right = this->next(1);
595 this->writeExpression(*b.fRight, right);
596 this->write(ByteCode::Instruction::kOr);
597 this->write(result);
598 this->write(left);
599 this->write(right);
600 falseLocation.set();
601 --fConditionCount;
602 this->write(ByteCode::Instruction::kMaskPop);
603 return;
604 }
605 case Token::Kind::SHL:
606 case Token::Kind::SHR: {
607 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
608 tc == SkSL::TypeCategory::kUnsigned));
609 if (!b.fRight->isConstant()) {
610 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
611 return;
612 }
613 int64_t shift = b.fRight->getConstantInt();
614 if (shift < 0 || shift > 31) {
615 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
616 return;
617 }
618
619 if (op == Token::Kind::SHL) {
620 this->write(ByteCode::Instruction::kShiftLeft);
621 } else {
622 this->write(type_category(lType) == TypeCategory::kSigned
623 ? ByteCode::Instruction::kShiftRightS
624 : ByteCode::Instruction::kShiftRightU);
625 }
626 this->write(result);
627 this->write(left);
628 this->write((uint8_t) shift);
629 return;
630 }
631 case Token::Kind::STAR:
632 // Special case for M*V, V*M, M*M (but not V*V!)
633 if (lType.columns() > 1 && rType.columns() > 1 &&
634 (lType.rows() > 1 || rType.rows() > 1)) {
635 ByteCode::Register right = this->next(SlotCount(rType));
636 this->writeExpression(*b.fRight, right);
637 int rCols = rType.columns(),
638 rRows = rType.rows(),
639 lCols = lType.columns(),
640 lRows = lType.rows();
641 // M*V treats the vector as a column
642 if (rType.kind() == Type::kVector_Kind) {
643 std::swap(rCols, rRows);
644 }
645 SkASSERT(lCols == rRows);
646 SkASSERT(SlotCount(b.fType) == lRows * rCols);
647 this->write(ByteCode::Instruction::kMatrixMultiply);
648 this->write(result);
649 this->write(left);
650 this->write(right);
651 this->write((uint8_t) lCols);
652 this->write((uint8_t) lRows);
653 this->write((uint8_t) rCols);
654 return;
655 }
656
657 default:
658 break;
659 }
660 ByteCode::Register right = this->next(SlotCount(*operandType));
661 this->writeExpression(*b.fRight, right);
662 if (lVecOrMtx && !rVecOrMtx) {
Ethan Nicholas2329da02020-01-24 15:49:33 -0500663 this->write(ByteCode::Instruction::kSplat);
664 this->write((uint8_t) (SlotCount(*operandType) - 1));
665 this->write(right + 1);
666 this->write(right);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500667 }
668 switch (op) {
669 case Token::Kind::EQEQ:
670 this->writeBinaryInstruction(*operandType, left, right,
671 ByteCode::Instruction::kCompareEQI,
672 ByteCode::Instruction::kCompareEQI,
673 ByteCode::Instruction::kCompareEQF,
674 result);
675 // Collapse to a single bool
676 for (int i = 1; i < count; ++i) {
677 this->write(ByteCode::Instruction::kAnd);
678 this->write(result);
679 this->write(result);
680 this->write(result + i);
681 }
682 break;
683 case Token::Kind::GT:
684 this->writeBinaryInstruction(*operandType, left, right,
685 ByteCode::Instruction::kCompareGTS,
686 ByteCode::Instruction::kCompareGTU,
687 ByteCode::Instruction::kCompareGTF,
688 result);
689 break;
690 case Token::Kind::GTEQ:
691 this->writeBinaryInstruction(*operandType, left, right,
692 ByteCode::Instruction::kCompareGTEQS,
693 ByteCode::Instruction::kCompareGTEQU,
694 ByteCode::Instruction::kCompareGTEQF,
695 result);
696 break;
697 case Token::Kind::LT:
698 this->writeBinaryInstruction(*operandType, left, right,
699 ByteCode::Instruction::kCompareLTS,
700 ByteCode::Instruction::kCompareLTU,
701 ByteCode::Instruction::kCompareLTF,
702 result);
703 break;
704 case Token::Kind::LTEQ:
705 this->writeBinaryInstruction(*operandType, left, right,
706 ByteCode::Instruction::kCompareLTEQS,
707 ByteCode::Instruction::kCompareLTEQU,
708 ByteCode::Instruction::kCompareLTEQF,
709 result);
710 break;
711 case Token::Kind::MINUS:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500712 this->writeVectorBinaryInstruction(*operandType, left, right,
713 ByteCode::Instruction::kSubtractI,
714 ByteCode::Instruction::kSubtractI,
715 ByteCode::Instruction::kSubtractF,
716 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500717 break;
718 case Token::Kind::NEQ:
719 this->writeBinaryInstruction(*operandType, left, right,
720 ByteCode::Instruction::kCompareNEQI,
721 ByteCode::Instruction::kCompareNEQI,
722 ByteCode::Instruction::kCompareNEQF,
723 result);
724 // Collapse to a single bool
725 for (int i = 1; i < count; ++i) {
726 this->write(ByteCode::Instruction::kOr);
727 this->write(result);
728 this->write(result);
729 this->write(result + i);
730 }
731 break;
732 case Token::Kind::PERCENT:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500733 this->writeVectorBinaryInstruction(*operandType, left, right,
734 ByteCode::Instruction::kRemainderS,
735 ByteCode::Instruction::kRemainderU,
736 ByteCode::Instruction::kRemainderF,
737 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 break;
739 case Token::Kind::PLUS:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500740 this->writeVectorBinaryInstruction(*operandType, left, right,
741 ByteCode::Instruction::kAddI,
742 ByteCode::Instruction::kAddI,
743 ByteCode::Instruction::kAddF,
744 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500745 break;
746 case Token::Kind::SLASH:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500747 this->writeVectorBinaryInstruction(*operandType, left, right,
748 ByteCode::Instruction::kDivideS,
749 ByteCode::Instruction::kDivideU,
750 ByteCode::Instruction::kDivideF,
751 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500752 break;
753 case Token::Kind::STAR:
Ethan Nicholas2329da02020-01-24 15:49:33 -0500754 this->writeVectorBinaryInstruction(*operandType, left, right,
755 ByteCode::Instruction::kMultiplyI,
756 ByteCode::Instruction::kMultiplyI,
757 ByteCode::Instruction::kMultiplyF,
758 result);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500759 break;
760 case Token::Kind::LOGICALXOR: {
761 SkASSERT(tc == SkSL::TypeCategory::kBool);
762 this->write(ByteCode::Instruction::kXor);
763 this->write(result);
764 this->write(left);
765 this->write(right);
766 break;
767 }
768 case Token::Kind::BITWISEAND: {
769 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
770 this->write(ByteCode::Instruction::kAnd);
771 this->write(result);
772 this->write(left);
773 this->write(right);
774 break;
775 }
776 case Token::Kind::BITWISEOR: {
777 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
778 this->write(ByteCode::Instruction::kOr);
779 this->write(result);
780 this->write(left);
781 this->write(right);
782 break;
783 }
784 case Token::Kind::BITWISEXOR: {
785 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
786 this->write(ByteCode::Instruction::kXor);
787 this->write(result);
788 this->write(left);
789 this->write(right);
790 break;
791 }
792 default:
793 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
794 Compiler::OperatorName(op)));
795 break;
796 }
797 if (lvalue) {
798 lvalue->store(result);
799 }
800}
801
802void ByteCodeGenerator::writeConstructor(const Constructor& c, ByteCode::Register result) {
803 if (c.fType.rows() > 1) {
804 if (c.fArguments.size() == 1) {
805 if (SlotCount(c.fArguments[0]->fType) == 1) {
806 ByteCode::Register v = this->next(1);
807 this->writeExpression(*c.fArguments[0], v);
808 this->write(ByteCode::Instruction::kScalarToMatrix);
809 this->write(result);
810 this->write(v);
811 this->write((uint8_t) c.fType.columns());
812 this->write((uint8_t) c.fType.rows());
813 return;
814 } else if (c.fArguments[0]->fType.rows() > 1) {
815 ByteCode::Register v = this->next(SlotCount(c.fArguments[0]->fType));
816 this->writeExpression(*c.fArguments[0], v);
817 this->write(ByteCode::Instruction::kMatrixToMatrix);
818 this->write(result);
819 this->write(v);
820 this->write((uint8_t) c.fArguments[0]->fType.columns());
821 this->write((uint8_t) c.fArguments[0]->fType.rows());
822 this->write((uint8_t) c.fType.columns());
823 this->write((uint8_t) c.fType.rows());
824 return;
825 }
826 }
827 int offset = 0;
828 for (const auto& arg : c.fArguments) {
829 this->writeExpression(*arg, ByteCode::Register{(uint16_t) (result.fIndex + offset)});
830 offset += SlotCount(arg->fType);
831 }
832 return;
833 }
834 if (c.fArguments.size() == 1 && c.fArguments[0]->fType.columns() == 1 &&
835 c.fType.columns() > 1) {
836 SkASSERT(SlotCount(c.fArguments[0]->fType) == 1);
837 ByteCode::Register v = result;
838 this->writeExpression(*c.fArguments[0], v);
Ethan Nicholas2329da02020-01-24 15:49:33 -0500839 this->write(ByteCode::Instruction::kSplat);
840 this->write((uint8_t) (c.fType.columns() - 1));
841 this->write(v + 1);
842 this->write(v);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500843 return;
844 }
845 ByteCode::Instruction inst;
846 switch (type_category(c.fArguments[0]->fType)) {
847 case TypeCategory::kSigned:
848 if (type_category(c.fType) == TypeCategory::kFloat) {
849 inst = ByteCode::Instruction::kSignedToFloat;
850 } else {
851 inst = ByteCode::Instruction::kNop;
852 }
853 break;
854 case TypeCategory::kUnsigned:
855 if (type_category(c.fType) == TypeCategory::kFloat) {
856 inst = ByteCode::Instruction::kUnsignedToFloat;
857 } else {
858 inst = ByteCode::Instruction::kNop;
859 }
860 break;
861 case TypeCategory::kFloat:
862 if (type_category(c.fType) == TypeCategory::kSigned) {
863 inst = ByteCode::Instruction::kFloatToSigned;
864 } else if (type_category(c.fType) == TypeCategory::kUnsigned) {
865 inst = ByteCode::Instruction::kFloatToUnsigned;
866 } else {
867 inst = ByteCode::Instruction::kNop;
868 }
869 break;
870 default:
871 SkASSERT(false);
872 return;
873 }
874 ByteCode::Register values;
875 if (inst == ByteCode::Instruction::kNop) {
876 values = result;
877 } else {
878 values = this->next(SlotCount(c.fType));
879 }
880 ByteCode::Register v = values;
881 for (size_t i = 0; i < c.fArguments.size(); ++i) {
882 this->writeExpression(*c.fArguments[i], v);
883 v.fIndex += SlotCount(c.fArguments[i]->fType);
884 }
885 if (inst != ByteCode::Instruction::kNop) {
886 v = values;
887 ByteCode::Register target = result;
888 for (size_t i = 0; i < c.fArguments.size(); ++i) {
889 int count = SlotCount(c.fArguments[i]->fType);
890 for (int j = 0; j < count; ++j) {
891 this->write(inst);
892 this->write(target);
893 ++target.fIndex;
894 this->write(v + j);
895 }
896 }
897 }
898}
899
900void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f,
901 ByteCode::Register result) {
902 int argumentCount = 0;
903 for (const auto& arg : f.fArguments) {
904 argumentCount += SlotCount(arg->fType);
905 }
906 ByteCode::Register args = this->next(argumentCount);
907 argumentCount = 0;
908 for (const auto& arg : f.fArguments) {
909 this->writeExpression(*arg, args + argumentCount);
910 argumentCount += SlotCount(arg->fType);
911 }
912 this->write(ByteCode::Instruction::kCallExternal);
913 this->write(result);
914 int index = fOutput->fExternalValues.size();
915 fOutput->fExternalValues.push_back(f.fFunction);
916 SkASSERT(index <= 255);
917 this->write((uint8_t) index);
918 SkASSERT(SlotCount(f.fType) <= 255);
919 this->write((uint8_t) SlotCount(f.fType));
920 this->write(args);
921 SkASSERT(argumentCount <= 255);
922 this->write((uint8_t) argumentCount);
923}
924
925void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e,
926 ByteCode::Register result) {
927 this->write(ByteCode::Instruction::kReadExternal);
928 this->write(result);
929 this->write((uint8_t) SlotCount(e.fValue->type()));
930 int index = fOutput->fExternalValues.size();
931 fOutput->fExternalValues.push_back(e.fValue);
932 SkASSERT(index <= 255);
933 this->write((uint8_t) index);
934}
935
936void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c, Intrinsic intrinsic,
937 ByteCode::Register result) {
938 if (intrinsic.fIsSpecial) {
939 switch (intrinsic.fValue.fSpecial) {
Brian Osman838007f2020-02-26 12:18:03 -0500940 case SpecialIntrinsic::kAll:
941 case SpecialIntrinsic::kAny: {
942 SkASSERT(c.fArguments.size() == 1);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500943 int count = SlotCount(c.fArguments[0]->fType);
Brian Osman838007f2020-02-26 12:18:03 -0500944 SkASSERT(count > 1);
945 // Fold a bvec down to a single bool:
946 ByteCode::Register arg = this->next(count);
947 ByteCode::Instruction inst = intrinsic.fValue.fSpecial == SpecialIntrinsic::kAll
948 ? ByteCode::Instruction::kAnd
949 : ByteCode::Instruction::kOr;
950 this->writeExpression(*c.fArguments[0], arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500951 for (int i = 1; i < count; ++i) {
Brian Osman838007f2020-02-26 12:18:03 -0500952 this->write(inst);
953 this->write(result);
954 this->write(i == 1 ? arg : result);
955 this->write(arg + i);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500956 }
957 break;
958 }
959 case SpecialIntrinsic::kInverse: {
960 SkASSERT(c.fArguments.size() == 1);
961 int count = SlotCount(c.fArguments[0]->fType);
962 ByteCode::Register arg = this->next(count);
963 this->writeExpression(*c.fArguments[0], arg);
964 switch (SlotCount(c.fArguments[0]->fType)) {
965 case 4: this->write(ByteCode::Instruction::kInverse2x2); break;
966 case 9: this->write(ByteCode::Instruction::kInverse3x3); break;
967 case 16: this->write(ByteCode::Instruction::kInverse4x4); break;
968 default: SkASSERT(false);
969 }
970 this->write(result);
971 this->write(arg);
972 break;
973 }
Brian Osmandc2a9772020-02-21 17:00:43 -0500974 case SpecialIntrinsic::kPrint: {
975 SkASSERT(c.fArguments.size() == 1);
976 SkASSERT(SlotCount(c.fArguments[0]->fType) == 1);
977 ByteCode::Register arg = this->next(1);
978 this->writeExpression(*c.fArguments[0], arg);
979 this->write(ByteCode::Instruction::kPrint);
980 this->write(arg);
981 break;
982 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500983 }
984 } else {
Brian Osman838007f2020-02-26 12:18:03 -0500985 uint8_t count = (uint8_t) SlotCount(c.fType);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500986 std::vector<ByteCode::Register> argRegs;
987 for (const auto& expr : c.fArguments) {
Brian Osmandc2a9772020-02-21 17:00:43 -0500988 SkASSERT(SlotCount(expr->fType) == count);
989 ByteCode::Register reg = this->next(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500990 this->writeExpression(*expr, reg);
991 argRegs.push_back(reg);
992 }
Brian Osman838007f2020-02-26 12:18:03 -0500993
994 const auto& instructions = intrinsic.fValue.fInstructions;
995 const Type& opType = c.fArguments[0]->fType;
996
997 if (instructions.fUseVector) {
998 if (count == 1) {
999 this->writeTypedInstruction(opType,
1000 instructions.fFloat,
1001 instructions.fSigned,
1002 instructions.fUnsigned);
1003 } else {
1004 this->writeTypedInstruction(opType,
1005 VEC(instructions.fFloat),
1006 VEC(instructions.fSigned),
1007 VEC(instructions.fUnsigned));
1008 this->write(count);
Brian Osmandc2a9772020-02-21 17:00:43 -05001009 }
Brian Osman838007f2020-02-26 12:18:03 -05001010 this->write(result);
Brian Osmandc2a9772020-02-21 17:00:43 -05001011 for (ByteCode::Register arg : argRegs) {
Brian Osman838007f2020-02-26 12:18:03 -05001012 this->write(arg);
1013 }
1014 } else {
1015 // No vector version of the instruction exists. Emit the scalar instruction N times.
1016 for (uint8_t i = 0; i < count; ++i) {
1017 this->writeTypedInstruction(opType,
1018 instructions.fFloat,
1019 instructions.fSigned,
1020 instructions.fUnsigned);
1021 this->write(result + i);
1022 for (ByteCode::Register arg : argRegs) {
1023 this->write(arg + i);
1024 }
Brian Osmandc2a9772020-02-21 17:00:43 -05001025 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001026 }
1027 }
1028}
1029
1030void ByteCodeGenerator::writeFunctionCall(const FunctionCall& c, ByteCode::Register result) {
Brian Osman838007f2020-02-26 12:18:03 -05001031 // 'mix' is present as both a "pure" intrinsic (fDefined == false), and an SkSL implementation
1032 // in the pre-parsed include files (fDefined == true), depending on argument types. We only
1033 // send calls to the former through the intrinsic path here.
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001034 auto found = fIntrinsics.find(c.fFunction.fName);
Brian Osman838007f2020-02-26 12:18:03 -05001035 if (found != fIntrinsics.end() && !c.fFunction.fDefined) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001036 return this->writeIntrinsicCall(c, found->second, result);
1037 }
1038 int argCount = c.fArguments.size();
1039 std::vector<std::unique_ptr<LValue>> lvalues;
1040 int parameterSlotCount = 0;
1041 for (const auto& p : c.fFunction.fParameters) {
1042 parameterSlotCount += SlotCount(p->fType);
1043 }
1044 ByteCode::Register argStart = this->next(parameterSlotCount);
1045 ByteCode::Register nextArg = argStart;
1046 for (int i = 0; i < argCount; ++i) {
1047 const auto& param = c.fFunction.fParameters[i];
1048 const auto& arg = c.fArguments[i];
1049 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1050 lvalues.emplace_back(this->getLValue(*arg));
1051 lvalues.back()->load(nextArg);
1052 } else {
1053 this->writeExpression(*arg, nextArg);
1054 }
1055 nextArg.fIndex += SlotCount(arg->fType);
1056 }
1057 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1058 // before they're defined. This is an easy-to-understand rule that prevents recursion.
1059 size_t idx;
1060 for (idx = 0; idx < fFunctions.size(); ++idx) {
1061 if (c.fFunction.matches(fFunctions[idx]->fDeclaration)) {
1062 break;
1063 }
1064 }
1065 if (idx > 255) {
1066 fErrors.error(c.fOffset, "Function count limit exceeded");
1067 return;
1068 } else if (idx >= fOutput->fFunctions.size()) {
1069 fErrors.error(c.fOffset, "Call to undefined function");
1070 return;
1071 }
1072
1073 this->write(ByteCode::Instruction::kCall);
1074 this->write(result);
1075 this->write((uint8_t) idx);
1076 this->write(argStart);
1077 nextArg = argStart;
1078 auto lvalue = lvalues.begin();
1079 for (int i = 0; i < argCount; ++i) {
1080 const auto& param = c.fFunction.fParameters[i];
1081 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1082 (*(lvalue++))->store(nextArg);
1083 }
1084 nextArg.fIndex += SlotCount(param->fType);
1085 }
1086}
1087
1088void ByteCodeGenerator::incOrDec(Token::Kind op, Expression& operand, bool prefix,
1089 ByteCode::Register result) {
1090 SkASSERT(op == Token::Kind::PLUSPLUS || op == Token::Kind::MINUSMINUS);
1091 std::unique_ptr<LValue> lvalue = this->getLValue(operand);
1092 SkASSERT(SlotCount(operand.fType) == 1);
1093 ByteCode::Register value;
1094 if (prefix) {
1095 value = this->next(1);
1096 } else {
1097 value = result;
1098 }
1099 lvalue->load(value);
1100 ByteCode::Register one = this->next(1);
1101 this->write(ByteCode::Instruction::kImmediate);
1102 this->write(one);
1103 if (type_category(operand.fType) == TypeCategory::kFloat) {
1104 this->write(ByteCode::Immediate(1.0f));
1105 } else {
1106 this->write(ByteCode::Immediate((int32_t) 1));
1107 }
1108 if (op == Token::Kind::PLUSPLUS) {
1109 this->writeTypedInstruction(operand.fType,
1110 ByteCode::Instruction::kAddI,
1111 ByteCode::Instruction::kAddI,
1112 ByteCode::Instruction::kAddF);
1113 } else {
1114 this->writeTypedInstruction(operand.fType,
1115 ByteCode::Instruction::kSubtractI,
1116 ByteCode::Instruction::kSubtractI,
1117 ByteCode::Instruction::kSubtractF);
1118 }
1119 if (prefix) {
1120 this->write(result);
1121 this->write(value);
1122 this->write(one);
1123 lvalue->store(result);
1124 } else {
1125 ByteCode::Register temp = this->next(1);
1126 this->write(temp);
1127 this->write(value);
1128 this->write(one);
1129 lvalue->store(temp);
1130 }
1131}
1132
1133void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p,
1134 ByteCode::Register result) {
1135 this->incOrDec(p.fOperator, *p.fOperand, false, result);
1136}
1137
1138void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p,
1139 ByteCode::Register result) {
1140 switch (p.fOperator) {
1141 case Token::Kind::PLUSPLUS:
1142 case Token::Kind::MINUSMINUS: {
1143 return this->incOrDec(p.fOperator, *p.fOperand, true, result);
1144 }
1145 case Token::Kind::MINUS: {
1146 ByteCode::Register src = this->next(SlotCount(p.fType));
1147 this->writeExpression(*p.fOperand, src);
1148 for (int i = 0; i < SlotCount(p.fType); ++i) {
1149 this->writeTypedInstruction(p.fType,
1150 ByteCode::Instruction::kNegateS,
1151 ByteCode::Instruction::kNegateS,
1152 ByteCode::Instruction::kNegateF);
1153 this->write(result + i);
1154 this->write(src + i);
1155 }
1156 break;
1157 }
1158 case Token::Kind::LOGICALNOT:
1159 case Token::Kind::BITWISENOT: {
1160 ByteCode::Register src = this->next(SlotCount(p.fType));
1161 this->writeExpression(*p.fOperand, src);
1162 for (int i = 0; i < SlotCount(p.fType); ++i) {
1163 this->write(ByteCode::Instruction::kNot);
1164 this->write(result + i);
1165 this->write(src + i);
1166 }
1167 break;
1168 }
1169 default:
1170 SkASSERT(false);
1171 }
1172}
1173
1174void ByteCodeGenerator::writeSwizzle(const Swizzle& s, ByteCode::Register result) {
1175 if (swizzle_is_simple(s)) {
1176 this->writeVariableExpression(s, result);
1177 return;
1178 }
1179 ByteCode::Register base = this->writeExpression(*s.fBase);
1180 for (int i = 0; i < (int) s.fComponents.size(); ++i) {
1181 this->write(ByteCode::Instruction::kCopy);
1182 this->write(result + i);
1183 this->write(base + s.fComponents[i]);
1184 }
1185}
1186
1187void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
1188 ByteCode::Register result) {
1189 int count = SlotCount(t.fType);
1190 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1191 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1192
1193 ByteCode::Register test = this->writeExpression(*t.fTest);
1194 this->write(ByteCode::Instruction::kMaskPush);
1195 ++fConditionCount;
1196 this->write(test);
1197 ByteCode::Register ifTrue = this->writeExpression(*t.fIfTrue);
1198 this->write(ByteCode::Instruction::kMaskNegate);
1199 ByteCode::Register ifFalse = this->writeExpression(*t.fIfFalse);
1200 --fConditionCount;
1201 this->write(ByteCode::Instruction::kMaskPop);
1202 for (int i = 0; i < count; ++i) {
1203 this->write(ByteCode::Instruction::kSelect);
1204 this->write(result + i);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001205 this->write(ifFalse + i);
Brian Osman838007f2020-02-26 12:18:03 -05001206 this->write(ifTrue + i);
1207 this->write(test);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001208 }
1209}
1210
1211void ByteCodeGenerator::writeVariableExpression(const Expression& expr,
1212 ByteCode::Register result) {
1213 ByteCodeGenerator::Location location = this->getLocation(expr);
1214 int count = SlotCount(expr.fType);
Ethan Nicholas2329da02020-01-24 15:49:33 -05001215 ByteCode::Instruction load = this->getLoadInstruction(location, this->getStorage(expr));
1216 this->write(load, count);
1217 this->write(result);
1218 this->write(location);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001219}
1220
1221void ByteCodeGenerator::writeExpression(const Expression& expr, ByteCode::Register result) {
1222 switch (expr.fKind) {
1223 case Expression::kBoolLiteral_Kind: {
1224 this->write(ByteCode::Instruction::kImmediate);
1225 this->write(result);
1226 this->write(ByteCode::Immediate((int32_t) (((BoolLiteral&) expr).fValue ? -1 : 0)));
1227 break;
1228 }
1229 case Expression::kBinary_Kind: {
1230 this->writeBinaryExpression((BinaryExpression&) expr, result);
1231 break;
1232 }
1233 case Expression::kConstructor_Kind: {
1234 this->writeConstructor((Constructor&) expr, result);
1235 break;
1236 }
1237 case Expression::kExternalFunctionCall_Kind:
1238 this->writeExternalFunctionCall((ExternalFunctionCall&) expr, result);
1239 break;
1240 case Expression::kExternalValue_Kind:
1241 this->writeExternalValue((ExternalValueReference&) expr, result);
1242 break;
1243 case Expression::kFloatLiteral_Kind: {
1244 this->write(ByteCode::Instruction::kImmediate);
1245 this->write(result);
1246 this->write(ByteCode::Immediate((float) ((FloatLiteral&) expr).fValue));
1247 break;
1248 }
1249 case Expression::kFunctionCall_Kind: {
1250 this->writeFunctionCall((FunctionCall&) expr, result);
1251 break;
1252 }
1253 case Expression::kIntLiteral_Kind: {
1254 this->write(ByteCode::Instruction::kImmediate);
1255 this->write(result);
1256 this->write(ByteCode::Immediate((int32_t) ((IntLiteral&) expr).fValue));
1257 break;
1258 }
1259 case Expression::kPostfix_Kind:
1260 this->writePostfixExpression((PostfixExpression&) expr, result);
1261 break;
1262 case Expression::kPrefix_Kind:
1263 this->writePrefixExpression((PrefixExpression&) expr, result);
1264 break;
1265 case Expression::kSwizzle_Kind:
1266 this->writeSwizzle((Swizzle&) expr, result);
1267 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001268 case Expression::kTernary_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001269 this->writeTernaryExpression((TernaryExpression&) expr, result);
1270 break;
1271 case Expression::kFieldAccess_Kind:
1272 case Expression::kIndex_Kind:
1273 case Expression::kVariableReference_Kind:
1274 this->writeVariableExpression(expr, result);
1275 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001276 default:
1277#ifdef SK_DEBUG
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001278 ABORT("unsupported lvalue %s\n", expr.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001279#endif
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001280 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001281 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001282}
1283
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001284ByteCode::Register ByteCodeGenerator::writeExpression(const Expression& expr) {
1285 ByteCode::Register result = this->next(SlotCount(expr.fType));
1286 this->writeExpression(expr, result);
1287 return result;
1288}
1289
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001290void ByteCodeGenerator::writeBlock(const Block& b) {
1291 for (const auto& s : b.fStatements) {
1292 this->writeStatement(*s);
1293 }
1294}
1295
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001296void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001297 this->write(ByteCode::Instruction::kLoopBegin);
1298 ++fConditionCount;
1299 SkASSERT(fCode->size() < ByteCode::kPointerMax);
1300 ByteCode::Pointer start{(uint16_t) fCode->size()};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001301 this->writeStatement(*d.fStatement);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001302 ByteCode::Register test = this->writeExpression(*d.fTest);
1303 this->write(ByteCode::Instruction::kLoopNext);
1304 this->write(ByteCode::Instruction::kLoopMask);
1305 this->write(test);
1306 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001307 DeferredLocation endLocation(this);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001308 this->write(ByteCode::Instruction::kBranch);
1309 this->write(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001310 endLocation.set();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001311 --fConditionCount;
1312 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001313}
1314
1315void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001316 if (f.fInitializer) {
1317 this->writeStatement(*f.fInitializer);
1318 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001319 this->write(ByteCode::Instruction::kLoopBegin);
1320 ++fConditionCount;
1321 ByteCode::Pointer start{(uint16_t) fCode->size()};
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001322 if (f.fTest) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001323 ByteCode::Register test = this->writeExpression(*f.fTest);
1324 this->write(ByteCode::Instruction::kLoopMask);
1325 this->write(test);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001326 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001327 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001328 DeferredLocation endLocation(this);
1329 this->writeStatement(*f.fStatement);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001330 this->write(ByteCode::Instruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001331 if (f.fNext) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001332 this->writeExpression(*f.fNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001333 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001334 this->write(ByteCode::Instruction::kBranch);
1335 this->write(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001336 endLocation.set();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001337 --fConditionCount;
1338 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001339}
1340
1341void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001342 ByteCode::Register test = this->writeExpression(*i.fTest);
1343 this->write(ByteCode::Instruction::kMaskPush);
1344 ++fConditionCount;
1345 this->write(test);
1346 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001347 DeferredLocation falseLocation(this);
1348 this->writeStatement(*i.fIfTrue);
1349 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001350 if (i.fIfFalse) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001351 this->write(ByteCode::Instruction::kMaskNegate);
1352 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001353 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001354 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001355 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001356 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001357 --fConditionCount;
1358 this->write(ByteCode::Instruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001359}
1360
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001361void ByteCodeGenerator::writeReturn(const ReturnStatement& r) {
1362 if (fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001363 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1364 return;
1365 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001366 if (r.fExpression) {
1367 ByteCode::Register value = this->writeExpression(*r.fExpression);
1368 this->write(ByteCode::Instruction::kReturnValue);
1369 this->write(value);
1370 }
1371 else {
1372 this->write(ByteCode::Instruction::kReturn);
1373 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001374}
1375
1376void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1377 for (const auto& declStatement : v.fVars) {
1378 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001379 // we need to grab the location even if we don't use it, to ensure it
1380 // has been allocated
1381 ByteCodeGenerator::Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001382 if (decl.fValue) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001383 ByteCode::Register src = this->writeExpression(*decl.fValue);
Ethan Nicholas2329da02020-01-24 15:49:33 -05001384 uint8_t count = (uint8_t) SlotCount(decl.fVar->fType);
1385 this->write(ByteCode::Instruction::kStoreStackDirect, count);
1386 this->write(location);
1387 this->write(src);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001388 }
1389 }
1390}
1391
1392void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001393 this->write(ByteCode::Instruction::kLoopBegin);
1394 ++fConditionCount;
1395 SkASSERT(fCode->size() < ByteCode::kPointerMax);
1396 ByteCode::Pointer start{(uint16_t) fCode->size()};
1397 ByteCode::Register test = this->writeExpression(*w.fTest);
1398 this->write(ByteCode::Instruction::kLoopMask);
1399 this->write(test);
1400 this->write(ByteCode::Instruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001401 DeferredLocation endLocation(this);
1402 this->writeStatement(*w.fStatement);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001403 this->write(ByteCode::Instruction::kLoopNext);
1404 this->write(ByteCode::Instruction::kBranch);
1405 this->write(start);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001406 endLocation.set();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001407 --fConditionCount;
1408 this->write(ByteCode::Instruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001409}
1410
1411void ByteCodeGenerator::writeStatement(const Statement& s) {
1412 switch (s.fKind) {
1413 case Statement::kBlock_Kind:
1414 this->writeBlock((Block&) s);
1415 break;
1416 case Statement::kBreak_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001417 this->write(ByteCode::Instruction::kBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001418 break;
1419 case Statement::kContinue_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001420 this->write(ByteCode::Instruction::kContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001421 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001422 case Statement::kDo_Kind:
1423 this->writeDoStatement((DoStatement&) s);
1424 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001425 case Statement::kExpression_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001426 this->writeExpression(*((ExpressionStatement&) s).fExpression);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001427 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001428 case Statement::kFor_Kind:
1429 this->writeForStatement((ForStatement&) s);
1430 break;
1431 case Statement::kIf_Kind:
1432 this->writeIfStatement((IfStatement&) s);
1433 break;
1434 case Statement::kNop_Kind:
1435 break;
1436 case Statement::kReturn_Kind:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001437 this->writeReturn((ReturnStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001438 break;
1439 case Statement::kVarDeclarations_Kind:
1440 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1441 break;
1442 case Statement::kWhile_Kind:
1443 this->writeWhileStatement((WhileStatement&) s);
1444 break;
1445 default:
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001446 ABORT("unsupported statement\n");
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001447 }
1448}
1449
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001450void ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
1451 fFunction = &f;
1452 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
1453 result->fReturnSlotCount = SlotCount(f.fDeclaration.fReturnType);
Brian Osman80164412019-06-07 13:00:23 -04001454 fParameterCount = 0;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001455 fConditionCount = 0;
1456 for (const auto& p : f.fDeclaration.fParameters) {
1457 int count = SlotCount(p->fType);
1458 bool isOut = ((p->fModifiers.fFlags & Modifiers::kOut_Flag) != 0);
1459 result->fParameters.push_back(ByteCodeFunction::Parameter{count, isOut});
1460 fParameterCount += count;
1461 }
1462 result->fParameterSlotCount = fParameterCount;
1463 fCode = &result->fCode;
1464 this->writeStatement(*f.fBody);
1465 result->fStackSlotCount = fLocals.size();
1466 if (f.fDeclaration.fReturnType.fName == "void") {
1467 this->write(ByteCode::Instruction::kReturn);
1468 } else {
1469 this->write(ByteCode::Instruction::kAbort);
1470 }
1471 fOutput->fFunctions.push_back(std::move(result));
1472 SkASSERT(fConditionCount == 0);
1473}
1474
1475void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
1476 if (type.kind() == Type::kOther_Kind) {
1477 return;
1478 } else if (type.kind() == Type::kStruct_Kind) {
1479 for (const auto& f : type.fields()) {
1480 this->gatherUniforms(*f.fType, name + "." + f.fName);
1481 }
1482 } else if (type.kind() == Type::kArray_Kind) {
1483 for (int i = 0; i < type.columns(); ++i) {
1484 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
1485 }
1486 } else {
1487 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
1488 fOutput->fUniformSlotCount });
1489 fOutput->fUniformSlotCount += type.columns() * type.rows();
Brian Osman80164412019-06-07 13:00:23 -04001490 }
1491}
1492
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001493bool ByteCodeGenerator::generateCode() {
1494 fOutput->fGlobalSlotCount = 0;
1495 fOutput->fUniformSlotCount = 0;
1496 for (const auto& pe : fProgram) {
1497 if (pe.fKind == ProgramElement::kVar_Kind) {
1498 VarDeclarations& decl = (VarDeclarations&) pe;
1499 for (const auto& v : decl.fVars) {
1500 const Variable* declVar = ((VarDeclaration&) *v).fVar;
1501 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
1502 continue;
1503 }
1504 if (is_uniform(*declVar)) {
1505 this->gatherUniforms(declVar->fType, declVar->fName);
1506 } else {
1507 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
1508 }
1509 }
1510 }
1511 }
1512 for (const auto& pe : fProgram) {
1513 if (pe.fKind == ProgramElement::kFunction_Kind) {
1514 FunctionDefinition& f = (FunctionDefinition&) pe;
1515 fFunctions.push_back(&f);
1516 this->writeFunction(f);
1517 }
1518 }
1519 return fErrors.errorCount() == 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001520}
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001521
1522} // namespace