blob: ea926f6929248ef2a0d16d7e407f41a212a2c73a [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/core/SkRasterPipeline.h"
11#include "src/sksl/SkSLInterpreter.h"
12#include "src/sksl/ir/SkSLBinaryExpression.h"
13#include "src/sksl/ir/SkSLExpressionStatement.h"
14#include "src/sksl/ir/SkSLForStatement.h"
15#include "src/sksl/ir/SkSLFunctionCall.h"
16#include "src/sksl/ir/SkSLFunctionReference.h"
17#include "src/sksl/ir/SkSLIfStatement.h"
18#include "src/sksl/ir/SkSLIndexExpression.h"
19#include "src/sksl/ir/SkSLPostfixExpression.h"
20#include "src/sksl/ir/SkSLPrefixExpression.h"
21#include "src/sksl/ir/SkSLProgram.h"
22#include "src/sksl/ir/SkSLStatement.h"
23#include "src/sksl/ir/SkSLTernaryExpression.h"
24#include "src/sksl/ir/SkSLVarDeclarations.h"
25#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
26#include "src/sksl/ir/SkSLVariableReference.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
Ethan Nicholas746035a2019-04-23 13:31:09 -040032Interpreter::Value* Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040033 Interpreter::Value inputs[]) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040034 fCurrentFunction = &f;
35 fStack.clear();
36 fGlobals.clear();
37#ifdef TRACE
38 this->disassemble(f);
39#endif
40 for (int i = 0; i < f.fParameterCount; ++i) {
41 this->push(args[i]);
42 }
43 for (int i = 0; i < f.fLocalCount; ++i) {
44 this->push(Value((int) UNINITIALIZED));
45 }
46 for (int i = 0; i < f.fOwner.fGlobalCount; ++i) {
47 fGlobals.push_back(Value((int) UNINITIALIZED));
48 }
49 for (int i = f.fOwner.fInputSlots.size() - 1; i >= 0; --i) {
50 fGlobals[f.fOwner.fInputSlots[i]] = inputs[i];
51 }
52 run();
53 int offset = 0;
54 for (const auto& p : f.fDeclaration.fParameters) {
55 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
56 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
57 args[offset] = fStack[offset];
58 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040059 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 } else {
61 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040062 }
63 }
Ethan Nicholas746035a2019-04-23 13:31:09 -040064 return fStack.data();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040065}
66
Mike Kleinb11ab572018-10-24 06:42:14 -040067struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040068 Interpreter* fInterpreter;
69 const FunctionDefinition* fFunction;
70};
71
Ethan Nicholas7e603db2019-05-03 12:57:47 -040072#define READ8() code[ip++]
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040073
Ethan Nicholas7e603db2019-05-03 12:57:47 -040074#define READ16() \
75 (SkASSERT(ip % 2 == 0), \
76 ip += 2, \
77 *(uint16_t*) &code[ip - 2])
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040078
Ethan Nicholas7e603db2019-05-03 12:57:47 -040079#define READ32() \
80 (SkASSERT(ip % 4 == 0), \
81 ip += 4, \
82 *(uint32_t*) &code[ip - 4])
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040083
84void Interpreter::push(Value v) {
85 fStack.push_back(v);
86}
87
88Interpreter::Value Interpreter::pop() {
89 Value v = fStack.back();
90 fStack.pop_back();
91 return v;
92}
93
94static String value_string(uint32_t v) {
95 union { uint32_t u; float f; } pun = { v };
96 return to_string(v) + "(" + to_string(pun.f) + ")";
97}
98
99void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400100 int ip = 0;
101 const uint8_t* code = f.fCode.data();
102 while (ip < (int) f.fCode.size()) {
103 printf("%d: ", ip);
104 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400105 case ByteCodeInstruction::kAddF: printf("addf"); break;
106 case ByteCodeInstruction::kAddI: printf("addi"); break;
107 case ByteCodeInstruction::kAndB: printf("andb"); break;
108 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400109 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400110 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
111 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
112 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
113 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
114 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
115 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
116 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
117 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
118 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
119 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
120 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
121 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
122 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
123 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
124 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
125 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
126 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400127 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400128 break;
129 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
130 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
131 case ByteCodeInstruction::kDivideS: printf("divides"); break;
132 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
133 case ByteCodeInstruction::kDup: printf("dup"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400134 case ByteCodeInstruction::kDupDown: printf("dupdown %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400135 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
136 case ByteCodeInstruction::kLoad: printf("load"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400137 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400138 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400139 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 printf("loadswizzle %d", count);
141 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400142 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400143 }
144 break;
145 }
146 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
147 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
148 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
149 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
150 case ByteCodeInstruction::kNegateS: printf("negates"); break;
151 case ByteCodeInstruction::kNot: printf("not"); break;
152 case ByteCodeInstruction::kOrB: printf("orb"); break;
153 case ByteCodeInstruction::kOrI: printf("ori"); break;
154 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400155 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400157 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400158 break;
159 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
160 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400161 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
163 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400164 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400165 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400166 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 printf("storeswizzle %d", count);
168 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400169 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 }
171 break;
172 }
173 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
174 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
175 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400176 printf("swizzle %d, ", READ8());
177 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178 printf("%d", count);
179 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400180 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 }
182 break;
183 }
184 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400185 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
186 default: printf("%d\n", code[ip - 1]);
Ethan Nicholas746035a2019-04-23 13:31:09 -0400187 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188 }
189 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400190 }
191}
192
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400193void Interpreter::dumpStack() {
194 printf("STACK:");
195 for (size_t i = 0; i < fStack.size(); ++i) {
196 printf(" %d(%f)", fStack[i].fSigned, fStack[i].fFloat);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400197 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400198 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400199}
200
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201#define BINARY_OP(inst, type, field, op) \
202 case ByteCodeInstruction::inst: { \
203 type b = this->pop().field; \
Ethan Nicholas95859472019-04-24 12:55:51 -0400204 Value* a = &fStack.back(); \
205 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 break; \
207 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400208
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209static constexpr int VECTOR_MAX = 16;
210
211#define VECTOR_BINARY_OP(inst, type, field, op) \
212 case ByteCodeInstruction::inst: { \
213 Value result[VECTOR_MAX]; \
214 for (int i = count - 1; i >= 0; --i) { \
215 result[i] = this->pop(); \
216 } \
217 for (int i = count - 1; i >= 0; --i) { \
218 result[i] = this->pop().field op result[i].field; \
219 } \
220 for (int i = 0; i < count; ++i) { \
221 this->push(result[i]); \
222 } \
223 break; \
224 }
225
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400226void Interpreter::run() {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400227 int ip = 0;
228 const uint8_t* code = fCurrentFunction->fCode.data();
229 for (;;) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400230#ifdef TRACE
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400231 printf("at %d\n", ip);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400232#endif
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400233 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400234 switch (inst) {
235 BINARY_OP(kAddI, int32_t, fSigned, +)
236 BINARY_OP(kAddF, float, fFloat, +)
237 case ByteCodeInstruction::kBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400238 ip = READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400239 break;
240 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
241 BINARY_OP(kCompareFEQ, float, fFloat, ==)
242 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
243 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
244 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
245 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
246 BINARY_OP(kCompareFGT, float, fFloat, >)
247 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
248 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
249 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
250 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
251 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
252 BINARY_OP(kCompareFLT, float, fFloat, <)
253 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
254 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
255 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
256 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400257 int target = READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400258 if (this->pop().fBool) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400259 ip = target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400260 }
261 break;
262 }
263 case ByteCodeInstruction::kDebugPrint: {
264 Value v = this->pop();
265 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
266 break;
267 }
268 BINARY_OP(kDivideS, int32_t, fSigned, /)
269 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
270 BINARY_OP(kDivideF, float, fFloat, /)
271 case ByteCodeInstruction::kDup:
272 this->push(fStack.back());
273 break;
274 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400275 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400276 for (int i = 0; i < count; ++i) {
277 fStack.insert(fStack.end() - i - count - 1, fStack[fStack.size() - i - 1]);
278 }
279 break;
280 }
281 case ByteCodeInstruction::kFloatToInt: {
282 Value& top = fStack.back();
283 top.fSigned = (int) top.fFloat;
284 break;
285 }
286 case ByteCodeInstruction::kSignedToFloat: {
287 Value& top = fStack.back();
288 top.fFloat = (float) top.fSigned;
289 break;
290 }
291 case ByteCodeInstruction::kUnsignedToFloat: {
292 Value& top = fStack.back();
293 top.fFloat = (float) top.fUnsigned;
294 break;
295 }
296 case ByteCodeInstruction::kLoad: {
297 int target = this->pop().fSigned;
298 SkASSERT(target < (int) fStack.size());
299 this->push(fStack[target]);
300 break;
301 }
302 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400303 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400304 SkASSERT(target < (int) fGlobals.size());
305 this->push(fGlobals[target]);
306 break;
307 }
308 case ByteCodeInstruction::kLoadSwizzle: {
309 Value target = this->pop();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400310 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400311 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400312 SkASSERT(target.fSigned + fCurrentFunction->fCode[ip + i] < (int) fStack.size());
313 this->push(fStack[target.fSigned + fCurrentFunction->fCode[ip + i]]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400314 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400315 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400316 break;
317 }
318 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
319 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
320 BINARY_OP(kMultiplyF, float, fFloat, *)
321 case ByteCodeInstruction::kNot: {
322 Value& top = fStack.back();
323 top.fBool = !top.fBool;
324 break;
325 }
326 case ByteCodeInstruction::kNegateF: {
327 Value& top = fStack.back();
328 top.fFloat = -top.fFloat;
329 break;
330 }
331 case ByteCodeInstruction::kNegateS: {
332 Value& top = fStack.back();
333 top.fSigned = -top.fSigned;
334 break;
335 }
336 case ByteCodeInstruction::kNop:
337 break;
338 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400339 for (int i = READ8(); i > 0; --i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400340 this->pop();
341 }
342 break;
343 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400344 this->push(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400345 break;
346 BINARY_OP(kRemainderS, int32_t, fSigned, %)
347 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
348 case ByteCodeInstruction::kReturn: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400349 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400350 for (int i = 0; i < count; ++i) {
351 fStack[i] = fStack[fStack.size() - count + i];
352 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400353 return;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400354 }
355 case ByteCodeInstruction::kStore: {
356 Value value = this->pop();
357 int target = this->pop().fSigned;
358 SkASSERT(target < (int) fStack.size());
359 fStack[target] = value;
360 break;
361 }
362 case ByteCodeInstruction::kStoreGlobal: {
363 Value value = this->pop();
364 int target = this->pop().fSigned;
365 SkASSERT(target < (int) fGlobals.size());
366 fGlobals[target] = value;
367 break;
368 }
369 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400370 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400371 int target = fStack[fStack.size() - count - 1].fSigned;
372 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400373 SkASSERT(target + fCurrentFunction->fCode[ip + i] < (int) fStack.size());
374 fStack[target + fCurrentFunction->fCode[ip + i]] = this->pop();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400375 }
376 this->pop();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400377 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400378 break;
379 }
380 BINARY_OP(kSubtractI, int32_t, fSigned, -)
381 BINARY_OP(kSubtractF, float, fFloat, -)
382 case ByteCodeInstruction::kSwizzle: {
383 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400384 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400385 vec[i] = this->pop();
386 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400387 for (int i = READ8() - 1; i >= 0; --i) {
388 this->push(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400389 }
390 break;
391 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400392 case ByteCodeInstruction::kVector: {
393 uint8_t count = READ8();
394 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
395 switch (inst) {
396 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
397 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
398 case ByteCodeInstruction::kBranch:
399 ip = READ16();
400 break;
401 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
402 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
403 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
404 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
405 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
406 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
407 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
408 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
409 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
410 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
411 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
412 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
413 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
414 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
415 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
416 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
417 case ByteCodeInstruction::kConditionalBranch: {
418 int target = READ16();
419 if (this->pop().fBool) {
420 ip = target;
421 }
422 break;
423 }
424 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
425 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
426 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
427 case ByteCodeInstruction::kFloatToInt: {
428 for (int i = 0; i < count; ++i) {
429 Value& v = fStack[fStack.size() - i - 1];
430 v.fSigned = (int) v.fFloat;
431 }
432 break;
433 }
434 case ByteCodeInstruction::kSignedToFloat: {
435 for (int i = 0; i < count; ++i) {
436 Value& v = fStack[fStack.size() - i - 1];
437 v.fFloat = (float) v.fSigned;
438 }
439 break;
440 }
441 case ByteCodeInstruction::kUnsignedToFloat: {
442 for (int i = 0; i < count; ++i) {
443 Value& v = fStack[fStack.size() - i - 1];
444 v.fFloat = (float) v.fUnsigned;
445 }
446 break;
447 }
448 case ByteCodeInstruction::kLoad: {
449 int target = this->pop().fSigned;
450 for (int i = 0; i < count; ++i) {
451 SkASSERT(target < (int) fStack.size());
452 this->push(fStack[target++]);
453 }
454 break;
455 }
456 case ByteCodeInstruction::kLoadGlobal: {
457 int target = READ8();
458 SkASSERT(target < (int) fGlobals.size());
459 this->push(fGlobals[target]);
460 break;
461 }
462 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
463 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
464 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
465 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
466 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
467 case ByteCodeInstruction::kStore: {
468 int target = fStack[fStack.size() - count - 1].fSigned + count;
469 for (int i = count - 1; i >= 0; --i) {
470 SkASSERT(target < (int) fStack.size());
471 fStack[--target] = this->pop();
472 }
473 break;
474 }
475 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
476 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
477 default:
478 printf("unsupported instruction %d\n", (int) inst);
479 SkASSERT(false);
480 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400481 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400482 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400483 default:
484 printf("unsupported instruction %d\n", (int) inst);
485 SkASSERT(false);
486 }
487#ifdef TRACE
488 this->dumpStack();
489#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400490 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400491}
492
493} // namespace
494
495#endif