Home | History | Annotate | Download | only in sksl
      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 
     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 
     43 static int SizeOf(const Type& type) {
     44     return 1;
     45 }
     46 
     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 
     60 void Interpreter::push(Value value) {
     61     fStack.push_back(value);
     62 }
     63 
     64 Interpreter::Value Interpreter::pop() {
     65     auto iter = fStack.end() - 1;
     66     Value result = *iter;
     67     fStack.erase(iter);
     68     return result;
     69 }
     70 
     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 
     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 
    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 
    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 
    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 
    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 
    263 Interpreter::Value Interpreter::call(const FunctionCall& c) {
    264     abort();
    265 }
    266 
    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