blob: f427cf212cec931bdba464dd2eeb22f6dcf42c57 [file] [log] [blame]
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_STANDALONE
9
10#include "SkSLInterpreter.h"
11#include "ir/SkSLBinaryExpression.h"
12#include "ir/SkSLExpressionStatement.h"
13#include "ir/SkSLForStatement.h"
14#include "ir/SkSLFunctionCall.h"
15#include "ir/SkSLFunctionReference.h"
16#include "ir/SkSLIfStatement.h"
17#include "ir/SkSLIndexExpression.h"
18#include "ir/SkSLPostfixExpression.h"
19#include "ir/SkSLPrefixExpression.h"
20#include "ir/SkSLProgram.h"
21#include "ir/SkSLStatement.h"
22#include "ir/SkSLTernaryExpression.h"
23#include "ir/SkSLVarDeclarations.h"
24#include "ir/SkSLVarDeclarationsStatement.h"
25#include "ir/SkSLVariableReference.h"
26#include "SkRasterPipeline.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040027
28namespace SkSL {
29
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040030static constexpr int UNINITIALIZED = 0xDEADBEEF;
31
32Interpreter::Value Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
33 Interpreter::Value inputs[]) {
34 fIP = 0;
35 fCurrentFunction = &f;
36 fStack.clear();
37 fGlobals.clear();
38#ifdef TRACE
39 this->disassemble(f);
40#endif
41 for (int i = 0; i < f.fParameterCount; ++i) {
42 this->push(args[i]);
43 }
44 for (int i = 0; i < f.fLocalCount; ++i) {
45 this->push(Value((int) UNINITIALIZED));
46 }
47 for (int i = 0; i < f.fOwner.fGlobalCount; ++i) {
48 fGlobals.push_back(Value((int) UNINITIALIZED));
49 }
50 for (int i = f.fOwner.fInputSlots.size() - 1; i >= 0; --i) {
51 fGlobals[f.fOwner.fInputSlots[i]] = inputs[i];
52 }
53 run();
54 int offset = 0;
55 for (const auto& p : f.fDeclaration.fParameters) {
56 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
57 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
58 args[offset] = fStack[offset];
59 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040060 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040061 } else {
62 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040063 }
64 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040065 return fReturnValue;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040066}
67
Mike Kleinb11ab572018-10-24 06:42:14 -040068struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040069 Interpreter* fInterpreter;
70 const FunctionDefinition* fFunction;
71};
72
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040073uint8_t Interpreter::read8() {
74 return fCurrentFunction->fCode[fIP++];
75}
76
77uint16_t Interpreter::read16() {
78 uint16_t result = (fCurrentFunction->fCode[fIP ] << 8) +
79 fCurrentFunction->fCode[fIP + 1];
80 fIP += 2;
81 return result;
82}
83
84uint32_t Interpreter::read32() {
85 uint32_t result = (fCurrentFunction->fCode[fIP] << 24) +
86 (fCurrentFunction->fCode[fIP + 1] << 16) +
87 (fCurrentFunction->fCode[fIP + 2] << 8) +
88 fCurrentFunction->fCode[fIP + 3];
89 fIP += 4;
90 return result;
91}
92
93void Interpreter::push(Value v) {
94 fStack.push_back(v);
95}
96
97Interpreter::Value Interpreter::pop() {
98 Value v = fStack.back();
99 fStack.pop_back();
100 return v;
101}
102
103static String value_string(uint32_t v) {
104 union { uint32_t u; float f; } pun = { v };
105 return to_string(v) + "(" + to_string(pun.f) + ")";
106}
107
108void Interpreter::disassemble(const ByteCodeFunction& f) {
109 SkASSERT(fIP == 0);
110 while (fIP < (int) f.fCode.size()) {
111 printf("%d: ", fIP);
112 switch ((ByteCodeInstruction) this->read8()) {
113 case ByteCodeInstruction::kAddF: printf("addf"); break;
114 case ByteCodeInstruction::kAddI: printf("addi"); break;
115 case ByteCodeInstruction::kAndB: printf("andb"); break;
116 case ByteCodeInstruction::kAndI: printf("andi"); break;
117 case ByteCodeInstruction::kBranch: printf("branch %d", this->read16()); break;
118 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
119 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
120 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
121 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
122 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
123 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
124 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
125 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
126 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
127 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
128 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
129 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
130 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
131 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
132 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
133 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
134 case ByteCodeInstruction::kConditionalBranch:
135 printf("conditionalbranch %d", this->read16());
136 break;
137 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
138 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
139 case ByteCodeInstruction::kDivideS: printf("divides"); break;
140 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
141 case ByteCodeInstruction::kDup: printf("dup"); break;
142 case ByteCodeInstruction::kDupDown: printf("dupdown %d", this->read8()); break;
143 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
144 case ByteCodeInstruction::kLoad: printf("load"); break;
145 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal"); break;
146 case ByteCodeInstruction::kLoadSwizzle: {
147 int count = this->read8();
148 printf("loadswizzle %d", count);
149 for (int i = 0; i < count; ++i) {
150 printf(", %d", this->read8());
151 }
152 break;
153 }
154 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
155 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
156 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
157 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
158 case ByteCodeInstruction::kNegateS: printf("negates"); break;
159 case ByteCodeInstruction::kNot: printf("not"); break;
160 case ByteCodeInstruction::kOrB: printf("orb"); break;
161 case ByteCodeInstruction::kOrI: printf("ori"); break;
162 case ByteCodeInstruction::kParameter: printf("parameter"); break;
163 case ByteCodeInstruction::kPop: printf("pop %d", this->read8()); break;
164 case ByteCodeInstruction::kPushImmediate:
165 printf("pushimmediate %s", value_string(this->read32()).c_str());
166 break;
167 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
168 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
169 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
170 case ByteCodeInstruction::kStore: printf("store"); break;
171 case ByteCodeInstruction::kStoreSwizzle: {
172 int count = this->read8();
173 printf("storeswizzle %d", count);
174 for (int i = 0; i < count; ++i) {
175 printf(", %d", this->read8());
176 }
177 break;
178 }
179 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
180 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
181 case ByteCodeInstruction::kSwizzle: {
182 printf("swizzle %d, ", this->read8());
183 int count = this->read8();
184 printf("%d", count);
185 for (int i = 0; i < count; ++i) {
186 printf(", %d", this->read8());
187 }
188 break;
189 }
190 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
191 case ByteCodeInstruction::kVector: printf("vector%d", this->read8()); break;
192 default: SkASSERT(false);
193 }
194 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400195 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196 fIP = 0;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400197}
198
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400199void Interpreter::dumpStack() {
200 printf("STACK:");
201 for (size_t i = 0; i < fStack.size(); ++i) {
202 printf(" %d(%f)", fStack[i].fSigned, fStack[i].fFloat);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400203 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400205}
206
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400207#define BINARY_OP(inst, type, field, op) \
208 case ByteCodeInstruction::inst: { \
209 type b = this->pop().field; \
210 type a = this->pop().field; \
211 this->push(Value(a op b)); \
212 break; \
213 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400214
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400215void Interpreter::next() {
216#ifdef TRACE
217 printf("at %d\n", fIP);
218#endif
219 ByteCodeInstruction inst = (ByteCodeInstruction) this->read8();
220 switch (inst) {
221 BINARY_OP(kAddI, int32_t, fSigned, +)
222 BINARY_OP(kAddF, float, fFloat, +)
223 case ByteCodeInstruction::kBranch:
224 fIP = this->read16();
225 break;
226 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
227 BINARY_OP(kCompareFEQ, float, fFloat, ==)
228 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
229 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
230 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
231 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
232 BINARY_OP(kCompareFGT, float, fFloat, >)
233 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
234 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
235 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
236 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
237 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
238 BINARY_OP(kCompareFLT, float, fFloat, <)
239 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
240 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
241 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
242 case ByteCodeInstruction::kConditionalBranch: {
243 int target = this->read16();
244 if (this->pop().fBool) {
245 fIP = target;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400246 }
247 break;
248 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400249 case ByteCodeInstruction::kDebugPrint: {
250 Value v = this->pop();
251 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400252 break;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400253 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400254 BINARY_OP(kDivideS, int32_t, fSigned, /)
255 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
256 BINARY_OP(kDivideF, float, fFloat, /)
257 case ByteCodeInstruction::kDup:
258 this->push(fStack.back());
259 break;
260 case ByteCodeInstruction::kDupDown: {
261 int count = this->read8();
262 for (int i = 0; i < count; ++i) {
263 fStack.insert(fStack.end() - i - count - 1, fStack[fStack.size() - i - 1]);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400264 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400265 break;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400266 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400267 case ByteCodeInstruction::kFloatToInt: {
268 Value& top = fStack.back();
269 top.fSigned = (int) top.fFloat;
270 break;
271 }
272 case ByteCodeInstruction::kSignedToFloat: {
273 Value& top = fStack.back();
274 top.fFloat = (float) top.fSigned;
275 break;
276 }
277 case ByteCodeInstruction::kUnsignedToFloat: {
278 Value& top = fStack.back();
279 top.fFloat = (float) top.fUnsigned;
280 break;
281 }
282 case ByteCodeInstruction::kLoad: {
283 int target = this->pop().fSigned;
284 SkASSERT(target < (int) fStack.size());
285 this->push(fStack[target]);
286 break;
287 }
288 case ByteCodeInstruction::kLoadGlobal: {
289 int target = this->read8();
290 SkASSERT(target < (int) fGlobals.size());
291 this->push(fGlobals[target]);
292 break;
293 }
294 case ByteCodeInstruction::kLoadSwizzle: {
295 Value target = this->pop();
296 int count = read8();
297 for (int i = 0; i < count; ++i) {
298 SkASSERT(target.fSigned + fCurrentFunction->fCode[fIP + i] < (int) fStack.size());
299 this->push(fStack[target.fSigned + fCurrentFunction->fCode[fIP + i]]);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400300 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400301 fIP += count;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400302 break;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400303 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400304 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
305 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
306 BINARY_OP(kMultiplyF, float, fFloat, *)
307 case ByteCodeInstruction::kNot: {
308 Value& top = fStack.back();
309 top.fBool = !top.fBool;
310 break;
311 }
312 case ByteCodeInstruction::kNegateF:
313 this->push(-this->pop().fFloat);
314 case ByteCodeInstruction::kNegateS:
315 this->push(-this->pop().fSigned);
316 case ByteCodeInstruction::kPop:
317 for (int i = read8(); i > 0; --i) {
318 this->pop();
319 }
320 break;
321 case ByteCodeInstruction::kPushImmediate:
322 this->push(Value((int) read32()));
323 break;
324 BINARY_OP(kRemainderS, int32_t, fSigned, %)
325 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
326 case ByteCodeInstruction::kStore: {
327 Value value = this->pop();
328 int target = this->pop().fSigned;
329 SkASSERT(target < (int) fStack.size());
330 fStack[target] = value;
331 break;
332 }
333 case ByteCodeInstruction::kStoreGlobal: {
334 Value value = this->pop();
335 int target = this->pop().fSigned;
336 SkASSERT(target < (int) fGlobals.size());
337 fGlobals[target] = value;
338 break;
339 }
340 case ByteCodeInstruction::kStoreSwizzle: {
341 int count = read8();
342 int target = fStack[fStack.size() - count - 1].fSigned;
343 for (int i = count - 1; i >= 0; --i) {
344 SkASSERT(target + fCurrentFunction->fCode[fIP + i] < (int) fStack.size());
345 fStack[target + fCurrentFunction->fCode[fIP + i]] = this->pop();
346 }
347 this->pop();
348 fIP += count;
349 break;
350 }
351 BINARY_OP(kSubtractI, int32_t, fSigned, -)
352 BINARY_OP(kSubtractF, float, fFloat, -)
353 case ByteCodeInstruction::kSwizzle: {
354 Value vec[4];
355 for (int i = this->read8() - 1; i >= 0; --i) {
356 vec[i] = this->pop();
357 }
358 for (int i = this->read8() - 1; i >= 0; --i) {
359 this->push(vec[this->read8()]);
360 }
361 break;
362 }
363 case ByteCodeInstruction::kVector:
364 this->nextVector(this->read8());
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400365 break;
366 default:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400367 printf("unsupported instruction %d\n", (int) inst);
368 SkASSERT(false);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400369 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400370#ifdef TRACE
371 this->dumpStack();
372#endif
373}
374
375static constexpr int VECTOR_MAX = 16;
376
377#define VECTOR_BINARY_OP(inst, type, field, op) \
378 case ByteCodeInstruction::inst: { \
379 Value result[VECTOR_MAX]; \
380 for (int i = count - 1; i >= 0; --i) { \
381 result[i] = this->pop(); \
382 } \
383 for (int i = count - 1; i >= 0; --i) { \
384 result[i] = this->pop().field op result[i].field; \
385 } \
386 for (int i = 0; i < count; ++i) { \
387 this->push(result[i]); \
388 } \
389 break; \
390 }
391
392void Interpreter::nextVector(int count) {
393 ByteCodeInstruction inst = (ByteCodeInstruction) this->read8();
394 switch (inst) {
395 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
396 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
397 case ByteCodeInstruction::kBranch:
398 fIP = this->read16();
399 break;
400 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
401 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
402 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
403 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
404 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
405 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
406 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
407 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
408 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
409 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
410 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
411 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
412 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
413 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
414 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
415 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
416 case ByteCodeInstruction::kConditionalBranch: {
417 int target = this->read16();
418 if (this->pop().fBool) {
419 fIP = target;
420 }
421 break;
422 }
423 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
424 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
425 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
426 case ByteCodeInstruction::kFloatToInt: {
427 for (int i = 0; i < count; ++i) {
428 Value& v = fStack[fStack.size() - i - 1];
429 v.fSigned = (int) v.fFloat;
430 }
431 break;
432 }
433 case ByteCodeInstruction::kSignedToFloat: {
434 for (int i = 0; i < count; ++i) {
435 Value& v = fStack[fStack.size() - i - 1];
436 v.fFloat = (float) v.fSigned;
437 }
438 break;
439 }
440 case ByteCodeInstruction::kUnsignedToFloat: {
441 for (int i = 0; i < count; ++i) {
442 Value& v = fStack[fStack.size() - i - 1];
443 v.fFloat = (float) v.fUnsigned;
444 }
445 break;
446 }
447 case ByteCodeInstruction::kLoad: {
448 int target = this->pop().fSigned;
449 for (int i = 0; i < count; ++i) {
450 SkASSERT(target < (int) fStack.size());
451 this->push(fStack[target++]);
452 }
453 break;
454 }
455 case ByteCodeInstruction::kLoadGlobal: {
456 int target = this->read8();
457 SkASSERT(target < (int) fGlobals.size());
458 this->push(fGlobals[target]);
459 break;
460 }
461 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
462 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
463 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
464 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
465 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
466 case ByteCodeInstruction::kStore: {
467 int target = fStack[fStack.size() - count - 1].fSigned + count;
468 for (int i = count - 1; i >= 0; --i) {
469 SkASSERT(target < (int) fStack.size());
470 fStack[--target] = this->pop();
471 }
472 break;
473 }
474 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
475 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
476 case ByteCodeInstruction::kVector:
477 this->nextVector(this->read8());
478 default:
479 printf("unsupported instruction %d\n", (int) inst);
480 SkASSERT(false);
481 }
482}
483
484void Interpreter::run() {
485 while (fIP < (int) fCurrentFunction->fCode.size()) {
486 next();
487 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400488}
489
490} // namespace
491
492#endif