blob: 5fb52f8c2c313d9b0eec4708078bcc795de05c4d [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
Ethan Nicholasdfcad062019-05-07 12:53:34 -040033Interpreter::Interpreter(std::unique_ptr<Program> program, std::unique_ptr<ByteCode> byteCode,
34 Interpreter::Value inputs[])
35 : fProgram(std::move(program))
36 , 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[]) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040044 for (int i = fByteCode->fInputSlots.size() - 1; i >= 0; --i) {
45 fGlobals[fByteCode->fInputSlots[i]] = inputs[i];
46 }
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 }
Brian Osman226668a2019-05-14 16:47:30 -040061 run(f, stack, args, outReturn);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040062 int offset = 0;
63 for (const auto& p : f.fDeclaration.fParameters) {
64 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
65 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040066 args[offset] = stack[offset];
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040067 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040068 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040069 } 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
Mike Kleinb11ab572018-10-24 06:42:14 -040075struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040076 Interpreter* fInterpreter;
77 const FunctionDefinition* fFunction;
78};
79
Ethan Nicholasdfcad062019-05-07 12:53:34 -040080#define STACK_SIZE() (int) (sp - stack + 1)
81
Ethan Nicholas91164d12019-05-15 15:29:54 -040082#define TOP() (SkASSERT(sp >= stack), *sp)
Ethan Nicholasdfcad062019-05-07 12:53:34 -040083
Ethan Nicholas91164d12019-05-15 15:29:54 -040084#define POP() (SkASSERT(sp >= stack), *(sp--))
Ethan Nicholasdfcad062019-05-07 12:53:34 -040085
Ethan Nicholas91164d12019-05-15 15:29:54 -040086#define PUSH(v) (SkASSERT(sp + 1 >= stack), *(++sp) = v)
Ethan Nicholasdfcad062019-05-07 12:53:34 -040087
88#define READ8() (*(ip++))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040089
Ethan Nicholas7e603db2019-05-03 12:57:47 -040090#define READ16() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040091 (SkASSERT((intptr_t) ip % 2 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040092 ip += 2, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040093 *(uint16_t*) (ip - 2))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094
Ethan Nicholas7e603db2019-05-03 12:57:47 -040095#define READ32() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040096 (SkASSERT((intptr_t) ip % 4 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040097 ip += 4, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040098 *(uint32_t*) (ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040099
100static 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
105void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400106 const uint8_t* ip = f.fCode.data();
107 while (ip < f.fCode.data() + f.fCode.size()) {
108 printf("%d: ", (int) (ip - f.fCode.data()));
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400109 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400110 case ByteCodeInstruction::kAddF: printf("addf"); break;
111 case ByteCodeInstruction::kAddI: printf("addi"); break;
112 case ByteCodeInstruction::kAndB: printf("andb"); break;
113 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400114 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Brian Osman226668a2019-05-14 16:47:30 -0400115 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400116 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
117 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
118 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
119 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
120 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
121 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
122 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
123 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
124 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
125 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
126 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
127 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
128 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
129 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
130 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
131 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
132 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400133 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400134 break;
135 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
136 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
137 case ByteCodeInstruction::kDivideS: printf("divides"); break;
138 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
139 case ByteCodeInstruction::kDup: printf("dup"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400140 case ByteCodeInstruction::kDupDown: printf("dupdown %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400141 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
142 case ByteCodeInstruction::kLoad: printf("load"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400143 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400144 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400145 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400146 printf("loadswizzle %d", count);
147 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400148 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400149 }
150 break;
151 }
Brian Osmanb7451292019-05-15 13:02:13 -0400152 case ByteCodeInstruction::kLoadSwizzleGlobal: {
153 int count = READ8();
154 printf("loadswizzleglobal %d", count);
155 for (int i = 0; i < count; ++i) {
156 printf(", %d", READ8());
157 }
158 break;
159 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400161 case ByteCodeInstruction::kMultiplyI: printf("multiplyi"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 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;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400175 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400176 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400177 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
178 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400179 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400180 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
181 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400182 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400184 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400185 printf("storeswizzle %d", count);
186 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400187 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188 }
189 break;
190 }
191 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
192 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
193 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400194 printf("swizzle %d, ", READ8());
195 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196 printf("%d", count);
197 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400198 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400199 }
200 break;
201 }
202 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400203 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400204 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400205 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 }
207 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400208 }
209}
210
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400211#define BINARY_OP(inst, type, field, op) \
212 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400213 type b = POP().field; \
214 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400215 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216 break; \
217 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400218
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400219static constexpr int VECTOR_MAX = 16;
220
221#define VECTOR_BINARY_OP(inst, type, field, op) \
222 case ByteCodeInstruction::inst: { \
223 Value result[VECTOR_MAX]; \
224 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400225 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400226 } \
227 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400228 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400229 } \
230 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400231 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400232 } \
233 break; \
234 }
235
Brian Osman226668a2019-05-14 16:47:30 -0400236struct StackFrame {
237 const uint8_t* fCode;
238 const uint8_t* fIP;
239 Interpreter::Value* fStack;
240};
241
242void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
243 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400244 const uint8_t* ip = code;
Ethan Nicholasf9ef1b82019-05-15 16:50:20 -0400245 if (f.fParameterCount) {
246 memcpy(stack, args, f.fParameterCount * sizeof(Value));
247 }
Brian Osman226668a2019-05-14 16:47:30 -0400248 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
249 std::vector<StackFrame> frames;
250
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400251 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400252 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400253#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400254 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400255#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400256 switch (inst) {
257 BINARY_OP(kAddI, int32_t, fSigned, +)
258 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400259 case ByteCodeInstruction::kBranch: {
260 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400261 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400262 }
Brian Osman226668a2019-05-14 16:47:30 -0400263 case ByteCodeInstruction::kCall: {
264 // Precursor code has pushed all parameters to the stack. Update our bottom of
265 // stack to point at the first parameter, and our sp to point past those parameters
266 // (plus space for locals).
267 int target = READ8();
268 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
269 frames.push_back({ code, ip, stack });
270 ip = code = fun->fCode.data();
271 stack = sp - fun->fParameterCount + 1;
272 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
273 break;
274 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400275 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
276 BINARY_OP(kCompareFEQ, float, fFloat, ==)
277 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
278 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
279 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
280 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
281 BINARY_OP(kCompareFGT, float, fFloat, >)
282 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
283 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
284 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
285 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
286 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
287 BINARY_OP(kCompareFLT, float, fFloat, <)
288 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
289 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
290 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
291 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400292 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400293 if (POP().fBool) {
294 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400295 }
296 break;
297 }
298 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400299 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400300 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
301 break;
302 }
303 BINARY_OP(kDivideS, int32_t, fSigned, /)
304 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
305 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400306 case ByteCodeInstruction::kDup: {
307 Value& top = TOP();
308 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400309 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400310 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400311 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400312 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400313 // before dupdown 4: X A B C D
314 // after dupdown 4: A B C D X A B C D
Ethan Nicholas91164d12019-05-15 15:29:54 -0400315 SkASSERT(sp - count >= stack);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400316 memmove(sp, sp - count, sizeof(Value) * (count + 1));
317 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400318 SkASSERT(sp - count * 2 >= stack);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400319 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400320 break;
321 }
322 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400323 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400324 top.fSigned = (int) top.fFloat;
325 break;
326 }
327 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400328 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400329 top.fFloat = (float) top.fSigned;
330 break;
331 }
332 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400333 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400334 top.fFloat = (float) top.fUnsigned;
335 break;
336 }
337 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400338 int target = POP().fSigned;
339 SkASSERT(target < STACK_SIZE());
340 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400341 break;
342 }
343 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400344 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400345 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400346 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400347 break;
348 }
349 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400350 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400351 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400352 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400353 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400354 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400355 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400356 break;
357 }
Brian Osmanb7451292019-05-15 13:02:13 -0400358 case ByteCodeInstruction::kLoadSwizzleGlobal: {
359 int target = READ8();
360 SkASSERT(target < (int) fGlobals.size());
361 int count = READ8();
362 for (int i = 0; i < count; ++i) {
363 PUSH(fGlobals[target + *(ip + i)]);
364 }
365 ip += count;
366 break;
367 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400368 BINARY_OP(kMultiplyI, int32_t, fSigned, *)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400369 BINARY_OP(kMultiplyF, float, fFloat, *)
370 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400371 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400372 top.fBool = !top.fBool;
373 break;
374 }
375 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400376 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400377 top.fFloat = -top.fFloat;
378 break;
379 }
380 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400381 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400382 top.fSigned = -top.fSigned;
383 break;
384 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400385 case ByteCodeInstruction::kNop1:
386 continue;
387 case ByteCodeInstruction::kNop2:
388 ++ip;
389 continue;
390 case ByteCodeInstruction::kNop3:
391 ip += 2;
392 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400393 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400394 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400395 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400396 }
397 break;
398 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400399 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400400 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400401 case ByteCodeInstruction::kReadExternal: {
402 int target = READ8();
403 ++sp;
404 fByteCode->fExternalValues[target]->read(sp);
405 break;
406 }
Brian Osman3b41baf2019-05-08 09:24:46 -0400407 case ByteCodeInstruction::kRemainderF: {
408 float b = POP().fFloat;
409 Value* a = &TOP();
410 *a = Value(fmodf(a->fFloat, b));
411 break;
412 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400413 BINARY_OP(kRemainderS, int32_t, fSigned, %)
414 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
415 case ByteCodeInstruction::kReturn: {
Brian Osman226668a2019-05-14 16:47:30 -0400416 int count = READ8();
417 if (frames.empty()) {
418 if (outReturn) {
419 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
420 }
421 return;
422 } else {
423 // When we were called, 'stack' was positioned at the old top-of-stack (where
424 // our parameters were placed). So copy our return values to that same spot.
425 memmove(stack, sp - count + 1, count * sizeof(Value));
426
427 // Now move the stack pointer to the end of the just-pushed return values,
428 // and restore everything else.
429 const StackFrame& frame(frames.back());
430 sp = stack + count - 1;
431 stack = frame.fStack;
432 code = frame.fCode;
433 ip = frame.fIP;
434 frames.pop_back();
435 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400436 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400437 }
438 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400439 Value value = POP();
440 int target = POP().fSigned;
441 SkASSERT(target < STACK_SIZE());
442 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400443 break;
444 }
445 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400446 Value value = POP();
447 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400448 SkASSERT(target < (int) fGlobals.size());
449 fGlobals[target] = value;
450 break;
451 }
452 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400453 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400454 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400455 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400456 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400457 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400458 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400459 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400460 break;
461 }
462 BINARY_OP(kSubtractI, int32_t, fSigned, -)
463 BINARY_OP(kSubtractF, float, fFloat, -)
464 case ByteCodeInstruction::kSwizzle: {
465 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400466 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400467 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400468 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400469 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400470 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400471 }
472 break;
473 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400474 case ByteCodeInstruction::kVector: {
475 uint8_t count = READ8();
476 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
477 switch (inst) {
478 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
479 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400480 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
481 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
482 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
483 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
484 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
485 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
486 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
487 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
488 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
489 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
490 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
491 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
492 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
493 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
494 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
495 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400496 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
497 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
498 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholas91164d12019-05-15 15:29:54 -0400499 case ByteCodeInstruction::kDup: {
500 SkASSERT(sp - count + 1 >= stack);
501 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
502 sp += count;
503 break;
504 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400505 case ByteCodeInstruction::kFloatToInt: {
506 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400507 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400508 v.fSigned = (int) v.fFloat;
509 }
510 break;
511 }
512 case ByteCodeInstruction::kSignedToFloat: {
513 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400514 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400515 v.fFloat = (float) v.fSigned;
516 }
517 break;
518 }
519 case ByteCodeInstruction::kUnsignedToFloat: {
520 for (int i = 0; i < count; ++i) {
Brian Osman41672152019-05-14 13:37:30 -0400521 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400522 v.fFloat = (float) v.fUnsigned;
523 }
524 break;
525 }
526 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400527 int src = POP().fSigned;
528 memcpy(sp + 1, &stack[src], count * sizeof(Value));
529 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400530 break;
531 }
532 case ByteCodeInstruction::kLoadGlobal: {
533 int target = READ8();
534 SkASSERT(target < (int) fGlobals.size());
Brian Osmanb7451292019-05-15 13:02:13 -0400535 memcpy(sp + 1, &fGlobals[target], count * sizeof(Value));
536 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400537 break;
538 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400539 case ByteCodeInstruction::kNegateS: {
540 for (int i = 0; i < count; ++i) {
541 Value& v = sp[-i];
542 v.fSigned = -v.fSigned;
543 }
544 break;
545 }
546 case ByteCodeInstruction::kNegateF: {
547 for (int i = 0; i < count; ++i) {
548 Value& v = sp[-i];
549 v.fFloat = -v.fFloat;
550 }
551 break;
552 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400553 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, *)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400554 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400555 case ByteCodeInstruction::kRemainderF: {
556 Value result[VECTOR_MAX];
557 for (int i = count - 1; i >= 0; --i) {
558 result[i] = POP();
559 }
560 for (int i = count - 1; i >= 0; --i) {
561 result[i] = fmodf(POP().fFloat, result[i].fFloat);
562 }
563 for (int i = 0; i < count; ++i) {
564 PUSH(result[i]);
565 }
566 break;
567 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400568 case ByteCodeInstruction::kReadExternal: {
569 int target = READ8();
570 // We read all the values in a single read() call, because the external
571 // value should know how many bytes to transfer. The vector op prefix just
572 // tells the interpreter how many stack slots to allocate.
573 fByteCode->fExternalValues[target]->read(sp + 1);
574 sp += count;
575 break;
576 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400577 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
578 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
579 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400580 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
581 count * sizeof(Value));
582 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400583 break;
584 }
Brian Osmanb7451292019-05-15 13:02:13 -0400585 case ByteCodeInstruction::kStoreGlobal: {
586 int target = (sp - count)->fSigned;
587 SkASSERT(target < (int)fGlobals.size());
588 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
589 sp -= count;
590 break;
591 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400592 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
593 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
Ethan Nicholas91164d12019-05-15 15:29:54 -0400594 case ByteCodeInstruction::kWriteExternal: {
595 int target = READ8();
596 // We write all the values in a single write() call, because the external
597 // value should know how many bytes to transfer. The vector op prefix just
598 // tells the interpreter how many stack slots to deallocate.
599 fByteCode->fExternalValues[target]->write(sp - count + 1);
600 sp -= count;
601 break;
602 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400603 default:
604 printf("unsupported instruction %d\n", (int) inst);
605 SkASSERT(false);
606 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400607 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400608 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400609 case ByteCodeInstruction::kWriteExternal: {
610 int target = READ8();
611 fByteCode->fExternalValues[target]->write(sp);
612 POP();
613 break;
614 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400615 default:
616 printf("unsupported instruction %d\n", (int) inst);
617 SkASSERT(false);
618 }
619#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400620 printf("STACK:");
621 for (int i = 0; i < STACK_SIZE(); ++i) {
622 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
623 }
624 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400625#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400626 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400627}
628
629} // namespace
630
631#endif