• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
10 #include "SkSLInterpreter.h"
11 #include "ir/SkSLBinaryExpression.h"
12 #include "ir/SkSLExpressionStatement.h"
13 #include "ir/SkSLForStatement.h"
14 #include "ir/SkSLFunctionCall.h"
15 #include "ir/SkSLFunctionReference.h"
16 #include "ir/SkSLIfStatement.h"
17 #include "ir/SkSLIndexExpression.h"
18 #include "ir/SkSLPostfixExpression.h"
19 #include "ir/SkSLPrefixExpression.h"
20 #include "ir/SkSLProgram.h"
21 #include "ir/SkSLStatement.h"
22 #include "ir/SkSLTernaryExpression.h"
23 #include "ir/SkSLVarDeclarations.h"
24 #include "ir/SkSLVarDeclarationsStatement.h"
25 #include "ir/SkSLVariableReference.h"
26 #include "SkRasterPipeline.h"
27 
28 namespace SkSL {
29 
run()30 void Interpreter::run() {
31     for (const auto& e : *fProgram) {
32         if (ProgramElement::kFunction_Kind == e.fKind) {
33             const FunctionDefinition& f = (const FunctionDefinition&) e;
34             if ("appendStages" == f.fDeclaration.fName) {
35                 this->run(f);
36                 return;
37             }
38         }
39     }
40     SkASSERT(false);
41 }
42 
SizeOf(const Type & type)43 static int SizeOf(const Type& type) {
44     return 1;
45 }
46 
run(const FunctionDefinition & f)47 void Interpreter::run(const FunctionDefinition& f) {
48     fVars.emplace_back();
49     StackIndex current = (StackIndex) fStack.size();
50     for (int i = f.fDeclaration.fParameters.size() - 1; i >= 0; --i) {
51         current -= SizeOf(f.fDeclaration.fParameters[i]->fType);
52         fVars.back()[f.fDeclaration.fParameters[i]] = current;
53     }
54     fCurrentIndex.push_back({ f.fBody.get(), 0 });
55     while (fCurrentIndex.size()) {
56         this->runStatement();
57     }
58 }
59 
push(Value value)60 void Interpreter::push(Value value) {
61     fStack.push_back(value);
62 }
63 
pop()64 Interpreter::Value Interpreter::pop() {
65     auto iter = fStack.end() - 1;
66     Value result = *iter;
67     fStack.erase(iter);
68     return result;
69 }
70 
stackAlloc(int count)71  Interpreter::StackIndex Interpreter::stackAlloc(int count) {
72     int result = fStack.size();
73     for (int i = 0; i < count; ++i) {
74         fStack.push_back(Value((int) 0xDEADBEEF));
75     }
76     return result;
77 }
78 
runStatement()79 void Interpreter::runStatement() {
80     const Statement& stmt = *fCurrentIndex.back().fStatement;
81     const size_t index = fCurrentIndex.back().fIndex;
82     fCurrentIndex.pop_back();
83     switch (stmt.fKind) {
84         case Statement::kBlock_Kind: {
85             const Block& b = (const Block&) stmt;
86             if (!b.fStatements.size()) {
87                 break;
88             }
89             SkASSERT(index < b.fStatements.size());
90             if (index < b.fStatements.size() - 1) {
91                 fCurrentIndex.push_back({ &b, index + 1 });
92             }
93             fCurrentIndex.push_back({ b.fStatements[index].get(), 0 });
94             break;
95         }
96         case Statement::kBreak_Kind:
97             SkASSERT(index == 0);
98             abort();
99         case Statement::kContinue_Kind:
100             SkASSERT(index == 0);
101             abort();
102         case Statement::kDiscard_Kind:
103             SkASSERT(index == 0);
104             abort();
105         case Statement::kDo_Kind:
106             abort();
107         case Statement::kExpression_Kind:
108             SkASSERT(index == 0);
109             this->evaluate(*((const ExpressionStatement&) stmt).fExpression);
110             break;
111         case Statement::kFor_Kind: {
112             ForStatement& f = (ForStatement&) stmt;
113             switch (index) {
114                 case 0:
115                     // initializer
116                     fCurrentIndex.push_back({ &f, 1 });
117                     if (f.fInitializer) {
118                         fCurrentIndex.push_back({ f.fInitializer.get(), 0 });
119                     }
120                     break;
121                 case 1:
122                     // test & body
123                     if (f.fTest && !evaluate(*f.fTest).fBool) {
124                         break;
125                     } else {
126                         fCurrentIndex.push_back({ &f, 2 });
127                         fCurrentIndex.push_back({ f.fStatement.get(), 0 });
128                     }
129                     break;
130                 case 2:
131                     // next
132                     if (f.fNext) {
133                         this->evaluate(*f.fNext);
134                     }
135                     fCurrentIndex.push_back({ &f, 1 });
136                     break;
137                 default:
138                     SkASSERT(false);
139             }
140             break;
141         }
142         case Statement::kGroup_Kind:
143             abort();
144         case Statement::kIf_Kind: {
145             IfStatement& i = (IfStatement&) stmt;
146             if (evaluate(*i.fTest).fBool) {
147                 fCurrentIndex.push_back({ i.fIfTrue.get(), 0 });
148             } else if (i.fIfFalse) {
149                 fCurrentIndex.push_back({ i.fIfFalse.get(), 0 });
150             }
151             break;
152         }
153         case Statement::kNop_Kind:
154             SkASSERT(index == 0);
155             break;
156         case Statement::kReturn_Kind:
157             SkASSERT(index == 0);
158             abort();
159         case Statement::kSwitch_Kind:
160             abort();
161         case Statement::kVarDeclarations_Kind:
162             SkASSERT(index == 0);
163             for (const auto& decl :((const VarDeclarationsStatement&) stmt).fDeclaration->fVars) {
164                 const Variable* var = ((VarDeclaration&) *decl).fVar;
165                 StackIndex pos = this->stackAlloc(SizeOf(var->fType));
166                 fVars.back()[var] = pos;
167                 if (var->fInitialValue) {
168                     fStack[pos] = this->evaluate(*var->fInitialValue);
169                 }
170             }
171             break;
172         case Statement::kWhile_Kind:
173             abort();
174         default:
175             abort();
176     }
177 }
178 
type_kind(const Type & type)179 static Interpreter::TypeKind type_kind(const Type& type) {
180     if (type.fName == "int") {
181         return Interpreter::kInt_TypeKind;
182     } else if (type.fName == "float") {
183         return Interpreter::kFloat_TypeKind;
184     }
185     ABORT("unsupported type: %s\n", type.description().c_str());
186 }
187 
getLValue(const Expression & expr)188 Interpreter::StackIndex Interpreter::getLValue(const Expression& expr) {
189     switch (expr.fKind) {
190         case Expression::kFieldAccess_Kind:
191             break;
192         case Expression::kIndex_Kind: {
193             const IndexExpression& idx = (const IndexExpression&) expr;
194             return this->evaluate(*idx.fBase).fInt + this->evaluate(*idx.fIndex).fInt;
195         }
196         case Expression::kSwizzle_Kind:
197             break;
198         case Expression::kVariableReference_Kind:
199             SkASSERT(fVars.size());
200             SkASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) !=
201                    fVars.back().end());
202             return fVars.back()[&((VariableReference&) expr).fVariable];
203         case Expression::kTernary_Kind: {
204             const TernaryExpression& t = (const TernaryExpression&) expr;
205             return this->getLValue(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse);
206         }
207         case Expression::kTypeReference_Kind:
208             break;
209         default:
210             break;
211     }
212     ABORT("unsupported lvalue");
213 }
214 
215 struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
216     Interpreter* fInterpreter;
217     const FunctionDefinition* fFunction;
218 };
219 
do_callback(SkRasterPipeline_CallbackCtx * raw,int activePixels)220 static void do_callback(SkRasterPipeline_CallbackCtx* raw, int activePixels) {
221     CallbackCtx& ctx = (CallbackCtx&) *raw;
222     for (int i = 0; i < activePixels; ++i) {
223         ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 0]));
224         ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 1]));
225         ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 2]));
226         ctx.fInterpreter->run(*ctx.fFunction);
227         ctx.read_from[i * 4 + 2] = ctx.fInterpreter->pop().fFloat;
228         ctx.read_from[i * 4 + 1] = ctx.fInterpreter->pop().fFloat;
229         ctx.read_from[i * 4 + 0] = ctx.fInterpreter->pop().fFloat;
230     }
231 }
232 
appendStage(const AppendStage & a)233 void Interpreter::appendStage(const AppendStage& a) {
234     switch (a.fStage) {
235         case SkRasterPipeline::matrix_4x5: {
236             SkASSERT(a.fArguments.size() == 1);
237             StackIndex transpose = evaluate(*a.fArguments[0]).fInt;
238             fPipeline.append(SkRasterPipeline::matrix_4x5, &fStack[transpose]);
239             break;
240         }
241         case SkRasterPipeline::callback: {
242             SkASSERT(a.fArguments.size() == 1);
243             CallbackCtx* ctx = new CallbackCtx();
244             ctx->fInterpreter = this;
245             ctx->fn = do_callback;
246             for (const auto& e : *fProgram) {
247                 if (ProgramElement::kFunction_Kind == e.fKind) {
248                     const FunctionDefinition& f = (const FunctionDefinition&) e;
249                     if (&f.fDeclaration ==
250                                       ((const FunctionReference&) *a.fArguments[0]).fFunctions[0]) {
251                         ctx->fFunction = &f;
252                     }
253                 }
254             }
255             fPipeline.append(SkRasterPipeline::callback, ctx);
256             break;
257         }
258         default:
259             fPipeline.append(a.fStage);
260     }
261 }
262 
call(const FunctionCall & c)263 Interpreter::Value Interpreter::call(const FunctionCall& c) {
264     abort();
265 }
266 
evaluate(const Expression & expr)267 Interpreter::Value Interpreter::evaluate(const Expression& expr) {
268     switch (expr.fKind) {
269         case Expression::kAppendStage_Kind:
270             this->appendStage((const AppendStage&) expr);
271             return Value((int) 0xDEADBEEF);
272         case Expression::kBinary_Kind: {
273             #define ARITHMETIC(op) {                               \
274                 Value left = this->evaluate(*b.fLeft);             \
275                 Value right = this->evaluate(*b.fRight);           \
276                 switch (type_kind(b.fLeft->fType)) {               \
277                     case kFloat_TypeKind:                          \
278                         return Value(left.fFloat op right.fFloat); \
279                     case kInt_TypeKind:                            \
280                         return Value(left.fInt op right.fInt);     \
281                     default:                                       \
282                         abort();                                   \
283                 }                                                  \
284             }
285             #define BITWISE(op) {                                  \
286                 Value left = this->evaluate(*b.fLeft);             \
287                 Value right = this->evaluate(*b.fRight);           \
288                 switch (type_kind(b.fLeft->fType)) {               \
289                     case kInt_TypeKind:                            \
290                         return Value(left.fInt op right.fInt);     \
291                     default:                                       \
292                         abort();                                   \
293                 }                                                  \
294             }
295             #define LOGIC(op) {                                    \
296                 Value left = this->evaluate(*b.fLeft);             \
297                 Value right = this->evaluate(*b.fRight);           \
298                 switch (type_kind(b.fLeft->fType)) {               \
299                     case kFloat_TypeKind:                          \
300                         return Value(left.fFloat op right.fFloat); \
301                     case kInt_TypeKind:                            \
302                         return Value(left.fInt op right.fInt);     \
303                     default:                                       \
304                         abort();                                   \
305                 }                                                  \
306             }
307             #define COMPOUND_ARITHMETIC(op) {                      \
308                 StackIndex left = this->getLValue(*b.fLeft);       \
309                 Value right = this->evaluate(*b.fRight);           \
310                 Value result = fStack[left];                       \
311                 switch (type_kind(b.fLeft->fType)) {               \
312                     case kFloat_TypeKind:                          \
313                         result.fFloat op right.fFloat;             \
314                         break;                                     \
315                     case kInt_TypeKind:                            \
316                         result.fInt op right.fInt;                 \
317                         break;                                     \
318                     default:                                       \
319                         abort();                                   \
320                 }                                                  \
321                 fStack[left] = result;                             \
322                 return result;                                     \
323             }
324             #define COMPOUND_BITWISE(op) {                         \
325                 StackIndex left = this->getLValue(*b.fLeft);       \
326                 Value right = this->evaluate(*b.fRight);           \
327                 Value result = fStack[left];                       \
328                 switch (type_kind(b.fLeft->fType)) {               \
329                     case kInt_TypeKind:                            \
330                         result.fInt op right.fInt;                 \
331                         break;                                     \
332                     default:                                       \
333                         abort();                                   \
334                 }                                                  \
335                 fStack[left] = result;                             \
336                 return result;                                     \
337             }
338             const BinaryExpression& b = (const BinaryExpression&) expr;
339             switch (b.fOperator) {
340                 case Token::PLUS:       ARITHMETIC(+)
341                 case Token::MINUS:      ARITHMETIC(-)
342                 case Token::STAR:       ARITHMETIC(*)
343                 case Token::SLASH:      ARITHMETIC(/)
344                 case Token::BITWISEAND: BITWISE(&)
345                 case Token::BITWISEOR:  BITWISE(|)
346                 case Token::BITWISEXOR: BITWISE(^)
347                 case Token::LT:         LOGIC(<)
348                 case Token::GT:         LOGIC(>)
349                 case Token::LTEQ:       LOGIC(<=)
350                 case Token::GTEQ:       LOGIC(>=)
351                 case Token::LOGICALAND: {
352                     Value result = this->evaluate(*b.fLeft);
353                     if (result.fBool) {
354                         result = this->evaluate(*b.fRight);
355                     }
356                     return result;
357                 }
358                 case Token::LOGICALOR: {
359                     Value result = this->evaluate(*b.fLeft);
360                     if (!result.fBool) {
361                         result = this->evaluate(*b.fRight);
362                     }
363                     return result;
364                 }
365                 case Token::EQ: {
366                     StackIndex left = this->getLValue(*b.fLeft);
367                     Value right = this->evaluate(*b.fRight);
368                     fStack[left] = right;
369                     return right;
370                 }
371                 case Token::PLUSEQ:       COMPOUND_ARITHMETIC(+=)
372                 case Token::MINUSEQ:      COMPOUND_ARITHMETIC(-=)
373                 case Token::STAREQ:       COMPOUND_ARITHMETIC(*=)
374                 case Token::SLASHEQ:      COMPOUND_ARITHMETIC(/=)
375                 case Token::BITWISEANDEQ: COMPOUND_BITWISE(&=)
376                 case Token::BITWISEOREQ:  COMPOUND_BITWISE(|=)
377                 case Token::BITWISEXOREQ: COMPOUND_BITWISE(^=)
378                 default:
379                     ABORT("unsupported operator: %s\n", expr.description().c_str());
380             }
381             break;
382         }
383         case Expression::kBoolLiteral_Kind:
384             return Value(((const BoolLiteral&) expr).fValue);
385         case Expression::kConstructor_Kind:
386             break;
387         case Expression::kIntLiteral_Kind:
388             return Value((int) ((const IntLiteral&) expr).fValue);
389         case Expression::kFieldAccess_Kind:
390             break;
391         case Expression::kFloatLiteral_Kind:
392             return Value((float) ((const FloatLiteral&) expr).fValue);
393         case Expression::kFunctionCall_Kind:
394             return this->call((const FunctionCall&) expr);
395         case Expression::kIndex_Kind: {
396             const IndexExpression& idx = (const IndexExpression&) expr;
397             StackIndex pos = this->evaluate(*idx.fBase).fInt +
398                              this->evaluate(*idx.fIndex).fInt;
399             return fStack[pos];
400         }
401         case Expression::kPrefix_Kind: {
402             const PrefixExpression& p = (const PrefixExpression&) expr;
403             switch (p.fOperator) {
404                 case Token::MINUS: {
405                     Value base = this->evaluate(*p.fOperand);
406                     switch (type_kind(p.fType)) {
407                         case kFloat_TypeKind:
408                             return Value(-base.fFloat);
409                         case kInt_TypeKind:
410                             return Value(-base.fInt);
411                         default:
412                             abort();
413                     }
414                 }
415                 case Token::LOGICALNOT: {
416                     Value base = this->evaluate(*p.fOperand);
417                     return Value(!base.fBool);
418                 }
419                 default:
420                     abort();
421             }
422         }
423         case Expression::kPostfix_Kind: {
424             const PostfixExpression& p = (const PostfixExpression&) expr;
425             StackIndex lvalue = this->getLValue(*p.fOperand);
426             Value result = fStack[lvalue];
427             switch (type_kind(p.fType)) {
428                 case kFloat_TypeKind:
429                     if (Token::PLUSPLUS == p.fOperator) {
430                         ++fStack[lvalue].fFloat;
431                     } else {
432                         SkASSERT(Token::MINUSMINUS == p.fOperator);
433                         --fStack[lvalue].fFloat;
434                     }
435                     break;
436                 case kInt_TypeKind:
437                     if (Token::PLUSPLUS == p.fOperator) {
438                         ++fStack[lvalue].fInt;
439                     } else {
440                         SkASSERT(Token::MINUSMINUS == p.fOperator);
441                         --fStack[lvalue].fInt;
442                     }
443                     break;
444                 default:
445                     abort();
446             }
447             return result;
448         }
449         case Expression::kSetting_Kind:
450             break;
451         case Expression::kSwizzle_Kind:
452             break;
453         case Expression::kVariableReference_Kind:
454             SkASSERT(fVars.size());
455             SkASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) !=
456                    fVars.back().end());
457             return fStack[fVars.back()[&((VariableReference&) expr).fVariable]];
458         case Expression::kTernary_Kind: {
459             const TernaryExpression& t = (const TernaryExpression&) expr;
460             return this->evaluate(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse);
461         }
462         case Expression::kTypeReference_Kind:
463             break;
464         default:
465             break;
466     }
467     ABORT("unsupported expression: %s\n", expr.description().c_str());
468 }
469 
470 } // namespace
471 
472 #endif
473