blob: 3cf16b3c839091d0be82d5025a2443d9865f5f18 [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"
Ethan Nicholas91164d12019-05-15 15:29:54 -040011#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/sksl/SkSLInterpreter.h"
13#include "src/sksl/ir/SkSLBinaryExpression.h"
14#include "src/sksl/ir/SkSLExpressionStatement.h"
15#include "src/sksl/ir/SkSLForStatement.h"
16#include "src/sksl/ir/SkSLFunctionCall.h"
17#include "src/sksl/ir/SkSLFunctionReference.h"
18#include "src/sksl/ir/SkSLIfStatement.h"
19#include "src/sksl/ir/SkSLIndexExpression.h"
20#include "src/sksl/ir/SkSLPostfixExpression.h"
21#include "src/sksl/ir/SkSLPrefixExpression.h"
22#include "src/sksl/ir/SkSLProgram.h"
23#include "src/sksl/ir/SkSLStatement.h"
24#include "src/sksl/ir/SkSLTernaryExpression.h"
25#include "src/sksl/ir/SkSLVarDeclarations.h"
26#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
27#include "src/sksl/ir/SkSLVariableReference.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040028
29namespace SkSL {
30
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040031static constexpr int UNINITIALIZED = 0xDEADBEEF;
32
Chris Dalton3fb15032019-05-21 06:32:29 +000033Interpreter::Interpreter(std::unique_ptr<Program> program, std::unique_ptr<ByteCode> byteCode,
Ethan Nicholasdfcad062019-05-07 12:53:34 -040034 Interpreter::Value inputs[])
35 : fProgram(std::move(program))
Chris Dalton3fb15032019-05-21 06:32:29 +000036 , fByteCode(std::move(byteCode)) {
37 for (int i = 0; i < fByteCode->fGlobalCount; ++i) {
38 fGlobals.push_back(Value((int) UNINITIALIZED));
39 }
Brian Osmand369a5e2019-05-09 13:13:25 -040040 this->setInputs(inputs);
41}
42
43void Interpreter::setInputs(Interpreter::Value inputs[]) {
Chris Dalton3fb15032019-05-21 06:32:29 +000044 for (int i = fByteCode->fInputSlots.size() - 1; i >= 0; --i) {
45 fGlobals[fByteCode->fInputSlots[i]] = inputs[i];
Ethan Nicholasdfcad062019-05-07 12:53:34 -040046 }
47}
48
49void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
50 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040051#ifdef TRACE
52 this->disassemble(f);
53#endif
Ethan Nicholasdfcad062019-05-07 12:53:34 -040054 Value smallStack[128];
55 std::unique_ptr<Value[]> largeStack;
56 Value* stack = smallStack;
Brian Osman226668a2019-05-14 16:47:30 -040057 if ((int) SK_ARRAY_COUNT(smallStack) < f.fStackCount) {
58 largeStack.reset(new Value[f.fStackCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040059 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 }
Chris Dalton3fb15032019-05-21 06:32:29 +000061 run(f, stack, args, outReturn);
62 int offset = 0;
63 for (const auto& p : f.fDeclaration.fParameters) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040064 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
Chris Dalton3fb15032019-05-21 06:32:29 +000065 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
66 args[offset] = stack[offset];
67 ++offset;
68 }
69 } else {
70 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040071 }
72 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040073}
74
Chris Dalton3fb15032019-05-21 06:32:29 +000075struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
76 Interpreter* fInterpreter;
77 const FunctionDefinition* fFunction;
78};
79
80#define STACK_SIZE() (int) (sp - stack + 1)
81
82#define TOP() (SkASSERT(sp >= stack), *sp)
83
84#define POP() (SkASSERT(sp >= stack), *(sp--))
85
86#define PUSH(v) (SkASSERT(sp + 1 >= stack), *(++sp) = v)
87
88#define READ8() (*(ip++))
89
Mike Klein76346ac2019-05-17 11:57:10 -050090template <typename T>
91static T unaligned_load(const void* ptr) {
92 T val;
93 memcpy(&val, ptr, sizeof(val));
94 return val;
95}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040096
Mike Klein76346ac2019-05-17 11:57:10 -050097#define READ16() (ip += 2, unaligned_load<uint16_t>(ip - 2))
98#define READ32() (ip += 4, unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040099
Chris Dalton3fb15032019-05-21 06:32:29 +0000100static String value_string(uint32_t v) {
101 union { uint32_t u; float f; } pun = { v };
102 return to_string(v) + "(" + to_string(pun.f) + ")";
103}
104
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400105#define VECTOR_DISASSEMBLE(op, text) \
106 case ByteCodeInstruction::op: printf(text); break; \
107 case ByteCodeInstruction::op##2: printf(text "2"); break; \
108 case ByteCodeInstruction::op##3: printf(text "3"); break; \
109 case ByteCodeInstruction::op##4: printf(text "4"); break;
110
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400111void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400112 const uint8_t* ip = f.fCode.data();
113 while (ip < f.fCode.data() + f.fCode.size()) {
114 printf("%d: ", (int) (ip - f.fCode.data()));
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400115 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400116 VECTOR_DISASSEMBLE(kAddF, "addf")
117 VECTOR_DISASSEMBLE(kAddI, "addi")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400118 case ByteCodeInstruction::kAndB: printf("andb"); break;
119 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400120 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Brian Osman226668a2019-05-14 16:47:30 -0400121 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400122 case ByteCodeInstruction::kCallExternal: {
123 int argumentCount = READ8();
124 int returnCount = READ8();
125 int externalValue = READ8();
126 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
127 break;
128 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400129 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
130 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
131 VECTOR_DISASSEMBLE(kCompareFEQ, "comparefeq")
132 VECTOR_DISASSEMBLE(kCompareFNEQ, "comparefneq")
133 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
134 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
135 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
136 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
137 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
138 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
139 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
140 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
141 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
142 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
143 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
144 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400146 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400147 break;
148 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400149 VECTOR_DISASSEMBLE(kDivideF, "dividef")
150 VECTOR_DISASSEMBLE(kDivideS, "divideS")
151 VECTOR_DISASSEMBLE(kDivideU, "divideu")
152 VECTOR_DISASSEMBLE(kDup, "dup")
153 VECTOR_DISASSEMBLE(kFloatToInt, "floattoint")
Brian Osman1091f022019-05-16 09:42:16 -0400154 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400155 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
156 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
157 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400158 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400159 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
160 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
161 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400163 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400164 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400165 printf("loadswizzle %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400167 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 }
169 break;
170 }
Brian Osmanb7451292019-05-15 13:02:13 -0400171 case ByteCodeInstruction::kLoadSwizzleGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400172 int target = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400173 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400174 printf("loadswizzleglobal %d %d", target, count);
Brian Osmanb7451292019-05-15 13:02:13 -0400175 for (int i = 0; i < count; ++i) {
176 printf(", %d", READ8());
177 }
178 break;
179 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400180 VECTOR_DISASSEMBLE(kMultiplyF, "multiplyf")
181 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
182 VECTOR_DISASSEMBLE(kNegateF, "negatef")
183 VECTOR_DISASSEMBLE(kNegateS, "negates")
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400184 VECTOR_DISASSEMBLE(kNot, "not")
185 VECTOR_DISASSEMBLE(kOrB, "orb")
186 VECTOR_DISASSEMBLE(kOrI, "ori")
187 VECTOR_DISASSEMBLE(kPop, "pop")
Chris Dalton3fb15032019-05-21 06:32:29 +0000188 case ByteCodeInstruction::kPushImmediate:
189 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400191 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400192 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
193 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
194 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
195 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
196 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
197 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400198 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400199 VECTOR_DISASSEMBLE(kSignedToFloat, "signedtofloat")
Brian Osman1091f022019-05-16 09:42:16 -0400200 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400201 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
202 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
203 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400204 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400205 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
206 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
207 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400209 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400210 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400211 printf("storeswizzle %d %d", target, count);
212 for (int i = 0; i < count; ++i) {
213 printf(", %d", READ8());
214 }
215 break;
216 }
217 case ByteCodeInstruction::kStoreSwizzleGlobal: {
218 int target = READ8();
219 int count = READ8();
220 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400221 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400222 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400223 }
224 break;
225 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400226 VECTOR_DISASSEMBLE(kSubtractF, "subtractf")
227 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400228 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400229 printf("swizzle %d, ", READ8());
230 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400231 printf("%d", count);
232 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400233 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400234 }
235 break;
236 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400237 VECTOR_DISASSEMBLE(kUnsignedToFloat, "unsignedtofloat")
Ethan Nicholas91164d12019-05-15 15:29:54 -0400238 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400239 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
240 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
241 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400242 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400243 }
244 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400245 }
246}
247
Chris Dalton3fb15032019-05-21 06:32:29 +0000248#define VECTOR_BINARY_OP(base, type, src, target, op) \
249 case ByteCodeInstruction::base ## 4: \
250 sp[-4].target = sp[-4].src op sp[0].src; \
251 POP(); \
252 /* fall through */ \
253 case ByteCodeInstruction::base ## 3: \
254 count = (int) ByteCodeInstruction::base - (int) inst - 1; \
255 sp[count].target = sp[count].src op sp[0].src; \
256 POP(); \
257 /* fall through */ \
258 case ByteCodeInstruction::base ## 2: \
259 count = (int) ByteCodeInstruction::base - (int) inst - 1; \
260 sp[count].target = sp[count].src op sp[0].src; \
261 POP(); \
262 /* fall through */ \
263 case ByteCodeInstruction::base: \
264 count = (int) ByteCodeInstruction::base - (int) inst - 1; \
265 sp[count].target = sp[count].src op sp[0].src; \
266 POP(); \
267 break;
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400268
Chris Dalton3fb15032019-05-21 06:32:29 +0000269#define VECTOR_BINARY_FN(base, type, src, target, fn) \
270 case ByteCodeInstruction::base ## 4: \
271 sp[-4].target = fn(sp[-4].src, sp[0].src); \
272 POP(); \
273 /* fall through */ \
274 case ByteCodeInstruction::base ## 3: \
275 count = (int) ByteCodeInstruction::base - (int) inst - 1; \
276 sp[count].target = fn(sp[count].src, sp[0].src); \
277 POP(); \
278 /* fall through */ \
279 case ByteCodeInstruction::base ## 2: \
280 count = (int) ByteCodeInstruction::base - (int) inst - 1; \
281 sp[count].target = fn(sp[count].src, sp[0].src); \
282 POP(); \
283 /* fall through */ \
284 case ByteCodeInstruction::base: \
285 count = (int) ByteCodeInstruction::base - (int) inst - 1; \
286 sp[count].target = fn(sp[count].src, sp[0].src); \
287 POP(); \
288 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400289
Brian Osman226668a2019-05-14 16:47:30 -0400290struct StackFrame {
291 const uint8_t* fCode;
292 const uint8_t* fIP;
293 Interpreter::Value* fStack;
294};
295
Chris Dalton3fb15032019-05-21 06:32:29 +0000296void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
Brian Osman226668a2019-05-14 16:47:30 -0400297 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400298 const uint8_t* ip = code;
Chris Dalton3fb15032019-05-21 06:32:29 +0000299 static constexpr int TMP_SLOTS = 4;
300 Value tmp[TMP_SLOTS];
301 int src;
302 int target;
303 int count;
304 if (f.fParameterCount) {
305 memcpy(stack, args, f.fParameterCount * sizeof(Value));
306 }
307 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
Brian Osman226668a2019-05-14 16:47:30 -0400308 std::vector<StackFrame> frames;
309
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400310 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400311 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400312#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400313 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400314#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400315 switch (inst) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400316 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, fSigned, +)
317 VECTOR_BINARY_OP(kAddF, float, fFloat, fFloat, +)
318 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400319 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400320 break;
Brian Osman226668a2019-05-14 16:47:30 -0400321 case ByteCodeInstruction::kCall: {
322 // Precursor code has pushed all parameters to the stack. Update our bottom of
323 // stack to point at the first parameter, and our sp to point past those parameters
324 // (plus space for locals).
Chris Dalton3fb15032019-05-21 06:32:29 +0000325 target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400326 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
327 frames.push_back({ code, ip, stack });
328 ip = code = fun->fCode.data();
329 stack = sp - fun->fParameterCount + 1;
330 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
331 break;
332 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400333 case ByteCodeInstruction::kCallExternal: {
334 int argumentCount = READ8();
335 int returnCount = READ8();
Chris Dalton3fb15032019-05-21 06:32:29 +0000336 SkASSERT(returnCount <= TMP_SLOTS);
337 target = READ8();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400338 ExternalValue* v = fByteCode->fExternalValues[target];
339 sp -= argumentCount - 1;
340 v->call(sp, tmp);
341 memcpy(sp, tmp, returnCount * sizeof(Value));
342 sp += returnCount - 1;
343 break;
344 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400345 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, fBool, ==)
346 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, fBool, ==)
347 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, fBool, !=)
348 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, fBool, !=)
349 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, fBool, >)
350 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, fBool, >)
351 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, fBool, >)
352 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, fBool, >=)
353 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, fBool, >=)
354 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, fBool, >=)
355 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, fBool, <)
356 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, fBool, <)
357 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, fBool, <)
358 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, fBool, <=)
359 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, fBool, <=)
360 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, fBool, <=)
Chris Dalton3fb15032019-05-21 06:32:29 +0000361 case ByteCodeInstruction::kConditionalBranch:
362 tmp[0].fSigned = READ16(); // target
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400363 if (POP().fBool) {
Chris Dalton3fb15032019-05-21 06:32:29 +0000364 ip = code + tmp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400365 }
366 break;
Chris Dalton3fb15032019-05-21 06:32:29 +0000367 case ByteCodeInstruction::kDebugPrint:
368 tmp[0] = POP();
369 printf("Debug: %d(int), %d(uint), %f(float)\n", tmp[0].fSigned, tmp[0].fUnsigned,
370 tmp[0].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400371 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400372 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, fSigned, /)
373 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, fUnsigned, /)
374 VECTOR_BINARY_OP(kDivideF, float, fFloat, fFloat, /)
Chris Dalton3fb15032019-05-21 06:32:29 +0000375 case ByteCodeInstruction::kDup4:
376 sp[1] = sp[-3];
377 ++sp;
378 // fall through
379 case ByteCodeInstruction::kDup3:
380 count = (int) ByteCodeInstruction::kDup - (int) inst;
381 sp[1] = sp[count];
382 ++sp;
383 // fall through
384 case ByteCodeInstruction::kDup2:
385 count = (int) ByteCodeInstruction::kDup - (int) inst;
386 sp[1] = sp[count];
387 ++sp;
388 // fall through
389 case ByteCodeInstruction::kDup:
390 count = (int) ByteCodeInstruction::kDup - (int) inst;
391 sp[1] = sp[count];
392 ++sp;
393 break;
394 case ByteCodeInstruction::kFloatToInt4:
395 sp[-3].fSigned = (int) sp[-3].fFloat;
396 // fall through
397 case ByteCodeInstruction::kFloatToInt3:
398 sp[-2].fSigned = (int) sp[-2].fFloat;
399 // fall through
400 case ByteCodeInstruction::kFloatToInt2:
401 sp[-1].fSigned = (int) sp[-1].fFloat;
402 // fall through
403 case ByteCodeInstruction::kFloatToInt:
404 sp[0].fSigned = (int) sp[0].fFloat;
405 break;
406 case ByteCodeInstruction::kSignedToFloat4:
407 sp[-3].fFloat = (int) sp[-3].fSigned;
408 // fall through
409 case ByteCodeInstruction::kSignedToFloat3:
410 sp[-2].fFloat = (int) sp[-2].fSigned;
411 // fall through
412 case ByteCodeInstruction::kSignedToFloat2:
413 sp[-1].fFloat = (int) sp[-1].fSigned;
414 // fall through
415 case ByteCodeInstruction::kSignedToFloat:
416 sp[0].fFloat = (int) sp[0].fSigned;
417 break;
418 case ByteCodeInstruction::kUnsignedToFloat4:
419 sp[-3].fFloat = (int) sp[-3].fUnsigned;
420 // fall through
421 case ByteCodeInstruction::kUnsignedToFloat3:
422 sp[-2].fFloat = (int) sp[-2].fUnsigned;
423 // fall through
424 case ByteCodeInstruction::kUnsignedToFloat2:
425 sp[-1].fFloat = (int) sp[-1].fUnsigned;
426 // fall through
427 case ByteCodeInstruction::kUnsignedToFloat:
428 sp[0].fFloat = (int) sp[0].fUnsigned;
429 break;
430 case ByteCodeInstruction::kLoad4:
431 sp[4] = stack[*ip + 3];
432 // fall through
433 case ByteCodeInstruction::kLoad3:
434 sp[3] = stack[*ip + 2];
435 // fall through
436 case ByteCodeInstruction::kLoad2:
437 sp[2] = stack[*ip + 1];
438 // fall through
439 case ByteCodeInstruction::kLoad:
440 sp[1] = stack[*ip];
441 ++ip;
442 sp += (int) inst - (int) ByteCodeInstruction::kLoad + 1;
443 break;
444 case ByteCodeInstruction::kLoadGlobal4:
445 sp[4] = fGlobals[*ip + 3];
446 // fall through
447 case ByteCodeInstruction::kLoadGlobal3:
448 sp[3] = fGlobals[*ip + 2];
449 // fall through
450 case ByteCodeInstruction::kLoadGlobal2:
451 sp[2] = fGlobals[*ip + 1];
452 // fall through
453 case ByteCodeInstruction::kLoadGlobal:
454 sp[1] = fGlobals[*ip];
455 ++ip;
456 sp += (int) inst - (int) ByteCodeInstruction::kLoadGlobal + 1;
457 break;
458 case ByteCodeInstruction::kLoadSwizzle:
459 src = READ8();
460 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400461 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400462 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400463 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400464 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400465 break;
Chris Dalton3fb15032019-05-21 06:32:29 +0000466 case ByteCodeInstruction::kLoadSwizzleGlobal:
467 src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400468 SkASSERT(src < (int) fGlobals.size());
Chris Dalton3fb15032019-05-21 06:32:29 +0000469 count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400470 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400471 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400472 }
473 ip += count;
474 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400475 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, fSigned, *)
476 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, fFloat, *)
477 case ByteCodeInstruction::kNot:
Chris Dalton3fb15032019-05-21 06:32:29 +0000478 TOP().fBool = !TOP().fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400479 break;
Chris Dalton3fb15032019-05-21 06:32:29 +0000480 case ByteCodeInstruction::kNegateF4:
481 sp[-3].fFloat = -sp[-3].fFloat;
482 // fall through
483 case ByteCodeInstruction::kNegateF3:
484 sp[-2].fFloat = -sp[-2].fFloat;
485 // fall through
486 case ByteCodeInstruction::kNegateF2:
487 sp[-1].fFloat = -sp[-1].fFloat;
488 // fall through
489 case ByteCodeInstruction::kNegateF:
490 sp[0].fFloat = -sp[0].fFloat;
491 break;
492 case ByteCodeInstruction::kNegateS4:
493 sp[-3].fSigned = -sp[-3].fSigned;
494 // fall through
495 case ByteCodeInstruction::kNegateS3:
496 sp[-2].fSigned = -sp[-2].fSigned;
497 // fall through
498 case ByteCodeInstruction::kNegateS2:
499 sp[-1].fSigned = -sp[-1].fSigned;
500 // fall through
501 case ByteCodeInstruction::kNegateS:
502 sp[0].fSigned = -sp[0].fSigned;
503 break;
504 case ByteCodeInstruction::kPop:
505 POP();
506 break;
507 case ByteCodeInstruction::kPop2:
508 sp -= 2;
509 break;
510 case ByteCodeInstruction::kPop3:
511 sp -= 3;
512 break;
513 case ByteCodeInstruction::kPop4:
514 sp -= 4;
515 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400516 case ByteCodeInstruction::kPushImmediate:
Chris Dalton3fb15032019-05-21 06:32:29 +0000517 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400518 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400519 case ByteCodeInstruction::kReadExternal: // fall through
520 case ByteCodeInstruction::kReadExternal2: // fall through
521 case ByteCodeInstruction::kReadExternal3: // fall through
Chris Dalton3fb15032019-05-21 06:32:29 +0000522 case ByteCodeInstruction::kReadExternal4:
523 count = (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
524 src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400525 fByteCode->fExternalValues[src]->read(sp + 1);
Chris Dalton3fb15032019-05-21 06:32:29 +0000526 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400527 break;
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400528 VECTOR_BINARY_FN(kRemainderF, int32_t, fFloat, fFloat, fmodf)
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400529 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, fSigned, %)
530 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, fUnsigned, %)
Chris Dalton3fb15032019-05-21 06:32:29 +0000531 case ByteCodeInstruction::kReturn:
532 count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400533 if (frames.empty()) {
534 if (outReturn) {
535 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
536 }
537 return;
538 } else {
539 // When we were called, 'stack' was positioned at the old top-of-stack (where
540 // our parameters were placed). So copy our return values to that same spot.
541 memmove(stack, sp - count + 1, count * sizeof(Value));
542
543 // Now move the stack pointer to the end of the just-pushed return values,
544 // and restore everything else.
545 const StackFrame& frame(frames.back());
546 sp = stack + count - 1;
547 stack = frame.fStack;
548 code = frame.fCode;
549 ip = frame.fIP;
550 frames.pop_back();
551 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400552 }
Chris Dalton3fb15032019-05-21 06:32:29 +0000553 case ByteCodeInstruction::kStore4:
554 stack[*ip + 3] = sp[0];
555 POP();
556 // fall through
557 case ByteCodeInstruction::kStore3:
558 stack[*ip + 2] = sp[0];
559 POP();
560 // fall through
561 case ByteCodeInstruction::kStore2:
562 stack[*ip + 1] = sp[0];
563 POP();
564 case ByteCodeInstruction::kStore:
565 stack[*ip] = sp[0];
566 POP();
567 ++ip;
568 break;
569 case ByteCodeInstruction::kStoreGlobal4:
570 fGlobals[*ip + 3] = sp[0];
571 POP();
572 // fall through
573 case ByteCodeInstruction::kStoreGlobal3:
574 fGlobals[*ip + 2] = sp[0];
575 POP();
576 // fall through
577 case ByteCodeInstruction::kStoreGlobal2:
578 fGlobals[*ip + 1] = sp[0];
579 POP();
580 case ByteCodeInstruction::kStoreGlobal:
581 fGlobals[*ip] = sp[0];
582 POP();
583 ++ip;
584 break;
585 case ByteCodeInstruction::kStoreSwizzle:
586 target = READ8();
587 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400588 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400589 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400590 }
Brian Osman1091f022019-05-16 09:42:16 -0400591 ip += count;
592 break;
Chris Dalton3fb15032019-05-21 06:32:29 +0000593 case ByteCodeInstruction::kStoreSwizzleGlobal:
594 target = READ8();
595 count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400596 for (int i = count - 1; i >= 0; --i) {
597 fGlobals[target + *(ip + i)] = POP();
598 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400599 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400600 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400601 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, fSigned, -)
602 VECTOR_BINARY_OP(kSubtractF, float, fFloat, fFloat, -)
Chris Dalton3fb15032019-05-21 06:32:29 +0000603 case ByteCodeInstruction::kSwizzle:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400604 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400605 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400606 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400607 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400608 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400609 }
610 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400611 case ByteCodeInstruction::kWriteExternal: // fall through
612 case ByteCodeInstruction::kWriteExternal2: // fall through
613 case ByteCodeInstruction::kWriteExternal3: // fall through
Chris Dalton3fb15032019-05-21 06:32:29 +0000614 case ByteCodeInstruction::kWriteExternal4:
615 count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
616 target = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400617 fByteCode->fExternalValues[target]->write(sp - count + 1);
618 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400619 break;
620 default:
Chris Dalton3fb15032019-05-21 06:32:29 +0000621 printf("unsupported instruction %d\n", (int) inst);
622 SkASSERT(false);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400623 }
624#ifdef TRACE
Chris Dalton3fb15032019-05-21 06:32:29 +0000625 printf("STACK(%d):", STACK_SIZE());
626 for (int i = 0; i < STACK_SIZE(); ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400627 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
628 }
629 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400630#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400631 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400632}
633
634} // namespace
635
636#endif