blob: 1d9d5931c82175113cfa536402fb2d9f5e6b9028 [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 }
39 for (int i = fByteCode->fInputSlots.size() - 1; i >= 0; --i) {
40 fGlobals[fByteCode->fInputSlots[i]] = inputs[i];
41 }
42}
43
44void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
45 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040046 fCurrentFunction = &f;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040047#ifdef TRACE
48 this->disassemble(f);
49#endif
Ethan Nicholasdfcad062019-05-07 12:53:34 -040050 Value smallStack[128];
51 std::unique_ptr<Value[]> largeStack;
52 Value* stack = smallStack;
53 if ((int) SK_ARRAY_COUNT(smallStack) < fCurrentFunction->fStackCount) {
54 largeStack.reset(new Value[fCurrentFunction->fStackCount]);
55 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040056 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -040057 run(stack, args, outReturn);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040058 int offset = 0;
59 for (const auto& p : f.fDeclaration.fParameters) {
60 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
61 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040062 args[offset] = stack[offset];
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040063 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040064 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040065 } else {
66 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040067 }
68 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040069}
70
Mike Kleinb11ab572018-10-24 06:42:14 -040071struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040072 Interpreter* fInterpreter;
73 const FunctionDefinition* fFunction;
74};
75
Ethan Nicholasdfcad062019-05-07 12:53:34 -040076#define STACK_SIZE() (int) (sp - stack + 1)
77
78#define TOP() (*sp)
79
80#define POP() (*(sp--))
81
82#define PUSH(v) (*(++sp) = v)
83
84#define READ8() (*(ip++))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040085
Ethan Nicholas7e603db2019-05-03 12:57:47 -040086#define READ16() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040087 (SkASSERT((intptr_t) ip % 2 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040088 ip += 2, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040089 *(uint16_t*) (ip - 2))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040090
Ethan Nicholas7e603db2019-05-03 12:57:47 -040091#define READ32() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040092 (SkASSERT((intptr_t) ip % 4 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040093 ip += 4, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040094 *(uint32_t*) (ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040095
96static String value_string(uint32_t v) {
97 union { uint32_t u; float f; } pun = { v };
98 return to_string(v) + "(" + to_string(pun.f) + ")";
99}
100
101void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400102 const uint8_t* ip = f.fCode.data();
103 while (ip < f.fCode.data() + f.fCode.size()) {
104 printf("%d: ", (int) (ip - f.fCode.data()));
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400105 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400106 case ByteCodeInstruction::kAddF: printf("addf"); break;
107 case ByteCodeInstruction::kAddI: printf("addi"); break;
108 case ByteCodeInstruction::kAndB: printf("andb"); break;
109 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400110 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400111 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
112 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
113 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
114 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
115 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
116 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
117 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
118 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
119 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
120 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
121 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
122 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
123 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
124 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
125 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
126 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
127 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400128 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400129 break;
130 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
131 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
132 case ByteCodeInstruction::kDivideS: printf("divides"); break;
133 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
134 case ByteCodeInstruction::kDup: printf("dup"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400135 case ByteCodeInstruction::kDupDown: printf("dupdown %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400136 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
137 case ByteCodeInstruction::kLoad: printf("load"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400138 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400139 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400140 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400141 printf("loadswizzle %d", count);
142 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400143 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400144 }
145 break;
146 }
147 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
148 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
149 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
150 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
151 case ByteCodeInstruction::kNegateS: printf("negates"); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400152 case ByteCodeInstruction::kNop1: printf("nop1"); break;
153 case ByteCodeInstruction::kNop2: printf("nop2"); break;
154 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400155 case ByteCodeInstruction::kNot: printf("not"); break;
156 case ByteCodeInstruction::kOrB: printf("orb"); break;
157 case ByteCodeInstruction::kOrI: printf("ori"); break;
158 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400159 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400161 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 break;
163 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
164 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400165 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
167 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400168 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400169 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400170 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 printf("storeswizzle %d", count);
172 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400173 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 }
175 break;
176 }
177 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
178 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
179 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400180 printf("swizzle %d, ", READ8());
181 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400182 printf("%d", count);
183 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400184 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400185 }
186 break;
187 }
188 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400189 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400190 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400191 }
192 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400193 }
194}
195
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196#define BINARY_OP(inst, type, field, op) \
197 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400198 type b = POP().field; \
199 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400200 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201 break; \
202 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400203
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204static constexpr int VECTOR_MAX = 16;
205
206#define VECTOR_BINARY_OP(inst, type, field, op) \
207 case ByteCodeInstruction::inst: { \
208 Value result[VECTOR_MAX]; \
209 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400210 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400211 } \
212 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400213 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400214 } \
215 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400216 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400217 } \
218 break; \
219 }
220
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400221void Interpreter::run(Value* stack, Value args[], Value* outReturn) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400222 const uint8_t* code = fCurrentFunction->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400223 const uint8_t* ip = code;
224 memcpy(stack, args, fCurrentFunction->fParameterCount * sizeof(Value));
225 Value* sp = stack + fCurrentFunction->fParameterCount + fCurrentFunction->fLocalCount - 1;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400226 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400227 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400228#ifdef TRACE
229 printf("at %d\n", (int) (ip - fCurrentFunction->fCode.data() - 1));
230#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400231 switch (inst) {
232 BINARY_OP(kAddI, int32_t, fSigned, +)
233 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400234 case ByteCodeInstruction::kBranch: {
235 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400236 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400237 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400238 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
239 BINARY_OP(kCompareFEQ, float, fFloat, ==)
240 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
241 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
242 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
243 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
244 BINARY_OP(kCompareFGT, float, fFloat, >)
245 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
246 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
247 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
248 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
249 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
250 BINARY_OP(kCompareFLT, float, fFloat, <)
251 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
252 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
253 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
254 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400255 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400256 if (POP().fBool) {
257 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400258 }
259 break;
260 }
261 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400262 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400263 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
264 break;
265 }
266 BINARY_OP(kDivideS, int32_t, fSigned, /)
267 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
268 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400269 case ByteCodeInstruction::kDup: {
270 Value& top = TOP();
271 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400272 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400273 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400274 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400275 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400276 // before dupdown 4: X A B C D
277 // after dupdown 4: A B C D X A B C D
278 memmove(sp, sp - count, sizeof(Value) * (count + 1));
279 sp += count;
280 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400281 break;
282 }
283 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400284 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400285 top.fSigned = (int) top.fFloat;
286 break;
287 }
288 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400289 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400290 top.fFloat = (float) top.fSigned;
291 break;
292 }
293 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400294 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400295 top.fFloat = (float) top.fUnsigned;
296 break;
297 }
298 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400299 int target = POP().fSigned;
300 SkASSERT(target < STACK_SIZE());
301 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400302 break;
303 }
304 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400305 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400306 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400307 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400308 break;
309 }
310 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400311 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400312 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400313 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400314 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400315 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400316 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400317 break;
318 }
319 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
320 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
321 BINARY_OP(kMultiplyF, float, fFloat, *)
322 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400323 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400324 top.fBool = !top.fBool;
325 break;
326 }
327 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400328 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400329 top.fFloat = -top.fFloat;
330 break;
331 }
332 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400333 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400334 top.fSigned = -top.fSigned;
335 break;
336 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400337 case ByteCodeInstruction::kNop1:
338 continue;
339 case ByteCodeInstruction::kNop2:
340 ++ip;
341 continue;
342 case ByteCodeInstruction::kNop3:
343 ip += 2;
344 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400345 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400346 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400347 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400348 }
349 break;
350 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400351 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400352 break;
353 BINARY_OP(kRemainderS, int32_t, fSigned, %)
354 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
355 case ByteCodeInstruction::kReturn: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400356 if (outReturn) {
357 int count = READ8();
358 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400359 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400360 return;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400361 }
362 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400363 Value value = POP();
364 int target = POP().fSigned;
365 SkASSERT(target < STACK_SIZE());
366 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400367 break;
368 }
369 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400370 Value value = POP();
371 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400372 SkASSERT(target < (int) fGlobals.size());
373 fGlobals[target] = value;
374 break;
375 }
376 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400377 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400378 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400379 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400380 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400381 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400382 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400383 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400384 break;
385 }
386 BINARY_OP(kSubtractI, int32_t, fSigned, -)
387 BINARY_OP(kSubtractF, float, fFloat, -)
388 case ByteCodeInstruction::kSwizzle: {
389 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400390 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400391 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400392 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400393 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400394 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400395 }
396 break;
397 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400398 case ByteCodeInstruction::kVector: {
399 uint8_t count = READ8();
400 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
401 switch (inst) {
402 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
403 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400404 case ByteCodeInstruction::kBranch: {
405 ip = code + READ16();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400406 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400407 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400408 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
409 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
410 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
411 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
412 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
413 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
414 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
415 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
416 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
417 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
418 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
419 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
420 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
421 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
422 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
423 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
424 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400425 uint16_t target = READ16();
426 if (POP().fBool) {
427 ip = code + target;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400428 }
429 break;
430 }
431 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
432 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
433 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
434 case ByteCodeInstruction::kFloatToInt: {
435 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400436 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400437 v.fSigned = (int) v.fFloat;
438 }
439 break;
440 }
441 case ByteCodeInstruction::kSignedToFloat: {
442 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400443 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400444 v.fFloat = (float) v.fSigned;
445 }
446 break;
447 }
448 case ByteCodeInstruction::kUnsignedToFloat: {
449 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400450 Value& v = stack[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400451 v.fFloat = (float) v.fUnsigned;
452 }
453 break;
454 }
455 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400456 int src = POP().fSigned;
457 memcpy(sp + 1, &stack[src], count * sizeof(Value));
458 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400459 break;
460 }
461 case ByteCodeInstruction::kLoadGlobal: {
462 int target = READ8();
463 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400464 PUSH(fGlobals[target]);
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400465 break;
466 }
467 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
468 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
469 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
470 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
471 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
472 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400473 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
474 count * sizeof(Value));
475 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400476 break;
477 }
478 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
479 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
480 default:
481 printf("unsupported instruction %d\n", (int) inst);
482 SkASSERT(false);
483 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400484 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400485 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400486 default:
487 printf("unsupported instruction %d\n", (int) inst);
488 SkASSERT(false);
489 }
490#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400491 printf("STACK:");
492 for (int i = 0; i < STACK_SIZE(); ++i) {
493 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
494 }
495 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400496#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400497 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400498}
499
500} // namespace
501
502#endif