blob: f33cf42a50f7b14ce88ceb7de5a0d668e4184c0c [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;
Brian Osman3b41baf2019-05-08 09:24:46 -0400163 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
165 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400166 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
168 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400169 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400171 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400172 printf("storeswizzle %d", count);
173 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400174 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400175 }
176 break;
177 }
178 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
179 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
180 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400181 printf("swizzle %d, ", READ8());
182 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 printf("%d", count);
184 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400185 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400186 }
187 break;
188 }
189 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400190 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400191 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400192 }
193 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400194 }
195}
196
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400197#define BINARY_OP(inst, type, field, op) \
198 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400199 type b = POP().field; \
200 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400201 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400202 break; \
203 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400204
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400205static constexpr int VECTOR_MAX = 16;
206
207#define VECTOR_BINARY_OP(inst, type, field, op) \
208 case ByteCodeInstruction::inst: { \
209 Value result[VECTOR_MAX]; \
210 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400211 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400212 } \
213 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400214 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400215 } \
216 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400217 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400218 } \
219 break; \
220 }
221
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400222void Interpreter::run(Value* stack, Value args[], Value* outReturn) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400223 const uint8_t* code = fCurrentFunction->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400224 const uint8_t* ip = code;
225 memcpy(stack, args, fCurrentFunction->fParameterCount * sizeof(Value));
226 Value* sp = stack + fCurrentFunction->fParameterCount + fCurrentFunction->fLocalCount - 1;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400227 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400228 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400229#ifdef TRACE
230 printf("at %d\n", (int) (ip - fCurrentFunction->fCode.data() - 1));
231#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400232 switch (inst) {
233 BINARY_OP(kAddI, int32_t, fSigned, +)
234 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400235 case ByteCodeInstruction::kBranch: {
236 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400237 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400238 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400239 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
240 BINARY_OP(kCompareFEQ, float, fFloat, ==)
241 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
242 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
243 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
244 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
245 BINARY_OP(kCompareFGT, float, fFloat, >)
246 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
247 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
248 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
249 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
250 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
251 BINARY_OP(kCompareFLT, float, fFloat, <)
252 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
253 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
254 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
255 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400256 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400257 if (POP().fBool) {
258 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400259 }
260 break;
261 }
262 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400263 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400264 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
265 break;
266 }
267 BINARY_OP(kDivideS, int32_t, fSigned, /)
268 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
269 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400270 case ByteCodeInstruction::kDup: {
271 Value& top = TOP();
272 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400273 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400274 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400275 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400276 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400277 // before dupdown 4: X A B C D
278 // after dupdown 4: A B C D X A B C D
279 memmove(sp, sp - count, sizeof(Value) * (count + 1));
280 sp += count;
281 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400282 break;
283 }
284 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400285 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400286 top.fSigned = (int) top.fFloat;
287 break;
288 }
289 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400290 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400291 top.fFloat = (float) top.fSigned;
292 break;
293 }
294 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400295 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400296 top.fFloat = (float) top.fUnsigned;
297 break;
298 }
299 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400300 int target = POP().fSigned;
301 SkASSERT(target < STACK_SIZE());
302 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400303 break;
304 }
305 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400306 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400307 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400308 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400309 break;
310 }
311 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400312 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400313 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400314 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400315 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400316 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400317 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400318 break;
319 }
320 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
321 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
322 BINARY_OP(kMultiplyF, float, fFloat, *)
323 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400324 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400325 top.fBool = !top.fBool;
326 break;
327 }
328 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400329 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400330 top.fFloat = -top.fFloat;
331 break;
332 }
333 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400334 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400335 top.fSigned = -top.fSigned;
336 break;
337 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400338 case ByteCodeInstruction::kNop1:
339 continue;
340 case ByteCodeInstruction::kNop2:
341 ++ip;
342 continue;
343 case ByteCodeInstruction::kNop3:
344 ip += 2;
345 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400346 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400347 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400348 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400349 }
350 break;
351 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400352 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400353 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400354 case ByteCodeInstruction::kRemainderF: {
355 float b = POP().fFloat;
356 Value* a = &TOP();
357 *a = Value(fmodf(a->fFloat, b));
358 break;
359 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400360 BINARY_OP(kRemainderS, int32_t, fSigned, %)
361 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
362 case ByteCodeInstruction::kReturn: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400363 if (outReturn) {
364 int count = READ8();
365 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400366 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400367 return;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400368 }
369 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400370 Value value = POP();
371 int target = POP().fSigned;
372 SkASSERT(target < STACK_SIZE());
373 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400374 break;
375 }
376 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400377 Value value = POP();
378 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400379 SkASSERT(target < (int) fGlobals.size());
380 fGlobals[target] = value;
381 break;
382 }
383 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400384 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400385 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400386 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400387 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400388 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400389 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400390 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400391 break;
392 }
393 BINARY_OP(kSubtractI, int32_t, fSigned, -)
394 BINARY_OP(kSubtractF, float, fFloat, -)
395 case ByteCodeInstruction::kSwizzle: {
396 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400397 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400398 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400399 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400400 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400401 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400402 }
403 break;
404 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400405 case ByteCodeInstruction::kVector: {
406 uint8_t count = READ8();
407 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
408 switch (inst) {
409 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
410 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400411 case ByteCodeInstruction::kBranch: {
412 ip = code + READ16();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400413 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400414 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400415 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
416 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
417 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
418 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
419 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
420 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
421 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
422 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
423 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
424 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
425 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
426 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
427 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
428 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
429 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
430 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
431 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400432 uint16_t target = READ16();
433 if (POP().fBool) {
434 ip = code + target;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400435 }
436 break;
437 }
438 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
439 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
440 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
441 case ByteCodeInstruction::kFloatToInt: {
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.fSigned = (int) v.fFloat;
445 }
446 break;
447 }
448 case ByteCodeInstruction::kSignedToFloat: {
449 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400450 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400451 v.fFloat = (float) v.fSigned;
452 }
453 break;
454 }
455 case ByteCodeInstruction::kUnsignedToFloat: {
456 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400457 Value& v = stack[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400458 v.fFloat = (float) v.fUnsigned;
459 }
460 break;
461 }
462 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400463 int src = POP().fSigned;
464 memcpy(sp + 1, &stack[src], count * sizeof(Value));
465 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400466 break;
467 }
468 case ByteCodeInstruction::kLoadGlobal: {
469 int target = READ8();
470 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400471 PUSH(fGlobals[target]);
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400472 break;
473 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400474 case ByteCodeInstruction::kNegateS: {
475 for (int i = 0; i < count; ++i) {
476 Value& v = sp[-i];
477 v.fSigned = -v.fSigned;
478 }
479 break;
480 }
481 case ByteCodeInstruction::kNegateF: {
482 for (int i = 0; i < count; ++i) {
483 Value& v = sp[-i];
484 v.fFloat = -v.fFloat;
485 }
486 break;
487 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400488 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
489 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
490 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400491 case ByteCodeInstruction::kRemainderF: {
492 Value result[VECTOR_MAX];
493 for (int i = count - 1; i >= 0; --i) {
494 result[i] = POP();
495 }
496 for (int i = count - 1; i >= 0; --i) {
497 result[i] = fmodf(POP().fFloat, result[i].fFloat);
498 }
499 for (int i = 0; i < count; ++i) {
500 PUSH(result[i]);
501 }
502 break;
503 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400504 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
505 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
506 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400507 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
508 count * sizeof(Value));
509 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400510 break;
511 }
512 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
513 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
514 default:
515 printf("unsupported instruction %d\n", (int) inst);
516 SkASSERT(false);
517 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400518 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400519 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400520 default:
521 printf("unsupported instruction %d\n", (int) inst);
522 SkASSERT(false);
523 }
524#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400525 printf("STACK:");
526 for (int i = 0; i < STACK_SIZE(); ++i) {
527 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
528 }
529 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400530#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400531 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400532}
533
534} // namespace
535
536#endif