initial SkSLJIT checkin

Docs-Preview: https://skia.org/?cl=112204
Bug: skia:
Change-Id: I10042a0200db00bd8ff8078467c409b1cf191f50
Reviewed-on: https://skia-review.googlesource.com/112204
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
diff --git a/src/sksl/SkSLInterpreter.cpp b/src/sksl/SkSLInterpreter.cpp
new file mode 100644
index 0000000..c9b7ceb
--- /dev/null
+++ b/src/sksl/SkSLInterpreter.cpp
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_STANDALONE
+
+#include "SkSLInterpreter.h"
+#include "ir/SkSLBinaryExpression.h"
+#include "ir/SkSLExpressionStatement.h"
+#include "ir/SkSLForStatement.h"
+#include "ir/SkSLFunctionCall.h"
+#include "ir/SkSLFunctionReference.h"
+#include "ir/SkSLIfStatement.h"
+#include "ir/SkSLIndexExpression.h"
+#include "ir/SkSLPostfixExpression.h"
+#include "ir/SkSLPrefixExpression.h"
+#include "ir/SkSLProgram.h"
+#include "ir/SkSLStatement.h"
+#include "ir/SkSLTernaryExpression.h"
+#include "ir/SkSLVarDeclarations.h"
+#include "ir/SkSLVarDeclarationsStatement.h"
+#include "ir/SkSLVariableReference.h"
+#include "SkRasterPipeline.h"
+#include "../jumper/SkJumper.h"
+
+namespace SkSL {
+
+void Interpreter::run() {
+    for (const auto& e : fProgram->fElements) {
+        if (ProgramElement::kFunction_Kind == e->fKind) {
+            const FunctionDefinition& f = (const FunctionDefinition&) *e;
+            if ("appendStages" == f.fDeclaration.fName) {
+                this->run(f);
+                return;
+            }
+        }
+    }
+    ASSERT(false);
+}
+
+static int SizeOf(const Type& type) {
+    return 1;
+}
+
+void Interpreter::run(const FunctionDefinition& f) {
+    fVars.emplace_back();
+    StackIndex current = (StackIndex) fStack.size();
+    for (int i = f.fDeclaration.fParameters.size() - 1; i >= 0; --i) {
+        current -= SizeOf(f.fDeclaration.fParameters[i]->fType);
+        fVars.back()[f.fDeclaration.fParameters[i]] = current;
+    }
+    fCurrentIndex.push_back({ f.fBody.get(), 0 });
+    while (fCurrentIndex.size()) {
+        this->runStatement();
+    }
+}
+
+void Interpreter::push(Value value) {
+    fStack.push_back(value);
+}
+
+Interpreter::Value Interpreter::pop() {
+    auto iter = fStack.end() - 1;
+    Value result = *iter;
+    fStack.erase(iter);
+    return result;
+}
+
+ Interpreter::StackIndex Interpreter::stackAlloc(int count) {
+    int result = fStack.size();
+    for (int i = 0; i < count; ++i) {
+        fStack.push_back(Value((int) 0xDEADBEEF));
+    }
+    return result;
+}
+
+void Interpreter::runStatement() {
+    const Statement& stmt = *fCurrentIndex.back().fStatement;
+    const size_t index = fCurrentIndex.back().fIndex;
+    fCurrentIndex.pop_back();
+    switch (stmt.fKind) {
+        case Statement::kBlock_Kind: {
+            const Block& b = (const Block&) stmt;
+            if (!b.fStatements.size()) {
+                break;
+            }
+            ASSERT(index < b.fStatements.size());
+            if (index < b.fStatements.size() - 1) {
+                fCurrentIndex.push_back({ &b, index + 1 });
+            }
+            fCurrentIndex.push_back({ b.fStatements[index].get(), 0 });
+            break;
+        }
+        case Statement::kBreak_Kind:
+            ASSERT(index == 0);
+            abort();
+        case Statement::kContinue_Kind:
+            ASSERT(index == 0);
+            abort();
+        case Statement::kDiscard_Kind:
+            ASSERT(index == 0);
+            abort();
+        case Statement::kDo_Kind:
+            abort();
+        case Statement::kExpression_Kind:
+            ASSERT(index == 0);
+            this->evaluate(*((const ExpressionStatement&) stmt).fExpression);
+            break;
+        case Statement::kFor_Kind: {
+            ForStatement& f = (ForStatement&) stmt;
+            switch (index) {
+                case 0:
+                    // initializer
+                    fCurrentIndex.push_back({ &f, 1 });
+                    if (f.fInitializer) {
+                        fCurrentIndex.push_back({ f.fInitializer.get(), 0 });
+                    }
+                    break;
+                case 1:
+                    // test & body
+                    if (f.fTest && !evaluate(*f.fTest).fBool) {
+                        break;
+                    } else {
+                        fCurrentIndex.push_back({ &f, 2 });
+                        fCurrentIndex.push_back({ f.fStatement.get(), 0 });
+                    }
+                    break;
+                case 2:
+                    // next
+                    if (f.fNext) {
+                        this->evaluate(*f.fNext);
+                    }
+                    fCurrentIndex.push_back({ &f, 1 });
+                    break;
+                default:
+                    ASSERT(false);
+            }
+            break;
+        }
+        case Statement::kGroup_Kind:
+            abort();
+        case Statement::kIf_Kind: {
+            IfStatement& i = (IfStatement&) stmt;
+            if (evaluate(*i.fTest).fBool) {
+                fCurrentIndex.push_back({ i.fIfTrue.get(), 0 });
+            } else if (i.fIfFalse) {
+                fCurrentIndex.push_back({ i.fIfFalse.get(), 0 });
+            }
+            break;
+        }
+        case Statement::kNop_Kind:
+            ASSERT(index == 0);
+            break;
+        case Statement::kReturn_Kind:
+            ASSERT(index == 0);
+            abort();
+        case Statement::kSwitch_Kind:
+            abort();
+        case Statement::kVarDeclarations_Kind:
+            ASSERT(index == 0);
+            for (const auto& decl :((const VarDeclarationsStatement&) stmt).fDeclaration->fVars) {
+                const Variable* var = ((VarDeclaration&) *decl).fVar;
+                StackIndex pos = this->stackAlloc(SizeOf(var->fType));
+                fVars.back()[var] = pos;
+                if (var->fInitialValue) {
+                    fStack[pos] = this->evaluate(*var->fInitialValue);
+                }
+            }
+            break;
+        case Statement::kWhile_Kind:
+            abort();
+        default:
+            abort();
+    }
+}
+
+static Interpreter::TypeKind type_kind(const Type& type) {
+    if (type.fName == "int") {
+        return Interpreter::kInt_TypeKind;
+    } else if (type.fName == "float") {
+        return Interpreter::kFloat_TypeKind;
+    }
+    ABORT("unsupported type: %s\n", type.description().c_str());
+}
+
+Interpreter::StackIndex Interpreter::getLValue(const Expression& expr) {
+    switch (expr.fKind) {
+        case Expression::kFieldAccess_Kind:
+            break;
+        case Expression::kIndex_Kind: {
+            const IndexExpression& idx = (const IndexExpression&) expr;
+            return this->evaluate(*idx.fBase).fInt + this->evaluate(*idx.fIndex).fInt;
+        }
+        case Expression::kSwizzle_Kind:
+            break;
+        case Expression::kVariableReference_Kind:
+            ASSERT(fVars.size());
+            ASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) !=
+                   fVars.back().end());
+            return fVars.back()[&((VariableReference&) expr).fVariable];
+        case Expression::kTernary_Kind: {
+            const TernaryExpression& t = (const TernaryExpression&) expr;
+            return this->getLValue(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse);
+        }
+        case Expression::kTypeReference_Kind:
+            break;
+        default:
+            break;
+    }
+    ABORT("unsupported lvalue");
+}
+
+struct CallbackCtx : public SkJumper_CallbackCtx {
+    Interpreter* fInterpreter;
+    const FunctionDefinition* fFunction;
+};
+
+static void do_callback(SkJumper_CallbackCtx* raw, int activePixels) {
+    CallbackCtx& ctx = (CallbackCtx&) *raw;
+    for (int i = 0; i < activePixels; ++i) {
+        ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 0]));
+        ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 1]));
+        ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 2]));
+        ctx.fInterpreter->run(*ctx.fFunction);
+        ctx.read_from[i * 4 + 2] = ctx.fInterpreter->pop().fFloat;
+        ctx.read_from[i * 4 + 1] = ctx.fInterpreter->pop().fFloat;
+        ctx.read_from[i * 4 + 0] = ctx.fInterpreter->pop().fFloat;
+    }
+}
+
+void Interpreter::appendStage(const AppendStage& a) {
+    switch (a.fStage) {
+        case SkRasterPipeline::matrix_4x5: {
+            ASSERT(a.fArguments.size() == 1);
+            StackIndex transpose = evaluate(*a.fArguments[0]).fInt;
+            fPipeline.append(SkRasterPipeline::matrix_4x5, &fStack[transpose]);
+            break;
+        }
+        case SkRasterPipeline::callback: {
+            ASSERT(a.fArguments.size() == 1);
+            CallbackCtx* ctx = new CallbackCtx();
+            ctx->fInterpreter = this;
+            ctx->fn = do_callback;
+            for (const auto& e : fProgram->fElements) {
+                if (ProgramElement::kFunction_Kind == e->fKind) {
+                    const FunctionDefinition& f = (const FunctionDefinition&) *e;
+                    if (&f.fDeclaration ==
+                                      ((const FunctionReference&) *a.fArguments[0]).fFunctions[0]) {
+                        ctx->fFunction = &f;
+                    }
+                }
+            }
+            fPipeline.append(SkRasterPipeline::callback, ctx);
+            break;
+        }
+        default:
+            fPipeline.append(a.fStage);
+    }
+}
+
+Interpreter::Value Interpreter::call(const FunctionCall& c) {
+    abort();
+}
+
+Interpreter::Value Interpreter::evaluate(const Expression& expr) {
+    switch (expr.fKind) {
+        case Expression::kAppendStage_Kind:
+            this->appendStage((const AppendStage&) expr);
+            return Value((int) 0xDEADBEEF);
+        case Expression::kBinary_Kind: {
+            #define ARITHMETIC(op) {                               \
+                Value left = this->evaluate(*b.fLeft);             \
+                Value right = this->evaluate(*b.fRight);           \
+                switch (type_kind(b.fLeft->fType)) {               \
+                    case kFloat_TypeKind:                          \
+                        return Value(left.fFloat op right.fFloat); \
+                    case kInt_TypeKind:                            \
+                        return Value(left.fInt op right.fInt);     \
+                    default:                                       \
+                        abort();                                   \
+                }                                                  \
+            }
+            #define BITWISE(op) {                                  \
+                Value left = this->evaluate(*b.fLeft);             \
+                Value right = this->evaluate(*b.fRight);           \
+                switch (type_kind(b.fLeft->fType)) {               \
+                    case kInt_TypeKind:                            \
+                        return Value(left.fInt op right.fInt);     \
+                    default:                                       \
+                        abort();                                   \
+                }                                                  \
+            }
+            #define LOGIC(op) {                                    \
+                Value left = this->evaluate(*b.fLeft);             \
+                Value right = this->evaluate(*b.fRight);           \
+                switch (type_kind(b.fLeft->fType)) {               \
+                    case kFloat_TypeKind:                          \
+                        return Value(left.fFloat op right.fFloat); \
+                    case kInt_TypeKind:                            \
+                        return Value(left.fInt op right.fInt);     \
+                    default:                                       \
+                        abort();                                   \
+                }                                                  \
+            }
+            #define COMPOUND_ARITHMETIC(op) {                      \
+                StackIndex left = this->getLValue(*b.fLeft);       \
+                Value right = this->evaluate(*b.fRight);           \
+                Value result = fStack[left];                       \
+                switch (type_kind(b.fLeft->fType)) {               \
+                    case kFloat_TypeKind:                          \
+                        result.fFloat op right.fFloat;             \
+                        break;                                     \
+                    case kInt_TypeKind:                            \
+                        result.fInt op right.fInt;                 \
+                        break;                                     \
+                    default:                                       \
+                        abort();                                   \
+                }                                                  \
+                fStack[left] = result;                             \
+                return result;                                     \
+            }
+            #define COMPOUND_BITWISE(op) {                         \
+                StackIndex left = this->getLValue(*b.fLeft);       \
+                Value right = this->evaluate(*b.fRight);           \
+                Value result = fStack[left];                       \
+                switch (type_kind(b.fLeft->fType)) {               \
+                    case kInt_TypeKind:                            \
+                        result.fInt op right.fInt;                 \
+                        break;                                     \
+                    default:                                       \
+                        abort();                                   \
+                }                                                  \
+                fStack[left] = result;                             \
+                return result;                                     \
+            }
+            const BinaryExpression& b = (const BinaryExpression&) expr;
+            switch (b.fOperator) {
+                case Token::PLUS:       ARITHMETIC(+)
+                case Token::MINUS:      ARITHMETIC(-)
+                case Token::STAR:       ARITHMETIC(*)
+                case Token::SLASH:      ARITHMETIC(/)
+                case Token::BITWISEAND: BITWISE(&)
+                case Token::BITWISEOR:  BITWISE(|)
+                case Token::BITWISEXOR: BITWISE(^)
+                case Token::LT:         LOGIC(<)
+                case Token::GT:         LOGIC(>)
+                case Token::LTEQ:       LOGIC(<=)
+                case Token::GTEQ:       LOGIC(>=)
+                case Token::LOGICALAND: {
+                    Value result = this->evaluate(*b.fLeft);
+                    if (result.fBool) {
+                        result = this->evaluate(*b.fRight);
+                    }
+                    return result;
+                }
+                case Token::LOGICALOR: {
+                    Value result = this->evaluate(*b.fLeft);
+                    if (!result.fBool) {
+                        result = this->evaluate(*b.fRight);
+                    }
+                    return result;
+                }
+                case Token::EQ: {
+                    StackIndex left = this->getLValue(*b.fLeft);
+                    Value right = this->evaluate(*b.fRight);
+                    fStack[left] = right;
+                    return right;
+                }
+                case Token::PLUSEQ:       COMPOUND_ARITHMETIC(+=)
+                case Token::MINUSEQ:      COMPOUND_ARITHMETIC(-=)
+                case Token::STAREQ:       COMPOUND_ARITHMETIC(*=)
+                case Token::SLASHEQ:      COMPOUND_ARITHMETIC(/=)
+                case Token::BITWISEANDEQ: COMPOUND_BITWISE(&=)
+                case Token::BITWISEOREQ:  COMPOUND_BITWISE(|=)
+                case Token::BITWISEXOREQ: COMPOUND_BITWISE(^=)
+                default:
+                    ABORT("unsupported operator: %s\n", expr.description().c_str());
+            }
+            break;
+        }
+        case Expression::kBoolLiteral_Kind:
+            return Value(((const BoolLiteral&) expr).fValue);
+        case Expression::kConstructor_Kind:
+            break;
+        case Expression::kIntLiteral_Kind:
+            return Value((int) ((const IntLiteral&) expr).fValue);
+        case Expression::kFieldAccess_Kind:
+            break;
+        case Expression::kFloatLiteral_Kind:
+            return Value((float) ((const FloatLiteral&) expr).fValue);
+        case Expression::kFunctionCall_Kind:
+            return this->call((const FunctionCall&) expr);
+        case Expression::kIndex_Kind: {
+            const IndexExpression& idx = (const IndexExpression&) expr;
+            StackIndex pos = this->evaluate(*idx.fBase).fInt +
+                             this->evaluate(*idx.fIndex).fInt;
+            return fStack[pos];
+        }
+        case Expression::kPrefix_Kind: {
+            const PrefixExpression& p = (const PrefixExpression&) expr;
+            switch (p.fOperator) {
+                case Token::MINUS: {
+                    Value base = this->evaluate(*p.fOperand);
+                    switch (type_kind(p.fType)) {
+                        case kFloat_TypeKind:
+                            return Value(-base.fFloat);
+                        case kInt_TypeKind:
+                            return Value(-base.fInt);
+                        default:
+                            abort();
+                    }
+                }
+                case Token::LOGICALNOT: {
+                    Value base = this->evaluate(*p.fOperand);
+                    return Value(!base.fBool);
+                }
+                default:
+                    abort();
+            }
+        }
+        case Expression::kPostfix_Kind: {
+            const PostfixExpression& p = (const PostfixExpression&) expr;
+            StackIndex lvalue = this->getLValue(*p.fOperand);
+            Value result = fStack[lvalue];
+            switch (type_kind(p.fType)) {
+                case kFloat_TypeKind:
+                    if (Token::PLUSPLUS == p.fOperator) {
+                        ++fStack[lvalue].fFloat;
+                    } else {
+                        ASSERT(Token::MINUSMINUS == p.fOperator);
+                        --fStack[lvalue].fFloat;
+                    }
+                    break;
+                case kInt_TypeKind:
+                    if (Token::PLUSPLUS == p.fOperator) {
+                        ++fStack[lvalue].fInt;
+                    } else {
+                        ASSERT(Token::MINUSMINUS == p.fOperator);
+                        --fStack[lvalue].fInt;
+                    }
+                    break;
+                default:
+                    abort();
+            }
+            return result;
+        }
+        case Expression::kSetting_Kind:
+            break;
+        case Expression::kSwizzle_Kind:
+            break;
+        case Expression::kVariableReference_Kind:
+            ASSERT(fVars.size());
+            ASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) !=
+                   fVars.back().end());
+            return fStack[fVars.back()[&((VariableReference&) expr).fVariable]];
+        case Expression::kTernary_Kind: {
+            const TernaryExpression& t = (const TernaryExpression&) expr;
+            return this->evaluate(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse);
+        }
+        case Expression::kTypeReference_Kind:
+            break;
+        default:
+            break;
+    }
+    ABORT("unsupported expression: %s\n", expr.description().c_str());
+}
+
+} // namespace
+
+#endif