blob: 01abdf2ce9cbf26e786d993c9e66af62df6c2d84 [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 }
151 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
152 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
153 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
154 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
155 case ByteCodeInstruction::kNegateS: printf("negates"); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400156 case ByteCodeInstruction::kNop1: printf("nop1"); break;
157 case ByteCodeInstruction::kNop2: printf("nop2"); break;
158 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 case ByteCodeInstruction::kNot: printf("not"); break;
160 case ByteCodeInstruction::kOrB: printf("orb"); break;
161 case ByteCodeInstruction::kOrI: printf("ori"); break;
162 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400163 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400165 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400167 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
169 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400170 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
172 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400173 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400175 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400176 printf("storeswizzle %d", count);
177 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400178 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400179 }
180 break;
181 }
182 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
183 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
184 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400185 printf("swizzle %d, ", READ8());
186 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187 printf("%d", count);
188 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400189 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190 }
191 break;
192 }
193 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400194 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400195 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196 }
197 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400198 }
199}
200
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201#define BINARY_OP(inst, type, field, op) \
202 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400203 type b = POP().field; \
204 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400205 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 break; \
207 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400208
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209static constexpr int VECTOR_MAX = 16;
210
211#define VECTOR_BINARY_OP(inst, type, field, op) \
212 case ByteCodeInstruction::inst: { \
213 Value result[VECTOR_MAX]; \
214 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400215 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216 } \
217 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400218 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400219 } \
220 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400221 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400222 } \
223 break; \
224 }
225
Brian Osman226668a2019-05-14 16:47:30 -0400226struct StackFrame {
227 const uint8_t* fCode;
228 const uint8_t* fIP;
229 Interpreter::Value* fStack;
230};
231
232void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
233 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400234 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400235 memcpy(stack, args, f.fParameterCount * sizeof(Value));
236 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
237 std::vector<StackFrame> frames;
238
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400239 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400240 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400241#ifdef TRACE
242 printf("at %d\n", (int) (ip - fCurrentFunction->fCode.data() - 1));
243#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400244 switch (inst) {
245 BINARY_OP(kAddI, int32_t, fSigned, +)
246 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400247 case ByteCodeInstruction::kBranch: {
248 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400249 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400250 }
Brian Osman226668a2019-05-14 16:47:30 -0400251 case ByteCodeInstruction::kCall: {
252 // Precursor code has pushed all parameters to the stack. Update our bottom of
253 // stack to point at the first parameter, and our sp to point past those parameters
254 // (plus space for locals).
255 int target = READ8();
256 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
257 frames.push_back({ code, ip, stack });
258 ip = code = fun->fCode.data();
259 stack = sp - fun->fParameterCount + 1;
260 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
261 break;
262 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400263 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
264 BINARY_OP(kCompareFEQ, float, fFloat, ==)
265 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
266 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
267 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
268 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
269 BINARY_OP(kCompareFGT, float, fFloat, >)
270 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
271 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
272 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
273 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
274 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
275 BINARY_OP(kCompareFLT, float, fFloat, <)
276 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
277 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
278 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
279 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400280 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400281 if (POP().fBool) {
282 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400283 }
284 break;
285 }
286 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400287 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400288 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
289 break;
290 }
291 BINARY_OP(kDivideS, int32_t, fSigned, /)
292 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
293 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400294 case ByteCodeInstruction::kDup: {
295 Value& top = TOP();
296 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400297 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400298 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400299 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400300 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400301 // before dupdown 4: X A B C D
302 // after dupdown 4: A B C D X A B C D
303 memmove(sp, sp - count, sizeof(Value) * (count + 1));
304 sp += count;
305 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400306 break;
307 }
308 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400309 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400310 top.fSigned = (int) top.fFloat;
311 break;
312 }
313 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400314 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400315 top.fFloat = (float) top.fSigned;
316 break;
317 }
318 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400319 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400320 top.fFloat = (float) top.fUnsigned;
321 break;
322 }
323 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400324 int target = POP().fSigned;
325 SkASSERT(target < STACK_SIZE());
326 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400327 break;
328 }
329 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400330 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400331 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400332 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400333 break;
334 }
335 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400336 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400337 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400338 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400339 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400340 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400341 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400342 break;
343 }
344 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
345 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
346 BINARY_OP(kMultiplyF, float, fFloat, *)
347 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400348 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400349 top.fBool = !top.fBool;
350 break;
351 }
352 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400353 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400354 top.fFloat = -top.fFloat;
355 break;
356 }
357 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400358 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400359 top.fSigned = -top.fSigned;
360 break;
361 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400362 case ByteCodeInstruction::kNop1:
363 continue;
364 case ByteCodeInstruction::kNop2:
365 ++ip;
366 continue;
367 case ByteCodeInstruction::kNop3:
368 ip += 2;
369 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400370 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400371 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400372 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400373 }
374 break;
375 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400376 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400377 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400378 case ByteCodeInstruction::kRemainderF: {
379 float b = POP().fFloat;
380 Value* a = &TOP();
381 *a = Value(fmodf(a->fFloat, b));
382 break;
383 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400384 BINARY_OP(kRemainderS, int32_t, fSigned, %)
385 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
386 case ByteCodeInstruction::kReturn: {
Brian Osman226668a2019-05-14 16:47:30 -0400387 int count = READ8();
388 if (frames.empty()) {
389 if (outReturn) {
390 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
391 }
392 return;
393 } else {
394 // When we were called, 'stack' was positioned at the old top-of-stack (where
395 // our parameters were placed). So copy our return values to that same spot.
396 memmove(stack, sp - count + 1, count * sizeof(Value));
397
398 // Now move the stack pointer to the end of the just-pushed return values,
399 // and restore everything else.
400 const StackFrame& frame(frames.back());
401 sp = stack + count - 1;
402 stack = frame.fStack;
403 code = frame.fCode;
404 ip = frame.fIP;
405 frames.pop_back();
406 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400407 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400408 }
409 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400410 Value value = POP();
411 int target = POP().fSigned;
412 SkASSERT(target < STACK_SIZE());
413 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400414 break;
415 }
416 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400417 Value value = POP();
418 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400419 SkASSERT(target < (int) fGlobals.size());
420 fGlobals[target] = value;
421 break;
422 }
423 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400424 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400425 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400426 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400427 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400428 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400429 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400430 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400431 break;
432 }
433 BINARY_OP(kSubtractI, int32_t, fSigned, -)
434 BINARY_OP(kSubtractF, float, fFloat, -)
435 case ByteCodeInstruction::kSwizzle: {
436 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400437 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400438 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400439 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400440 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400441 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400442 }
443 break;
444 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400445 case ByteCodeInstruction::kVector: {
446 uint8_t count = READ8();
447 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
448 switch (inst) {
449 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
450 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400451 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
452 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
453 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
454 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
455 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
456 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
457 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
458 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
459 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
460 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
461 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
462 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
463 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
464 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
465 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
466 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400467 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
468 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
469 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
470 case ByteCodeInstruction::kFloatToInt: {
471 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400472 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400473 v.fSigned = (int) v.fFloat;
474 }
475 break;
476 }
477 case ByteCodeInstruction::kSignedToFloat: {
478 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400479 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400480 v.fFloat = (float) v.fSigned;
481 }
482 break;
483 }
484 case ByteCodeInstruction::kUnsignedToFloat: {
485 for (int i = 0; i < count; ++i) {
Brian Osman41672152019-05-14 13:37:30 -0400486 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400487 v.fFloat = (float) v.fUnsigned;
488 }
489 break;
490 }
491 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400492 int src = POP().fSigned;
493 memcpy(sp + 1, &stack[src], count * sizeof(Value));
494 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400495 break;
496 }
497 case ByteCodeInstruction::kLoadGlobal: {
498 int target = READ8();
499 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400500 PUSH(fGlobals[target]);
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400501 break;
502 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400503 case ByteCodeInstruction::kNegateS: {
504 for (int i = 0; i < count; ++i) {
505 Value& v = sp[-i];
506 v.fSigned = -v.fSigned;
507 }
508 break;
509 }
510 case ByteCodeInstruction::kNegateF: {
511 for (int i = 0; i < count; ++i) {
512 Value& v = sp[-i];
513 v.fFloat = -v.fFloat;
514 }
515 break;
516 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400517 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
518 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
519 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400520 case ByteCodeInstruction::kRemainderF: {
521 Value result[VECTOR_MAX];
522 for (int i = count - 1; i >= 0; --i) {
523 result[i] = POP();
524 }
525 for (int i = count - 1; i >= 0; --i) {
526 result[i] = fmodf(POP().fFloat, result[i].fFloat);
527 }
528 for (int i = 0; i < count; ++i) {
529 PUSH(result[i]);
530 }
531 break;
532 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400533 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
534 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
535 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400536 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
537 count * sizeof(Value));
538 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400539 break;
540 }
541 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
542 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
543 default:
544 printf("unsupported instruction %d\n", (int) inst);
545 SkASSERT(false);
546 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400547 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400548 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400549 default:
550 printf("unsupported instruction %d\n", (int) inst);
551 SkASSERT(false);
552 }
553#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400554 printf("STACK:");
555 for (int i = 0; i < STACK_SIZE(); ++i) {
556 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
557 }
558 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400559#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400560 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400561}
562
563} // namespace
564
565#endif