blob: f05a645c8b38b30397727ca4bbbaadba1a0f4bb1 [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 Nicholasdfcad062019-05-07 12:53:34 -040032Interpreter::Interpreter(std::unique_ptr<Program> program, std::unique_ptr<ByteCode> byteCode,
33 Interpreter::Value inputs[])
34 : fProgram(std::move(program))
35 , fByteCode(std::move(byteCode)) {
36 for (int i = 0; i < fByteCode->fGlobalCount; ++i) {
37 fGlobals.push_back(Value((int) UNINITIALIZED));
38 }
Brian Osmand369a5e2019-05-09 13:13:25 -040039 this->setInputs(inputs);
40}
41
42void Interpreter::setInputs(Interpreter::Value inputs[]) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040043 for (int i = fByteCode->fInputSlots.size() - 1; i >= 0; --i) {
44 fGlobals[fByteCode->fInputSlots[i]] = inputs[i];
45 }
46}
47
48void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
49 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040050#ifdef TRACE
51 this->disassemble(f);
52#endif
Ethan Nicholasdfcad062019-05-07 12:53:34 -040053 Value smallStack[128];
54 std::unique_ptr<Value[]> largeStack;
55 Value* stack = smallStack;
Brian Osman226668a2019-05-14 16:47:30 -040056 if ((int) SK_ARRAY_COUNT(smallStack) < f.fStackCount) {
57 largeStack.reset(new Value[f.fStackCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040058 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059 }
Brian Osman226668a2019-05-14 16:47:30 -040060 run(f, stack, args, outReturn);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040061 int offset = 0;
62 for (const auto& p : f.fDeclaration.fParameters) {
63 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
64 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040065 args[offset] = stack[offset];
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040066 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040067 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040068 } else {
69 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040070 }
71 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040072}
73
Mike Kleinb11ab572018-10-24 06:42:14 -040074struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040075 Interpreter* fInterpreter;
76 const FunctionDefinition* fFunction;
77};
78
Ethan Nicholasdfcad062019-05-07 12:53:34 -040079#define STACK_SIZE() (int) (sp - stack + 1)
80
81#define TOP() (*sp)
82
83#define POP() (*(sp--))
84
85#define PUSH(v) (*(++sp) = v)
86
87#define READ8() (*(ip++))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040088
Ethan Nicholas7e603db2019-05-03 12:57:47 -040089#define READ16() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040090 (SkASSERT((intptr_t) ip % 2 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040091 ip += 2, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040092 *(uint16_t*) (ip - 2))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040093
Ethan Nicholas7e603db2019-05-03 12:57:47 -040094#define READ32() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040095 (SkASSERT((intptr_t) ip % 4 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040096 ip += 4, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040097 *(uint32_t*) (ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040098
99static String value_string(uint32_t v) {
100 union { uint32_t u; float f; } pun = { v };
101 return to_string(v) + "(" + to_string(pun.f) + ")";
102}
103
104void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400105 const uint8_t* ip = f.fCode.data();
106 while (ip < f.fCode.data() + f.fCode.size()) {
107 printf("%d: ", (int) (ip - f.fCode.data()));
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400108 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400109 case ByteCodeInstruction::kAddF: printf("addf"); break;
110 case ByteCodeInstruction::kAddI: printf("addi"); break;
111 case ByteCodeInstruction::kAndB: printf("andb"); break;
112 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400113 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Brian Osman226668a2019-05-14 16:47:30 -0400114 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400115 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
116 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
117 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
118 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
119 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
120 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
121 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
122 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
123 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
124 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
125 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
126 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
127 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
128 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
129 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
130 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
131 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400132 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400133 break;
134 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
135 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
136 case ByteCodeInstruction::kDivideS: printf("divides"); break;
137 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
138 case ByteCodeInstruction::kDup: printf("dup"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400139 case ByteCodeInstruction::kDupDown: printf("dupdown %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
141 case ByteCodeInstruction::kLoad: printf("load"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400142 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400143 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400144 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145 printf("loadswizzle %d", count);
146 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400147 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400148 }
149 break;
150 }
Brian Osmanb7451292019-05-15 13:02:13 -0400151 case ByteCodeInstruction::kLoadSwizzleGlobal: {
152 int count = READ8();
153 printf("loadswizzleglobal %d", count);
154 for (int i = 0; i < count; ++i) {
155 printf(", %d", READ8());
156 }
157 break;
158 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
160 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
161 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
162 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
163 case ByteCodeInstruction::kNegateS: printf("negates"); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400164 case ByteCodeInstruction::kNop1: printf("nop1"); break;
165 case ByteCodeInstruction::kNop2: printf("nop2"); break;
166 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 case ByteCodeInstruction::kNot: printf("not"); break;
168 case ByteCodeInstruction::kOrB: printf("orb"); break;
169 case ByteCodeInstruction::kOrI: printf("ori"); break;
170 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400171 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400172 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400173 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400175 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400176 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
177 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400178 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400179 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
180 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400181 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400182 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400183 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184 printf("storeswizzle %d", count);
185 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400186 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187 }
188 break;
189 }
190 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
191 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
192 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400193 printf("swizzle %d, ", READ8());
194 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400195 printf("%d", count);
196 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400197 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400198 }
199 break;
200 }
201 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400202 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400203 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204 }
205 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400206 }
207}
208
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209#define BINARY_OP(inst, type, field, op) \
210 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400211 type b = POP().field; \
212 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400213 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400214 break; \
215 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400216
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400217static constexpr int VECTOR_MAX = 16;
218
219#define VECTOR_BINARY_OP(inst, type, field, op) \
220 case ByteCodeInstruction::inst: { \
221 Value result[VECTOR_MAX]; \
222 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400223 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400224 } \
225 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400226 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400227 } \
228 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400229 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400230 } \
231 break; \
232 }
233
Brian Osman226668a2019-05-14 16:47:30 -0400234struct StackFrame {
235 const uint8_t* fCode;
236 const uint8_t* fIP;
237 Interpreter::Value* fStack;
238};
239
240void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
241 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400242 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400243 memcpy(stack, args, f.fParameterCount * sizeof(Value));
244 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
245 std::vector<StackFrame> frames;
246
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400247 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400248 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400249#ifdef TRACE
250 printf("at %d\n", (int) (ip - fCurrentFunction->fCode.data() - 1));
251#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400252 switch (inst) {
253 BINARY_OP(kAddI, int32_t, fSigned, +)
254 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400255 case ByteCodeInstruction::kBranch: {
256 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400257 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400258 }
Brian Osman226668a2019-05-14 16:47:30 -0400259 case ByteCodeInstruction::kCall: {
260 // Precursor code has pushed all parameters to the stack. Update our bottom of
261 // stack to point at the first parameter, and our sp to point past those parameters
262 // (plus space for locals).
263 int target = READ8();
264 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
265 frames.push_back({ code, ip, stack });
266 ip = code = fun->fCode.data();
267 stack = sp - fun->fParameterCount + 1;
268 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
269 break;
270 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400271 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
272 BINARY_OP(kCompareFEQ, float, fFloat, ==)
273 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
274 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
275 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
276 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
277 BINARY_OP(kCompareFGT, float, fFloat, >)
278 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
279 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
280 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
281 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
282 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
283 BINARY_OP(kCompareFLT, float, fFloat, <)
284 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
285 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
286 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
287 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400288 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400289 if (POP().fBool) {
290 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400291 }
292 break;
293 }
294 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400295 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400296 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
297 break;
298 }
299 BINARY_OP(kDivideS, int32_t, fSigned, /)
300 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
301 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400302 case ByteCodeInstruction::kDup: {
303 Value& top = TOP();
304 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400305 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400306 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400307 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400308 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400309 // before dupdown 4: X A B C D
310 // after dupdown 4: A B C D X A B C D
311 memmove(sp, sp - count, sizeof(Value) * (count + 1));
312 sp += count;
313 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400314 break;
315 }
316 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400317 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400318 top.fSigned = (int) top.fFloat;
319 break;
320 }
321 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400322 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400323 top.fFloat = (float) top.fSigned;
324 break;
325 }
326 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400327 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400328 top.fFloat = (float) top.fUnsigned;
329 break;
330 }
331 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400332 int target = POP().fSigned;
333 SkASSERT(target < STACK_SIZE());
334 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400335 break;
336 }
337 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400338 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400339 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400340 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400341 break;
342 }
343 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400344 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400345 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400346 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400347 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400348 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400349 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400350 break;
351 }
Brian Osmanb7451292019-05-15 13:02:13 -0400352 case ByteCodeInstruction::kLoadSwizzleGlobal: {
353 int target = READ8();
354 SkASSERT(target < (int) fGlobals.size());
355 int count = READ8();
356 for (int i = 0; i < count; ++i) {
357 PUSH(fGlobals[target + *(ip + i)]);
358 }
359 ip += count;
360 break;
361 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400362 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
363 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
364 BINARY_OP(kMultiplyF, float, fFloat, *)
365 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400366 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400367 top.fBool = !top.fBool;
368 break;
369 }
370 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400371 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400372 top.fFloat = -top.fFloat;
373 break;
374 }
375 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400376 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400377 top.fSigned = -top.fSigned;
378 break;
379 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400380 case ByteCodeInstruction::kNop1:
381 continue;
382 case ByteCodeInstruction::kNop2:
383 ++ip;
384 continue;
385 case ByteCodeInstruction::kNop3:
386 ip += 2;
387 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400388 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400389 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400390 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400391 }
392 break;
393 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400394 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400395 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400396 case ByteCodeInstruction::kRemainderF: {
397 float b = POP().fFloat;
398 Value* a = &TOP();
399 *a = Value(fmodf(a->fFloat, b));
400 break;
401 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400402 BINARY_OP(kRemainderS, int32_t, fSigned, %)
403 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
404 case ByteCodeInstruction::kReturn: {
Brian Osman226668a2019-05-14 16:47:30 -0400405 int count = READ8();
406 if (frames.empty()) {
407 if (outReturn) {
408 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
409 }
410 return;
411 } else {
412 // When we were called, 'stack' was positioned at the old top-of-stack (where
413 // our parameters were placed). So copy our return values to that same spot.
414 memmove(stack, sp - count + 1, count * sizeof(Value));
415
416 // Now move the stack pointer to the end of the just-pushed return values,
417 // and restore everything else.
418 const StackFrame& frame(frames.back());
419 sp = stack + count - 1;
420 stack = frame.fStack;
421 code = frame.fCode;
422 ip = frame.fIP;
423 frames.pop_back();
424 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400425 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400426 }
427 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400428 Value value = POP();
429 int target = POP().fSigned;
430 SkASSERT(target < STACK_SIZE());
431 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400432 break;
433 }
434 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400435 Value value = POP();
436 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400437 SkASSERT(target < (int) fGlobals.size());
438 fGlobals[target] = value;
439 break;
440 }
441 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400442 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400443 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400444 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400445 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400446 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400447 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400448 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400449 break;
450 }
451 BINARY_OP(kSubtractI, int32_t, fSigned, -)
452 BINARY_OP(kSubtractF, float, fFloat, -)
453 case ByteCodeInstruction::kSwizzle: {
454 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400455 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400456 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400457 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400458 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400459 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400460 }
461 break;
462 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400463 case ByteCodeInstruction::kVector: {
464 uint8_t count = READ8();
465 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
466 switch (inst) {
467 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
468 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400469 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
470 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
471 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
472 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
473 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
474 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
475 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
476 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
477 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
478 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
479 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
480 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
481 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
482 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
483 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
484 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400485 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
486 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
487 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
488 case ByteCodeInstruction::kFloatToInt: {
489 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400490 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400491 v.fSigned = (int) v.fFloat;
492 }
493 break;
494 }
495 case ByteCodeInstruction::kSignedToFloat: {
496 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400497 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400498 v.fFloat = (float) v.fSigned;
499 }
500 break;
501 }
502 case ByteCodeInstruction::kUnsignedToFloat: {
503 for (int i = 0; i < count; ++i) {
Brian Osman41672152019-05-14 13:37:30 -0400504 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400505 v.fFloat = (float) v.fUnsigned;
506 }
507 break;
508 }
509 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400510 int src = POP().fSigned;
511 memcpy(sp + 1, &stack[src], count * sizeof(Value));
512 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400513 break;
514 }
515 case ByteCodeInstruction::kLoadGlobal: {
516 int target = READ8();
517 SkASSERT(target < (int) fGlobals.size());
Brian Osmanb7451292019-05-15 13:02:13 -0400518 memcpy(sp + 1, &fGlobals[target], count * sizeof(Value));
519 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400520 break;
521 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400522 case ByteCodeInstruction::kNegateS: {
523 for (int i = 0; i < count; ++i) {
524 Value& v = sp[-i];
525 v.fSigned = -v.fSigned;
526 }
527 break;
528 }
529 case ByteCodeInstruction::kNegateF: {
530 for (int i = 0; i < count; ++i) {
531 Value& v = sp[-i];
532 v.fFloat = -v.fFloat;
533 }
534 break;
535 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400536 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
537 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
538 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400539 case ByteCodeInstruction::kRemainderF: {
540 Value result[VECTOR_MAX];
541 for (int i = count - 1; i >= 0; --i) {
542 result[i] = POP();
543 }
544 for (int i = count - 1; i >= 0; --i) {
545 result[i] = fmodf(POP().fFloat, result[i].fFloat);
546 }
547 for (int i = 0; i < count; ++i) {
548 PUSH(result[i]);
549 }
550 break;
551 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400552 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
553 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
554 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400555 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
556 count * sizeof(Value));
557 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400558 break;
559 }
Brian Osmanb7451292019-05-15 13:02:13 -0400560 case ByteCodeInstruction::kStoreGlobal: {
561 int target = (sp - count)->fSigned;
562 SkASSERT(target < (int)fGlobals.size());
563 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
564 sp -= count;
565 break;
566 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400567 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
568 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
569 default:
570 printf("unsupported instruction %d\n", (int) inst);
571 SkASSERT(false);
572 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400573 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400574 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400575 default:
576 printf("unsupported instruction %d\n", (int) inst);
577 SkASSERT(false);
578 }
579#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400580 printf("STACK:");
581 for (int i = 0; i < STACK_SIZE(); ++i) {
582 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
583 }
584 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400585#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400586 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400587}
588
589} // namespace
590
591#endif