Remove old SkSL JIT and cleanup include files a bit

- The raster pipeline JIT was an experiment that never really panned
  out (except for also introducing the interpreter, which survives).
  The removal should be pretty thorough, including undoing some changes
  to SkRasterPipeline itself. For reference, I basically undid most of
  https://skia-review.googlesource.com/c/skia/+/112204/

- With runtime shaders, always convert to Program using kPipelineStage
  This makes the first-pass compile consistent with runtime color filter,
  and with GrSkSLFP.

- Remove sksl_mixer.inc, which hasn't been used in a while.

- In sksl_pipeline.inc, all of the math symbols are already declared
  in sksl_gpu.inc, which forms the base symbol table when this include
  is parsed.

  sk_x and sk_y appear to never be used? Those builtin IDs are the IDs
  of the x and y params to main, but that logic still works without
  these declarations.

  sk_OutColor only makes sense in FP files (it's still declared in
  sksl_fp.inc).

Change-Id: Ie8dd68d2c4687745d46f96804a76695bce8c1ba2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/246017
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index c2d04fe..48f99ce 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -73,12 +73,6 @@
   if (skia_use_angle) {
     defines += [ "SK_ANGLE" ]
   }
-  if (skia_llvm_path != "") {
-    defines += [ "SK_LLVM_AVAILABLE" ]
-    include_dirs += [ "$skia_llvm_path/include" ]
-    libs += [ skia_llvm_lib ]
-    lib_dirs += [ "$skia_llvm_path/lib/" ]
-  }
 }
 
 # Any code that's linked into Skia-the-library should use this config via += skia_library_configs.
diff --git a/gn/skia.gni b/gn/skia.gni
index 928ab7d..398d61f 100644
--- a/gn/skia.gni
+++ b/gn/skia.gni
@@ -33,8 +33,6 @@
   skia_generate_workarounds = false
   skia_include_multiframe_procs = false
   skia_lex = false
-  skia_llvm_lib = "LLVM"
-  skia_llvm_path = ""
   skia_pdf_subset_harfbuzz = false  # TODO: set skia_pdf_subset_harfbuzz to skia_use_harfbuzz.
   skia_qt_path = getenv("QT_PATH")
   skia_skqp_global_error_tolerance = 0
diff --git a/gn/sksl.gni b/gn/sksl.gni
index eb83fb3..3241259 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -13,7 +13,6 @@
   "$_src/sksl/SkSLCFGGenerator.cpp",
   "$_src/sksl/SkSLCompiler.cpp",
   "$_src/sksl/SkSLIRGenerator.cpp",
-  "$_src/sksl/SkSLJIT.cpp",
   "$_src/sksl/SkSLLexer.cpp",
   "$_src/sksl/SkSLParser.cpp",
   "$_src/sksl/SkSLSectionAndParameterHelper.cpp",
diff --git a/gn/tests.gni b/gn/tests.gni
index 9675035..6ce4dbc 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -248,7 +248,6 @@
   "$_tests/SkSLFPTest.cpp",
   "$_tests/SkSLGLSLTest.cpp",
   "$_tests/SkSLInterpreterTest.cpp",
-  "$_tests/SkSLJITTest.cpp",
   "$_tests/SkSLMemoryLayoutTest.cpp",
   "$_tests/SkSLMetalTest.cpp",
   "$_tests/SkSLSPIRVTest.cpp",
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index 1ff515e..2e26b47 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -27,7 +27,7 @@
     this->unchecked_append(stage, ctx);
 }
 void SkRasterPipeline::unchecked_append(StockStage stage, void* ctx) {
-    fStages = fAlloc->make<StageList>( StageList{fStages, (uint64_t) stage, ctx, false} );
+    fStages = fAlloc->make<StageList>( StageList{fStages, stage, ctx} );
     fNumStages   += 1;
     fSlotsNeeded += ctx ? 2 : 1;
 }
@@ -36,11 +36,6 @@
     memcpy(&ptrCtx, &ctx, sizeof(ctx));
     this->append(stage, ptrCtx);
 }
-void SkRasterPipeline::append(void* fn, void* ctx) {
-    fStages = fAlloc->make<StageList>( StageList{fStages, (uint64_t) fn, ctx, true} );
-    fNumStages   += 1;
-    fSlotsNeeded += ctx ? 2 : 1;
-}
 
 void SkRasterPipeline::extend(const SkRasterPipeline& src) {
     if (src.empty()) {
@@ -289,8 +284,7 @@
     // Stages are stored backwards in fStages, so we reverse here, back to front.
     *--ip = (void*)SkOpts::just_return_lowp;
     for (const StageList* st = fStages; st; st = st->prev) {
-        SkOpts::StageFn fn;
-        if (!st->rawFunction && (fn = SkOpts::stages_lowp[st->stage])) {
+        if (auto fn = SkOpts::stages_lowp[st->stage]) {
             if (st->ctx) {
                 *--ip = st->ctx;
             }
@@ -309,11 +303,7 @@
         if (st->ctx) {
             *--ip = st->ctx;
         }
-        if (st->rawFunction) {
-            *--ip = (void*)st->stage;
-        } else {
-            *--ip = (void*)SkOpts::stages_highp[st->stage];
-        }
+        *--ip = (void*)SkOpts::stages_highp[st->stage];
     }
     return SkOpts::start_pipeline_highp;
 }
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 938735f..fab9540 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -224,9 +224,6 @@
     void append(StockStage, void* = nullptr);
     void append(StockStage stage, const void* ctx) { this->append(stage, const_cast<void*>(ctx)); }
     void append(StockStage, uintptr_t ctx);
-    // For raw functions (i.e. from a JIT).  Don't use this unless you know exactly what fn needs to
-    // be. :)
-    void append(void* fn, void* ctx);
 
     // Append all stages to this pipeline.
     void extend(const SkRasterPipeline&);
@@ -269,9 +266,8 @@
 private:
     struct StageList {
         StageList* prev;
-        uint64_t   stage;
+        StockStage stage;
         void*      ctx;
-        bool       rawFunction;
     };
 
     using StartPipelineFn = void(*)(size_t,size_t,size_t,size_t, void** program);
diff --git a/src/shaders/SkRTShader.cpp b/src/shaders/SkRTShader.cpp
index bba86a2..c42a8d0 100644
--- a/src/shaders/SkRTShader.cpp
+++ b/src/shaders/SkRTShader.cpp
@@ -59,7 +59,7 @@
     SkAutoMutexExclusive ama(fByteCodeMutex);
     if (!fByteCode) {
         SkSL::Compiler c;
-        auto prog = c.convertProgram(SkSL::Program::kGeneric_Kind,
+        auto prog = c.convertProgram(SkSL::Program::kPipelineStage_Kind,
                                      SkSL::String(fSkSL.c_str()),
                                      SkSL::Program::Settings());
         if (c.errorCount()) {
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index be26279..8ef2dd5 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -408,7 +408,6 @@
             cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                          constantPropagate, e, nullptr });
             break;
-        case Expression::kAppendStage_Kind:   // fall through
         case Expression::kBoolLiteral_Kind:   // fall through
         case Expression::kExternalValue_Kind: // fall through
         case Expression::kFloatLiteral_Kind:  // fall through
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 16a24f0..7aa6b9f 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -210,7 +210,6 @@
     ADD_TYPE(GSampler2DArrayShadow);
     ADD_TYPE(GSamplerCubeArrayShadow);
     ADD_TYPE(FragmentProcessor);
-    ADD_TYPE(SkRasterPipeline);
     ADD_TYPE(Sampler);
     ADD_TYPE(Texture2D);
 
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index e06bac1..acfafc5 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -207,7 +207,6 @@
     , fSkCaps_Type(new Type("$sk_Caps"))
     , fSkArgs_Type(new Type("$sk_Args"))
     , fFragmentProcessor_Type(fp_type(fInt_Type.get(), fBool_Type.get()))
-    , fSkRasterPipeline_Type(new Type("SkRasterPipeline"))
     , fDefined_Expression(new Defined(*fInvalid_Type)) {}
 
     static std::vector<const Type*> static_type(const Type& t) {
@@ -381,7 +380,6 @@
     const std::unique_ptr<Type> fSkCaps_Type;
     const std::unique_ptr<Type> fSkArgs_Type;
     const std::unique_ptr<Type> fFragmentProcessor_Type;
-    const std::unique_ptr<Type> fSkRasterPipeline_Type;
 
     // dummy expression used to mark that a variable has a value during dataflow analysis (when it
     // could have several different values, or the analyzer is otherwise unable to assign it a
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index e082ae9..9b71c17 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -12,7 +12,6 @@
 
 #include "src/sksl/SkSLCompiler.h"
 #include "src/sksl/SkSLParser.h"
-#include "src/sksl/ir/SkSLAppendStage.h"
 #include "src/sksl/ir/SkSLBinaryExpression.h"
 #include "src/sksl/ir/SkSLBoolLiteral.h"
 #include "src/sksl/ir/SkSLBreakStatement.h"
@@ -2257,91 +2256,6 @@
     return result;
 }
 
-std::unique_ptr<Expression> IRGenerator::convertAppend(int offset,
-                                                       const std::vector<ASTNode>& args) {
-#ifndef SKSL_STANDALONE
-    if (args.size() < 2) {
-        fErrors.error(offset, "'append' requires at least two arguments");
-        return nullptr;
-    }
-    std::unique_ptr<Expression> pipeline = this->convertExpression(args[0]);
-    if (!pipeline) {
-        return nullptr;
-    }
-    if (pipeline->fType != *fContext.fSkRasterPipeline_Type) {
-        fErrors.error(offset, "first argument of 'append' must have type 'SkRasterPipeline'");
-        return nullptr;
-    }
-    if (ASTNode::Kind::kIdentifier != args[1].fKind) {
-        fErrors.error(offset, "'" + args[1].description() + "' is not a valid stage");
-        return nullptr;
-    }
-    StringFragment name = args[1].getString();
-    SkRasterPipeline::StockStage stage = SkRasterPipeline::premul;
-    std::vector<std::unique_ptr<Expression>> stageArgs;
-    stageArgs.push_back(std::move(pipeline));
-    for (size_t i = 2; i < args.size(); ++i) {
-        std::unique_ptr<Expression> arg = this->convertExpression(args[i]);
-        if (!arg) {
-            return nullptr;
-        }
-        stageArgs.push_back(std::move(arg));
-    }
-    size_t expectedArgs = 0;
-    // FIXME use a map
-    if ("premul" == name) {
-        stage = SkRasterPipeline::premul;
-    }
-    else if ("unpremul" == name) {
-        stage = SkRasterPipeline::unpremul;
-    }
-    else if ("clamp_0" == name) {
-        stage = SkRasterPipeline::clamp_0;
-    }
-    else if ("clamp_1" == name) {
-        stage = SkRasterPipeline::clamp_1;
-    }
-    else if ("matrix_4x5" == name) {
-        expectedArgs = 1;
-        stage = SkRasterPipeline::matrix_4x5;
-        if (1 == stageArgs.size() && stageArgs[0]->fType.fName != "float[20]") {
-            fErrors.error(offset, "pipeline stage '" + name + "' expected a float[20] argument");
-            return nullptr;
-        }
-    }
-    else {
-        bool found = false;
-        for (const auto& e : *fProgramElements) {
-            if (ProgramElement::kFunction_Kind == e->fKind) {
-                const FunctionDefinition& f = (const FunctionDefinition&) *e;
-                if (f.fDeclaration.fName == name) {
-                    stage = SkRasterPipeline::callback;
-                    std::vector<const FunctionDeclaration*> functions = { &f.fDeclaration };
-                    stageArgs.emplace_back(new FunctionReference(fContext, offset, functions));
-                    found = true;
-                    break;
-                }
-            }
-        }
-        if (!found) {
-            fErrors.error(offset, "'" + name + "' is not a valid pipeline stage");
-            return nullptr;
-        }
-    }
-    if (args.size() != expectedArgs + 2) {
-        fErrors.error(offset, "pipeline stage '" + name + "' expected an additional argument " +
-                              "count of " + to_string((int) expectedArgs) + ", but found " +
-                              to_string((int) args.size() - 1));
-        return nullptr;
-    }
-    return std::unique_ptr<Expression>(new AppendStage(fContext, offset, stage,
-                                                       std::move(stageArgs)));
-#else
-    SkASSERT(false);
-    return nullptr;
-#endif
-}
-
 std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
     SkASSERT(index.fKind == ASTNode::Kind::kIndex);
     auto iter = index.begin();
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 7eb1157..20a556f 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -95,7 +95,6 @@
                                      std::vector<std::unique_ptr<Expression>> arguments);
     int coercionCost(const Expression& expr, const Type& type);
     std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
-    std::unique_ptr<Expression> convertAppend(int offset, const std::vector<ASTNode>& args);
     std::unique_ptr<Block> convertBlock(const ASTNode& block);
     std::unique_ptr<Statement> convertBreak(const ASTNode& b);
     std::unique_ptr<Expression> convertNumberConstructor(
diff --git a/src/sksl/SkSLJIT.cpp b/src/sksl/SkSLJIT.cpp
deleted file mode 100644
index 9077498..0000000
--- a/src/sksl/SkSLJIT.cpp
+++ /dev/null
@@ -1,1931 +0,0 @@
-/*
- * 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
-
-#ifdef SK_LLVM_AVAILABLE
-
-#include "src/sksl/SkSLJIT.h"
-
-#include "src/core/SkCpu.h"
-#include "src/core/SkRasterPipeline.h"
-#include "src/sksl/ir/SkSLAppendStage.h"
-#include "src/sksl/ir/SkSLExpressionStatement.h"
-#include "src/sksl/ir/SkSLFunctionCall.h"
-#include "src/sksl/ir/SkSLFunctionReference.h"
-#include "src/sksl/ir/SkSLIndexExpression.h"
-#include "src/sksl/ir/SkSLProgram.h"
-#include "src/sksl/ir/SkSLUnresolvedFunction.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-
-static constexpr int MAX_VECTOR_COUNT = 16;
-
-extern "C" void sksl_pipeline_append(SkRasterPipeline* p, int stage, void* ctx) {
-    p->append((SkRasterPipeline::StockStage) stage, ctx);
-}
-
-#define PTR_SIZE sizeof(void*)
-
-extern "C" void sksl_pipeline_append_callback(SkRasterPipeline* p, void* fn) {
-    p->append(fn, nullptr);
-}
-
-extern "C" void sksl_debug_print(float f) {
-    printf("Debug: %f\n", f);
-}
-
-extern "C" float sksl_clamp1(float f, float min, float max) {
-    return SkTPin(f, min, max);
-}
-
-using float2 = __attribute__((vector_size(8))) float;
-using float3 = __attribute__((vector_size(16))) float;
-using float4 = __attribute__((vector_size(16))) float;
-
-extern "C" float2 sksl_clamp2(float2 f, float min, float max) {
-    return float2 { SkTPin(f[0], min, max), SkTPin(f[1], min, max) };
-}
-
-extern "C" float3 sksl_clamp3(float3 f, float min, float max) {
-    return float3 { SkTPin(f[0], min, max), SkTPin(f[1], min, max), SkTPin(f[2], min, max) };
-}
-
-extern "C" float4 sksl_clamp4(float4 f, float min, float max) {
-    return float4 { SkTPin(f[0], min, max), SkTPin(f[1], min, max), SkTPin(f[2], min, max),
-                    SkTPin(f[3], min, max) };
-}
-
-namespace SkSL {
-
-static constexpr int STAGE_PARAM_COUNT = 12;
-
-static bool ends_with_branch(const Statement& stmt) {
-    switch (stmt.fKind) {
-        case Statement::kBlock_Kind: {
-            const Block& b = (const Block&) stmt;
-            if (b.fStatements.size()) {
-                return ends_with_branch(*b.fStatements.back());
-            }
-            return false;
-        }
-        case Statement::kBreak_Kind:    // fall through
-        case Statement::kContinue_Kind: // fall through
-        case Statement::kReturn_Kind:   // fall through
-            return true;
-        default:
-            return false;
-    }
-}
-
-JIT::JIT(Compiler* compiler)
-: fCompiler(*compiler) {
-    LLVMInitializeNativeTarget();
-    LLVMInitializeNativeAsmPrinter();
-    LLVMLinkInMCJIT();
-    SkASSERT(!SkCpu::Supports(SkCpu::SKX)); // not yet supported
-    if (SkCpu::Supports(SkCpu::HSW)) {
-        fVectorCount = 8;
-        fCPU = "haswell";
-    } else if (SkCpu::Supports(SkCpu::AVX)) {
-        fVectorCount = 8;
-        fCPU = "ivybridge";
-    } else {
-        fVectorCount = 4;
-        fCPU = nullptr;
-    }
-    fContext = LLVMContextCreate();
-    fVoidType = LLVMVoidTypeInContext(fContext);
-    fInt1Type = LLVMInt1TypeInContext(fContext);
-    fInt1VectorType = LLVMVectorType(fInt1Type, fVectorCount);
-    fInt1Vector2Type = LLVMVectorType(fInt1Type, 2);
-    fInt1Vector3Type = LLVMVectorType(fInt1Type, 3);
-    fInt1Vector4Type = LLVMVectorType(fInt1Type, 4);
-    fInt8Type = LLVMInt8TypeInContext(fContext);
-    fInt8PtrType = LLVMPointerType(fInt8Type, 0);
-    fInt32Type = LLVMInt32TypeInContext(fContext);
-    fInt64Type = LLVMInt64TypeInContext(fContext);
-    fSizeTType = LLVMInt64TypeInContext(fContext);
-    fInt32VectorType = LLVMVectorType(fInt32Type, fVectorCount);
-    fInt32Vector2Type = LLVMVectorType(fInt32Type, 2);
-    fInt32Vector3Type = LLVMVectorType(fInt32Type, 3);
-    fInt32Vector4Type = LLVMVectorType(fInt32Type, 4);
-    fFloat32Type = LLVMFloatTypeInContext(fContext);
-    fFloat32VectorType = LLVMVectorType(fFloat32Type, fVectorCount);
-    fFloat32Vector2Type = LLVMVectorType(fFloat32Type, 2);
-    fFloat32Vector3Type = LLVMVectorType(fFloat32Type, 3);
-    fFloat32Vector4Type = LLVMVectorType(fFloat32Type, 4);
-}
-
-JIT::~JIT() {
-    LLVMOrcDisposeInstance(fJITStack);
-    LLVMContextDispose(fContext);
-}
-
-void JIT::addBuiltinFunction(const char* ourName, const char* realName, LLVMTypeRef returnType,
-                             std::vector<LLVMTypeRef> parameters) {
-    bool found = false;
-    for (const auto& pair : *fProgram->fSymbols) {
-        if (Symbol::kFunctionDeclaration_Kind == pair.second->fKind) {
-            const FunctionDeclaration& f = (const FunctionDeclaration&) *pair.second;
-            if (pair.first != ourName || returnType != this->getType(f.fReturnType) ||
-                parameters.size() != f.fParameters.size()) {
-                continue;
-            }
-            for (size_t i = 0; i < parameters.size(); ++i) {
-                if (parameters[i] != this->getType(f.fParameters[i]->fType)) {
-                    goto next;
-                }
-            }
-            fFunctions[&f] = LLVMAddFunction(fModule, realName, LLVMFunctionType(returnType,
-                                                                                 parameters.data(),
-                                                                                 parameters.size(),
-                                                                                 false));
-            found = true;
-        }
-        if (Symbol::kUnresolvedFunction_Kind == pair.second->fKind) {
-            // FIXME consolidate this with the code above
-            for (const auto& f : ((const UnresolvedFunction&) *pair.second).fFunctions) {
-                if (pair.first != ourName || returnType != this->getType(f->fReturnType) ||
-                    parameters.size() != f->fParameters.size()) {
-                    continue;
-                }
-                for (size_t i = 0; i < parameters.size(); ++i) {
-                    if (parameters[i] != this->getType(f->fParameters[i]->fType)) {
-                        goto next;
-                    }
-                }
-                fFunctions[f] = LLVMAddFunction(fModule, realName, LLVMFunctionType(
-                                                                                  returnType,
-                                                                                  parameters.data(),
-                                                                                  parameters.size(),
-                                                                                  false));
-                found = true;
-            }
-        }
-        next:;
-    }
-    SkASSERT(found);
-}
-
-void JIT::loadBuiltinFunctions() {
-    this->addBuiltinFunction("abs", "fabs", fFloat32Type, { fFloat32Type });
-    this->addBuiltinFunction("sin", "sinf", fFloat32Type, { fFloat32Type });
-    this->addBuiltinFunction("cos", "cosf", fFloat32Type, { fFloat32Type });
-    this->addBuiltinFunction("tan", "tanf", fFloat32Type, { fFloat32Type });
-    this->addBuiltinFunction("sqrt", "sqrtf", fFloat32Type, { fFloat32Type });
-    this->addBuiltinFunction("clamp", "sksl_clamp1", fFloat32Type, { fFloat32Type,
-                                                                     fFloat32Type,
-                                                                     fFloat32Type });
-    this->addBuiltinFunction("clamp", "sksl_clamp2", fFloat32Vector2Type, { fFloat32Vector2Type,
-                                                                            fFloat32Type,
-                                                                            fFloat32Type });
-    this->addBuiltinFunction("clamp", "sksl_clamp3", fFloat32Vector3Type, { fFloat32Vector3Type,
-                                                                            fFloat32Type,
-                                                                            fFloat32Type });
-    this->addBuiltinFunction("clamp", "sksl_clamp4", fFloat32Vector4Type, { fFloat32Vector4Type,
-                                                                            fFloat32Type,
-                                                                            fFloat32Type });
-    this->addBuiltinFunction("print", "sksl_debug_print", fVoidType, { fFloat32Type });
-}
-
-uint64_t JIT::resolveSymbol(const char* name, JIT* jit) {
-    LLVMOrcTargetAddress result;
-    if (!LLVMOrcGetSymbolAddress(jit->fJITStack, &result, name)) {
-        if (!strcmp(name, "_sksl_pipeline_append")) {
-            result = (uint64_t) &sksl_pipeline_append;
-        } else if (!strcmp(name, "_sksl_pipeline_append_callback")) {
-            result = (uint64_t) &sksl_pipeline_append_callback;
-        } else if (!strcmp(name, "_sksl_clamp1")) {
-            result = (uint64_t) &sksl_clamp1;
-        } else if (!strcmp(name, "_sksl_clamp2")) {
-            result = (uint64_t) &sksl_clamp2;
-        } else if (!strcmp(name, "_sksl_clamp3")) {
-            result = (uint64_t) &sksl_clamp3;
-        } else if (!strcmp(name, "_sksl_clamp4")) {
-            result = (uint64_t) &sksl_clamp4;
-        } else if (!strcmp(name, "_sksl_debug_print")) {
-            result = (uint64_t) &sksl_debug_print;
-        } else {
-            result = llvm::RTDyldMemoryManager::getSymbolAddressInProcess(name);
-        }
-    }
-    SkASSERT(result);
-    return result;
-}
-
-LLVMValueRef JIT::compileFunctionCall(LLVMBuilderRef builder, const FunctionCall& fc) {
-    LLVMValueRef func = fFunctions[&fc.fFunction];
-    SkASSERT(func);
-    std::vector<LLVMValueRef> parameters;
-    for (const auto& a : fc.fArguments) {
-        parameters.push_back(this->compileExpression(builder, *a));
-    }
-    return LLVMBuildCall(builder, func, parameters.data(), parameters.size(), "");
-}
-
-LLVMTypeRef JIT::getType(const Type& type) {
-    switch (type.kind()) {
-        case Type::kOther_Kind:
-            if (type.name() == "void") {
-                return fVoidType;
-            }
-            SkASSERT(type.name() == "SkRasterPipeline");
-            return fInt8PtrType;
-        case Type::kScalar_Kind:
-            if (type.isSigned() || type.isUnsigned()) {
-                return fInt32Type;
-            }
-            if (type.isUnsigned()) {
-                return fInt32Type;
-            }
-            if (type.isFloat()) {
-                return fFloat32Type;
-            }
-            SkASSERT(type.name() == "bool");
-            return fInt1Type;
-        case Type::kArray_Kind:
-            return LLVMPointerType(this->getType(type.componentType()), 0);
-        case Type::kVector_Kind:
-            if (type.name() == "float2" || type.name() == "half2") {
-                return fFloat32Vector2Type;
-            }
-            if (type.name() == "float3" || type.name() == "half3") {
-                return fFloat32Vector3Type;
-            }
-            if (type.name() == "float4" || type.name() == "half4") {
-                return fFloat32Vector4Type;
-            }
-            if (type.name() == "int2" || type.name() == "short2" || type.name == "byte2") {
-                return fInt32Vector2Type;
-            }
-            if (type.name() == "int3" || type.name() == "short3" || type.name == "byte3") {
-                return fInt32Vector3Type;
-            }
-            if (type.name() == "int4" || type.name() == "short4" || type.name == "byte3") {
-                return fInt32Vector4Type;
-            }
-            // fall through
-        default:
-            ABORT("unsupported type");
-    }
-}
-
-void JIT::setBlock(LLVMBuilderRef builder, LLVMBasicBlockRef block) {
-    fCurrentBlock = block;
-    LLVMPositionBuilderAtEnd(builder, block);
-}
-
-std::unique_ptr<JIT::LValue> JIT::getLValue(LLVMBuilderRef builder, const Expression& expr) {
-    switch (expr.fKind) {
-        case Expression::kVariableReference_Kind: {
-            class PointerLValue : public LValue {
-            public:
-                PointerLValue(LLVMValueRef ptr)
-                : fPointer(ptr) {}
-
-                LLVMValueRef load(LLVMBuilderRef builder) override {
-                    return LLVMBuildLoad(builder, fPointer, "lvalue load");
-                }
-
-                void store(LLVMBuilderRef builder, LLVMValueRef value) override {
-                    LLVMBuildStore(builder, value, fPointer);
-                }
-
-            private:
-                LLVMValueRef fPointer;
-            };
-            const Variable* var = &((VariableReference&) expr).fVariable;
-            if (var->fStorage == Variable::kParameter_Storage &&
-                !(var->fModifiers.fFlags & Modifiers::kOut_Flag) &&
-                fPromotedParameters.find(var) == fPromotedParameters.end()) {
-                // promote parameter to variable
-                fPromotedParameters.insert(var);
-                LLVMPositionBuilderAtEnd(builder, fAllocaBlock);
-                LLVMValueRef alloca = LLVMBuildAlloca(builder, this->getType(var->fType),
-                                                      String(var->fName).c_str());
-                LLVMBuildStore(builder, fVariables[var], alloca);
-                LLVMPositionBuilderAtEnd(builder, fCurrentBlock);
-                fVariables[var] = alloca;
-            }
-            LLVMValueRef ptr = fVariables[var];
-            return std::unique_ptr<LValue>(new PointerLValue(ptr));
-        }
-        case Expression::kTernary_Kind: {
-            class TernaryLValue : public LValue {
-            public:
-                TernaryLValue(JIT* jit, LLVMValueRef test, std::unique_ptr<LValue> ifTrue,
-                              std::unique_ptr<LValue> ifFalse)
-                : fJIT(*jit)
-                , fTest(test)
-                , fIfTrue(std::move(ifTrue))
-                , fIfFalse(std::move(ifFalse)) {}
-
-                LLVMValueRef load(LLVMBuilderRef builder) override {
-                    LLVMBasicBlockRef trueBlock = LLVMAppendBasicBlockInContext(
-                                                                              fJIT.fContext,
-                                                                              fJIT.fCurrentFunction,
-                                                                              "true ? ...");
-                    LLVMBasicBlockRef falseBlock = LLVMAppendBasicBlockInContext(
-                                                                              fJIT.fContext,
-                                                                              fJIT.fCurrentFunction,
-                                                                              "false ? ...");
-                    LLVMBasicBlockRef merge = LLVMAppendBasicBlockInContext(fJIT.fContext,
-                                                                            fJIT.fCurrentFunction,
-                                                                            "ternary merge");
-                    LLVMBuildCondBr(builder, fTest, trueBlock, falseBlock);
-                    fJIT.setBlock(builder, trueBlock);
-                    LLVMValueRef ifTrue = fIfTrue->load(builder);
-                    LLVMBuildBr(builder, merge);
-                    fJIT.setBlock(builder, falseBlock);
-                    LLVMValueRef ifFalse = fIfTrue->load(builder);
-                    LLVMBuildBr(builder, merge);
-                    fJIT.setBlock(builder, merge);
-                    LLVMTypeRef type = LLVMPointerType(LLVMTypeOf(ifTrue), 0);
-                    LLVMValueRef phi = LLVMBuildPhi(builder, type, "?");
-                    LLVMValueRef incomingValues[2] = { ifTrue, ifFalse };
-                    LLVMBasicBlockRef incomingBlocks[2] = { trueBlock, falseBlock };
-                    LLVMAddIncoming(phi, incomingValues, incomingBlocks, 2);
-                    return phi;
-                }
-
-                void store(LLVMBuilderRef builder, LLVMValueRef value) override {
-                    LLVMBasicBlockRef trueBlock = LLVMAppendBasicBlockInContext(
-                                                                              fJIT.fContext,
-                                                                              fJIT.fCurrentFunction,
-                                                                              "true ? ...");
-                    LLVMBasicBlockRef falseBlock = LLVMAppendBasicBlockInContext(
-                                                                              fJIT.fContext,
-                                                                              fJIT.fCurrentFunction,
-                                                                              "false ? ...");
-                    LLVMBasicBlockRef merge = LLVMAppendBasicBlockInContext(fJIT.fContext,
-                                                                            fJIT.fCurrentFunction,
-                                                                            "ternary merge");
-                    LLVMBuildCondBr(builder, fTest, trueBlock, falseBlock);
-                    fJIT.setBlock(builder, trueBlock);
-                    fIfTrue->store(builder, value);
-                    LLVMBuildBr(builder, merge);
-                    fJIT.setBlock(builder, falseBlock);
-                    fIfTrue->store(builder, value);
-                    LLVMBuildBr(builder, merge);
-                    fJIT.setBlock(builder, merge);
-                }
-
-            private:
-                JIT& fJIT;
-                LLVMValueRef fTest;
-                std::unique_ptr<LValue> fIfTrue;
-                std::unique_ptr<LValue> fIfFalse;
-            };
-            const TernaryExpression& t = (const TernaryExpression&) expr;
-            LLVMValueRef test = this->compileExpression(builder, *t.fTest);
-            return std::unique_ptr<LValue>(new TernaryLValue(this,
-                                                             test,
-                                                             this->getLValue(builder,
-                                                                             *t.fIfTrue),
-                                                             this->getLValue(builder,
-                                                                             *t.fIfFalse)));
-        }
-        case Expression::kSwizzle_Kind: {
-            class SwizzleLValue : public LValue {
-            public:
-                SwizzleLValue(JIT* jit, LLVMTypeRef type, std::unique_ptr<LValue> base,
-                              std::vector<int> components)
-                : fJIT(*jit)
-                , fType(type)
-                , fBase(std::move(base))
-                , fComponents(components) {}
-
-                LLVMValueRef load(LLVMBuilderRef builder) override {
-                    LLVMValueRef base = fBase->load(builder);
-                    if (fComponents.size() > 1) {
-                        LLVMValueRef result = LLVMGetUndef(fType);
-                        for (size_t i = 0; i < fComponents.size(); ++i) {
-                            LLVMValueRef element = LLVMBuildExtractElement(
-                                                                       builder,
-                                                                       base,
-                                                                       LLVMConstInt(fJIT.fInt32Type,
-                                                                                    fComponents[i],
-                                                                                    false),
-                                                                       "swizzle extract");
-                            result = LLVMBuildInsertElement(builder, result, element,
-                                                            LLVMConstInt(fJIT.fInt32Type, i, false),
-                                                            "swizzle insert");
-                        }
-                        return result;
-                    }
-                    SkASSERT(fComponents.size() == 1);
-                    return LLVMBuildExtractElement(builder, base,
-                                                            LLVMConstInt(fJIT.fInt32Type,
-                                                                         fComponents[0],
-                                                                         false),
-                                                            "swizzle extract");
-                }
-
-                void store(LLVMBuilderRef builder, LLVMValueRef value) override {
-                    LLVMValueRef result = fBase->load(builder);
-                    if (fComponents.size() > 1) {
-                        for (size_t i = 0; i < fComponents.size(); ++i) {
-                            LLVMValueRef element = LLVMBuildExtractElement(builder, value,
-                                                                           LLVMConstInt(
-                                                                                    fJIT.fInt32Type,
-                                                                                    i,
-                                                                                    false),
-                                                                           "swizzle extract");
-                            result = LLVMBuildInsertElement(builder, result, element,
-                                                            LLVMConstInt(fJIT.fInt32Type,
-                                                                         fComponents[i],
-                                                                         false),
-                                                            "swizzle insert");
-                        }
-                    } else {
-                        result = LLVMBuildInsertElement(builder, result, value,
-                                                        LLVMConstInt(fJIT.fInt32Type,
-                                                                     fComponents[0],
-                                                                     false),
-                                                        "swizzle insert");
-                    }
-                    fBase->store(builder, result);
-                }
-
-            private:
-                JIT& fJIT;
-                LLVMTypeRef fType;
-                std::unique_ptr<LValue> fBase;
-                std::vector<int> fComponents;
-            };
-            const Swizzle& s = (const Swizzle&) expr;
-            return std::unique_ptr<LValue>(new SwizzleLValue(this, this->getType(s.fType),
-                                                             this->getLValue(builder, *s.fBase),
-                                                             s.fComponents));
-        }
-        default:
-            ABORT("unsupported lvalue");
-    }
-}
-
-JIT::TypeKind JIT::typeKind(const Type& type) {
-    if (type.kind() == Type::kVector_Kind) {
-        return this->typeKind(type.componentType());
-    }
-    if (type.fName == "int" || type.fName == "short" || type.fName == "byte") {
-        return JIT::kInt_TypeKind;
-    } else if (type.fName == "uint" || type.fName == "ushort" || type.fName == "ubyte") {
-        return JIT::kUInt_TypeKind;
-    } else if (type.fName == "float" || type.fName == "double" || type.fName == "half") {
-        return JIT::kFloat_TypeKind;
-    }
-    ABORT("unsupported type: %s\n", type.description().c_str());
-}
-
-void JIT::vectorize(LLVMBuilderRef builder, LLVMValueRef* value, int columns) {
-    LLVMValueRef result = LLVMGetUndef(LLVMVectorType(LLVMTypeOf(*value), columns));
-    for (int i = 0; i < columns; ++i) {
-        result = LLVMBuildInsertElement(builder,
-                                        result,
-                                        *value,
-                                        LLVMConstInt(fInt32Type, i, false),
-                                        "vectorize");
-    }
-    *value = result;
-}
-
-void JIT::vectorize(LLVMBuilderRef builder, const BinaryExpression& b, LLVMValueRef* left,
-                    LLVMValueRef* right) {
-    if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
-        b.fRight->fType.kind() == Type::kVector_Kind) {
-        this->vectorize(builder, left, b.fRight->fType.columns());
-    } else if (b.fLeft->fType.kind() == Type::kVector_Kind &&
-               b.fRight->fType.kind() == Type::kScalar_Kind) {
-        this->vectorize(builder, right, b.fLeft->fType.columns());
-    }
-}
-
-
-LLVMValueRef JIT::compileBinary(LLVMBuilderRef builder, const BinaryExpression& b) {
-    #define BINARY(SFunc, UFunc, FFunc) {                                    \
-        LLVMValueRef left = this->compileExpression(builder, *b.fLeft);      \
-        LLVMValueRef right = this->compileExpression(builder, *b.fRight);    \
-        this->vectorize(builder, b, &left, &right);                          \
-        switch (this->typeKind(b.fLeft->fType)) {                            \
-            case kInt_TypeKind:                                              \
-                return SFunc(builder, left, right, "binary");                \
-            case kUInt_TypeKind:                                             \
-                return UFunc(builder, left, right, "binary");                \
-            case kFloat_TypeKind:                                            \
-                return FFunc(builder, left, right, "binary");                \
-            default:                                                         \
-                ABORT("unsupported typeKind");                               \
-        }                                                                    \
-    }
-    #define COMPOUND(SFunc, UFunc, FFunc) {                                  \
-        std::unique_ptr<LValue> lvalue = this->getLValue(builder, *b.fLeft); \
-        LLVMValueRef left = lvalue->load(builder);                           \
-        LLVMValueRef right = this->compileExpression(builder, *b.fRight);    \
-        this->vectorize(builder, b, &left, &right);                          \
-        LLVMValueRef result;                                                 \
-        switch (this->typeKind(b.fLeft->fType)) {                            \
-            case kInt_TypeKind:                                              \
-                result = SFunc(builder, left, right, "binary");              \
-                break;                                                       \
-            case kUInt_TypeKind:                                             \
-                result = UFunc(builder, left, right, "binary");              \
-                break;                                                       \
-            case kFloat_TypeKind:                                            \
-                result = FFunc(builder, left, right, "binary");              \
-                break;                                                       \
-            default:                                                         \
-                ABORT("unsupported typeKind");                               \
-        }                                                                    \
-        lvalue->store(builder, result);                                      \
-        return result;                                                       \
-    }
-    #define COMPARE(SFunc, SOp, UFunc, UOp, FFunc, FOp) {                    \
-        LLVMValueRef left = this->compileExpression(builder, *b.fLeft);      \
-        LLVMValueRef right = this->compileExpression(builder, *b.fRight);    \
-        this->vectorize(builder, b, &left, &right);                          \
-        switch (this->typeKind(b.fLeft->fType)) {                            \
-            case kInt_TypeKind:                                              \
-                return SFunc(builder, SOp, left, right, "binary");           \
-            case kUInt_TypeKind:                                             \
-                return UFunc(builder, UOp, left, right, "binary");           \
-            case kFloat_TypeKind:                                            \
-                return FFunc(builder, FOp, left, right, "binary");           \
-            default:                                                         \
-                ABORT("unsupported typeKind");                               \
-        }                                                                    \
-    }
-    switch (b.fOperator) {
-        case Token::EQ: {
-            std::unique_ptr<LValue> lvalue = this->getLValue(builder, *b.fLeft);
-            LLVMValueRef result = this->compileExpression(builder, *b.fRight);
-            lvalue->store(builder, result);
-            return result;
-        }
-        case Token::PLUS:
-            BINARY(LLVMBuildAdd, LLVMBuildAdd, LLVMBuildFAdd);
-        case Token::MINUS:
-            BINARY(LLVMBuildSub, LLVMBuildSub, LLVMBuildFSub);
-        case Token::STAR:
-            BINARY(LLVMBuildMul, LLVMBuildMul, LLVMBuildFMul);
-        case Token::SLASH:
-            BINARY(LLVMBuildSDiv, LLVMBuildUDiv, LLVMBuildFDiv);
-        case Token::PERCENT:
-            BINARY(LLVMBuildSRem, LLVMBuildURem, LLVMBuildSRem);
-        case Token::BITWISEAND:
-            BINARY(LLVMBuildAnd, LLVMBuildAnd, LLVMBuildAnd);
-        case Token::BITWISEOR:
-            BINARY(LLVMBuildOr, LLVMBuildOr, LLVMBuildOr);
-        case Token::SHL:
-            BINARY(LLVMBuildShl, LLVMBuildShl, LLVMBuildShl);
-        case Token::SHR:
-            BINARY(LLVMBuildAShr, LLVMBuildLShr, LLVMBuildAShr);
-        case Token::PLUSEQ:
-            COMPOUND(LLVMBuildAdd, LLVMBuildAdd, LLVMBuildFAdd);
-        case Token::MINUSEQ:
-            COMPOUND(LLVMBuildSub, LLVMBuildSub, LLVMBuildFSub);
-        case Token::STAREQ:
-            COMPOUND(LLVMBuildMul, LLVMBuildMul, LLVMBuildFMul);
-        case Token::SLASHEQ:
-            COMPOUND(LLVMBuildSDiv, LLVMBuildUDiv, LLVMBuildFDiv);
-        case Token::BITWISEANDEQ:
-            COMPOUND(LLVMBuildAnd, LLVMBuildAnd, LLVMBuildAnd);
-        case Token::BITWISEOREQ:
-            COMPOUND(LLVMBuildOr, LLVMBuildOr, LLVMBuildOr);
-        case Token::EQEQ:
-            switch (b.fLeft->fType.kind()) {
-                case Type::kScalar_Kind:
-                    COMPARE(LLVMBuildICmp, LLVMIntEQ,
-                            LLVMBuildICmp, LLVMIntEQ,
-                            LLVMBuildFCmp, LLVMRealOEQ);
-                case Type::kVector_Kind: {
-                    LLVMValueRef left = this->compileExpression(builder, *b.fLeft);
-                    LLVMValueRef right = this->compileExpression(builder, *b.fRight);
-                    this->vectorize(builder, b, &left, &right);
-                    LLVMValueRef value;
-                    switch (this->typeKind(b.fLeft->fType)) {
-                        case kInt_TypeKind:
-                            value = LLVMBuildICmp(builder, LLVMIntEQ, left, right, "binary");
-                            break;
-                        case kUInt_TypeKind:
-                            value = LLVMBuildICmp(builder, LLVMIntEQ, left, right, "binary");
-                            break;
-                        case kFloat_TypeKind:
-                            value = LLVMBuildFCmp(builder, LLVMRealOEQ, left, right, "binary");
-                            break;
-                        default:
-                            ABORT("unsupported typeKind");
-                    }
-                    LLVMValueRef args[1] = { value };
-                    LLVMValueRef func;
-                    switch (b.fLeft->fType.columns()) {
-                        case 2: func = fFoldAnd2Func; break;
-                        case 3: func = fFoldAnd3Func; break;
-                        case 4: func = fFoldAnd4Func; break;
-                        default:
-                            SkASSERT(false);
-                            func = fFoldAnd2Func;
-                    }
-                    return LLVMBuildCall(builder, func, args, 1, "all");
-                }
-                default:
-                    SkASSERT(false);
-            }
-        case Token::NEQ:
-            switch (b.fLeft->fType.kind()) {
-                case Type::kScalar_Kind:
-                    COMPARE(LLVMBuildICmp, LLVMIntNE,
-                            LLVMBuildICmp, LLVMIntNE,
-                            LLVMBuildFCmp, LLVMRealONE);
-                case Type::kVector_Kind: {
-                    LLVMValueRef left = this->compileExpression(builder, *b.fLeft);
-                    LLVMValueRef right = this->compileExpression(builder, *b.fRight);
-                    this->vectorize(builder, b, &left, &right);
-                    LLVMValueRef value;
-                    switch (this->typeKind(b.fLeft->fType)) {
-                        case kInt_TypeKind:
-                            value = LLVMBuildICmp(builder, LLVMIntNE, left, right, "binary");
-                            break;
-                        case kUInt_TypeKind:
-                            value = LLVMBuildICmp(builder, LLVMIntNE, left, right, "binary");
-                            break;
-                        case kFloat_TypeKind:
-                            value = LLVMBuildFCmp(builder, LLVMRealONE, left, right, "binary");
-                            break;
-                        default:
-                            ABORT("unsupported typeKind");
-                    }
-                    LLVMValueRef args[1] = { value };
-                    LLVMValueRef func;
-                    switch (b.fLeft->fType.columns()) {
-                        case 2: func = fFoldOr2Func; break;
-                        case 3: func = fFoldOr3Func; break;
-                        case 4: func = fFoldOr4Func; break;
-                        default:
-                            SkASSERT(false);
-                            func = fFoldOr2Func;
-                    }
-                    return LLVMBuildCall(builder, func, args, 1, "all");
-                }
-                default:
-                    SkASSERT(false);
-            }
-        case Token::LT:
-            COMPARE(LLVMBuildICmp, LLVMIntSLT,
-                    LLVMBuildICmp, LLVMIntULT,
-                    LLVMBuildFCmp, LLVMRealOLT);
-        case Token::LTEQ:
-            COMPARE(LLVMBuildICmp, LLVMIntSLE,
-                    LLVMBuildICmp, LLVMIntULE,
-                    LLVMBuildFCmp, LLVMRealOLE);
-        case Token::GT:
-            COMPARE(LLVMBuildICmp, LLVMIntSGT,
-                    LLVMBuildICmp, LLVMIntUGT,
-                    LLVMBuildFCmp, LLVMRealOGT);
-        case Token::GTEQ:
-            COMPARE(LLVMBuildICmp, LLVMIntSGE,
-                    LLVMBuildICmp, LLVMIntUGE,
-                    LLVMBuildFCmp, LLVMRealOGE);
-        case Token::LOGICALAND: {
-            LLVMValueRef left = this->compileExpression(builder, *b.fLeft);
-            LLVMBasicBlockRef ifFalse = fCurrentBlock;
-            LLVMBasicBlockRef ifTrue = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                     "true && ...");
-            LLVMBasicBlockRef merge = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                    "&& merge");
-            LLVMBuildCondBr(builder, left, ifTrue, merge);
-            this->setBlock(builder, ifTrue);
-            LLVMValueRef right = this->compileExpression(builder, *b.fRight);
-            LLVMBuildBr(builder, merge);
-            this->setBlock(builder, merge);
-            LLVMValueRef phi = LLVMBuildPhi(builder, fInt1Type, "&&");
-            LLVMValueRef incomingValues[2] = { right, LLVMConstInt(fInt1Type, 0, false) };
-            LLVMBasicBlockRef incomingBlocks[2] = { ifTrue, ifFalse };
-            LLVMAddIncoming(phi, incomingValues, incomingBlocks, 2);
-            return phi;
-        }
-        case Token::LOGICALOR: {
-            LLVMValueRef left = this->compileExpression(builder, *b.fLeft);
-            LLVMBasicBlockRef ifTrue = fCurrentBlock;
-            LLVMBasicBlockRef ifFalse = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                      "false || ...");
-            LLVMBasicBlockRef merge = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                    "|| merge");
-            LLVMBuildCondBr(builder, left, merge, ifFalse);
-            this->setBlock(builder, ifFalse);
-            LLVMValueRef right = this->compileExpression(builder, *b.fRight);
-            LLVMBuildBr(builder, merge);
-            this->setBlock(builder, merge);
-            LLVMValueRef phi = LLVMBuildPhi(builder, fInt1Type, "||");
-            LLVMValueRef incomingValues[2] = { right, LLVMConstInt(fInt1Type, 1, false) };
-            LLVMBasicBlockRef incomingBlocks[2] = { ifFalse, ifTrue };
-            LLVMAddIncoming(phi, incomingValues, incomingBlocks, 2);
-            return phi;
-        }
-        default:
-            printf("%s\n", b.description().c_str());
-            ABORT("unsupported binary operator");
-    }
-}
-
-LLVMValueRef JIT::compileIndex(LLVMBuilderRef builder, const IndexExpression& idx) {
-    LLVMValueRef base = this->compileExpression(builder, *idx.fBase);
-    LLVMValueRef index = this->compileExpression(builder, *idx.fIndex);
-    LLVMValueRef ptr = LLVMBuildGEP(builder, base, &index, 1, "index ptr");
-    return LLVMBuildLoad(builder, ptr, "index load");
-}
-
-LLVMValueRef JIT::compilePostfix(LLVMBuilderRef builder, const PostfixExpression& p) {
-    std::unique_ptr<LValue> lvalue = this->getLValue(builder, *p.fOperand);
-    LLVMValueRef result = lvalue->load(builder);
-    LLVMValueRef mod;
-    LLVMValueRef one = LLVMConstInt(this->getType(p.fType), 1, false);
-    switch (p.fOperator) {
-        case Token::PLUSPLUS:
-            switch (this->typeKind(p.fType)) {
-                case kInt_TypeKind: // fall through
-                case kUInt_TypeKind:
-                    mod = LLVMBuildAdd(builder, result, one, "++");
-                    break;
-                case kFloat_TypeKind:
-                    mod = LLVMBuildFAdd(builder, result, one, "++");
-                    break;
-                default:
-                    ABORT("unsupported typeKind");
-            }
-            break;
-        case Token::MINUSMINUS:
-            switch (this->typeKind(p.fType)) {
-                case kInt_TypeKind: // fall through
-                case kUInt_TypeKind:
-                    mod = LLVMBuildSub(builder, result, one, "--");
-                    break;
-                case kFloat_TypeKind:
-                    mod = LLVMBuildFSub(builder, result, one, "--");
-                    break;
-                default:
-                    ABORT("unsupported typeKind");
-            }
-            break;
-        default:
-            ABORT("unsupported postfix op");
-    }
-    lvalue->store(builder, mod);
-    return result;
-}
-
-LLVMValueRef JIT::compilePrefix(LLVMBuilderRef builder, const PrefixExpression& p) {
-    LLVMValueRef one = LLVMConstInt(this->getType(p.fType), 1, false);
-    if (Token::LOGICALNOT == p.fOperator) {
-        LLVMValueRef base = this->compileExpression(builder, *p.fOperand);
-        return LLVMBuildXor(builder, base, one, "!");
-    }
-    if (Token::MINUS == p.fOperator) {
-        LLVMValueRef base = this->compileExpression(builder, *p.fOperand);
-        return LLVMBuildSub(builder, LLVMConstInt(this->getType(p.fType), 0, false), base, "-");
-    }
-    std::unique_ptr<LValue> lvalue = this->getLValue(builder, *p.fOperand);
-    LLVMValueRef raw = lvalue->load(builder);
-    LLVMValueRef result;
-    switch (p.fOperator) {
-        case Token::PLUSPLUS:
-            switch (this->typeKind(p.fType)) {
-                case kInt_TypeKind: // fall through
-                case kUInt_TypeKind:
-                    result = LLVMBuildAdd(builder, raw, one, "++");
-                    break;
-                case kFloat_TypeKind:
-                    result = LLVMBuildFAdd(builder, raw, one, "++");
-                    break;
-                default:
-                    ABORT("unsupported typeKind");
-            }
-            break;
-        case Token::MINUSMINUS:
-            switch (this->typeKind(p.fType)) {
-                case kInt_TypeKind: // fall through
-                case kUInt_TypeKind:
-                    result = LLVMBuildSub(builder, raw, one, "--");
-                    break;
-                case kFloat_TypeKind:
-                    result = LLVMBuildFSub(builder, raw, one, "--");
-                    break;
-                default:
-                    ABORT("unsupported typeKind");
-            }
-            break;
-        default:
-            ABORT("unsupported prefix op");
-    }
-    lvalue->store(builder, result);
-    return result;
-}
-
-LLVMValueRef JIT::compileVariableReference(LLVMBuilderRef builder, const VariableReference& v) {
-    const Variable& var = v.fVariable;
-    if (Variable::kParameter_Storage == var.fStorage &&
-        !(var.fModifiers.fFlags & Modifiers::kOut_Flag) &&
-        fPromotedParameters.find(&var) == fPromotedParameters.end()) {
-        return fVariables[&var];
-    }
-    return LLVMBuildLoad(builder, fVariables[&var], String(var.fName).c_str());
-}
-
-void JIT::appendStage(LLVMBuilderRef builder, const AppendStage& a) {
-    SkASSERT(a.fArguments.size() >= 1);
-    SkASSERT(a.fArguments[0]->fType == *fCompiler.context().fSkRasterPipeline_Type);
-    LLVMValueRef pipeline = this->compileExpression(builder, *a.fArguments[0]);
-    LLVMValueRef stage = LLVMConstInt(fInt32Type, a.fStage, 0);
-    switch (a.fStage) {
-        case SkRasterPipeline::callback: {
-            SkASSERT(a.fArguments.size() == 2);
-            SkASSERT(a.fArguments[1]->fKind == Expression::kFunctionReference_Kind);
-            const FunctionDeclaration& functionDecl =
-                                             *((FunctionReference&) *a.fArguments[1]).fFunctions[0];
-            bool found = false;
-            for (const auto& pe : *fProgram) {
-                if (ProgramElement::kFunction_Kind == pe.fKind) {
-                    const FunctionDefinition& def = (const FunctionDefinition&) pe;
-                    if (&def.fDeclaration == &functionDecl) {
-                        LLVMValueRef fn = this->compileStageFunction(def);
-                        LLVMValueRef args[2] = {
-                            pipeline,
-                            LLVMBuildBitCast(builder, fn, fInt8PtrType, "callback cast")
-                        };
-                        LLVMBuildCall(builder, fAppendCallbackFunc, args, 2, "");
-                        found = true;
-                        break;
-                    }
-                }
-            }
-            SkASSERT(found);
-            break;
-        }
-        default: {
-            LLVMValueRef ctx;
-            if (a.fArguments.size() == 2) {
-                ctx = this->compileExpression(builder, *a.fArguments[1]);
-                ctx = LLVMBuildBitCast(builder, ctx, fInt8PtrType, "context cast");
-            } else {
-                SkASSERT(a.fArguments.size() == 1);
-                ctx = LLVMConstNull(fInt8PtrType);
-            }
-            LLVMValueRef args[3] = {
-                pipeline,
-                stage,
-                ctx
-            };
-            LLVMBuildCall(builder, fAppendFunc, args, 3, "");
-            break;
-        }
-    }
-}
-
-LLVMValueRef JIT::compileConstructor(LLVMBuilderRef builder, const Constructor& c) {
-    switch (c.fType.kind()) {
-        case Type::kScalar_Kind: {
-            SkASSERT(c.fArguments.size() == 1);
-            TypeKind from = this->typeKind(c.fArguments[0]->fType);
-            TypeKind to = this->typeKind(c.fType);
-            LLVMValueRef base = this->compileExpression(builder, *c.fArguments[0]);
-            switch (to) {
-                case kFloat_TypeKind:
-                    switch (from) {
-                        case kInt_TypeKind:
-                            return LLVMBuildSIToFP(builder, base, this->getType(c.fType), "cast");
-                        case kUInt_TypeKind:
-                            return LLVMBuildUIToFP(builder, base, this->getType(c.fType), "cast");
-                        case kFloat_TypeKind:
-                            return base;
-                        case kBool_TypeKind:
-                            SkASSERT(false);
-                    }
-                case kInt_TypeKind:
-                    switch (from) {
-                        case kInt_TypeKind:
-                            return base;
-                        case kUInt_TypeKind:
-                            return base;
-                        case kFloat_TypeKind:
-                            return LLVMBuildFPToSI(builder, base, this->getType(c.fType), "cast");
-                        case kBool_TypeKind:
-                            SkASSERT(false);
-                    }
-                case kUInt_TypeKind:
-                    switch (from) {
-                        case kInt_TypeKind:
-                            return base;
-                        case kUInt_TypeKind:
-                            return base;
-                        case kFloat_TypeKind:
-                            return LLVMBuildFPToUI(builder, base, this->getType(c.fType), "cast");
-                        case kBool_TypeKind:
-                            SkASSERT(false);
-                    }
-                case kBool_TypeKind:
-                    SkASSERT(false);
-            }
-        }
-        case Type::kVector_Kind: {
-            LLVMValueRef vec = LLVMGetUndef(this->getType(c.fType));
-            if (c.fArguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) {
-                LLVMValueRef value = this->compileExpression(builder, *c.fArguments[0]);
-                for (int i = 0; i < c.fType.columns(); ++i) {
-                    vec = LLVMBuildInsertElement(builder, vec, value,
-                                                 LLVMConstInt(fInt32Type, i, false),
-                                                 "vec build 1");
-                }
-            } else {
-                int index = 0;
-                for (const auto& arg : c.fArguments) {
-                    LLVMValueRef value = this->compileExpression(builder, *arg);
-                    if (arg->fType.kind() == Type::kVector_Kind) {
-                        for (int i = 0; i < arg->fType.columns(); ++i) {
-                            LLVMValueRef column = LLVMBuildExtractElement(builder,
-                                                                          vec,
-                                                                          LLVMConstInt(fInt32Type,
-                                                                                       i,
-                                                                                       false),
-                                                                          "construct extract");
-                            vec = LLVMBuildInsertElement(builder, vec, column,
-                                                         LLVMConstInt(fInt32Type, index++, false),
-                                                         "vec build 2");
-                        }
-                    } else {
-                        vec = LLVMBuildInsertElement(builder, vec, value,
-                                                     LLVMConstInt(fInt32Type, index++, false),
-                                                     "vec build 3");
-                    }
-                }
-            }
-            return vec;
-        }
-        default:
-            break;
-    }
-    ABORT("unsupported constructor");
-}
-
-LLVMValueRef JIT::compileSwizzle(LLVMBuilderRef builder, const Swizzle& s) {
-    LLVMValueRef base = this->compileExpression(builder, *s.fBase);
-    if (s.fComponents.size() > 1) {
-        LLVMValueRef result = LLVMGetUndef(this->getType(s.fType));
-        for (size_t i = 0; i < s.fComponents.size(); ++i) {
-            LLVMValueRef element = LLVMBuildExtractElement(
-                                                       builder,
-                                                       base,
-                                                       LLVMConstInt(fInt32Type,
-                                                                    s.fComponents[i],
-                                                                    false),
-                                                       "swizzle extract");
-            result = LLVMBuildInsertElement(builder, result, element,
-                                            LLVMConstInt(fInt32Type, i, false),
-                                            "swizzle insert");
-        }
-        return result;
-    }
-    SkASSERT(s.fComponents.size() == 1);
-    return LLVMBuildExtractElement(builder, base,
-                                            LLVMConstInt(fInt32Type,
-                                                         s.fComponents[0],
-                                                         false),
-                                            "swizzle extract");
-}
-
-LLVMValueRef JIT::compileTernary(LLVMBuilderRef builder, const TernaryExpression& t) {
-    LLVMValueRef test = this->compileExpression(builder, *t.fTest);
-    LLVMBasicBlockRef trueBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                "if true");
-    LLVMBasicBlockRef merge = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                            "if merge");
-    LLVMBasicBlockRef falseBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                 "if false");
-    LLVMBuildCondBr(builder, test, trueBlock, falseBlock);
-    this->setBlock(builder, trueBlock);
-    LLVMValueRef ifTrue = this->compileExpression(builder, *t.fIfTrue);
-    trueBlock = fCurrentBlock;
-    LLVMBuildBr(builder, merge);
-    this->setBlock(builder, falseBlock);
-    LLVMValueRef ifFalse = this->compileExpression(builder, *t.fIfFalse);
-    falseBlock = fCurrentBlock;
-    LLVMBuildBr(builder, merge);
-    this->setBlock(builder, merge);
-    LLVMValueRef phi = LLVMBuildPhi(builder, this->getType(t.fType), "?");
-    LLVMValueRef incomingValues[2] = { ifTrue, ifFalse };
-    LLVMBasicBlockRef incomingBlocks[2] = { trueBlock, falseBlock };
-    LLVMAddIncoming(phi, incomingValues, incomingBlocks, 2);
-    return phi;
-}
-
-LLVMValueRef JIT::compileExpression(LLVMBuilderRef builder, const Expression& expr) {
-    switch (expr.fKind) {
-        case Expression::kAppendStage_Kind: {
-            this->appendStage(builder, (const AppendStage&) expr);
-            return LLVMValueRef();
-        }
-        case Expression::kBinary_Kind:
-            return this->compileBinary(builder, (BinaryExpression&) expr);
-        case Expression::kBoolLiteral_Kind:
-            return LLVMConstInt(fInt1Type, ((BoolLiteral&) expr).fValue, false);
-        case Expression::kConstructor_Kind:
-            return this->compileConstructor(builder, (Constructor&) expr);
-        case Expression::kIntLiteral_Kind:
-            return LLVMConstInt(this->getType(expr.fType), ((IntLiteral&) expr).fValue, true);
-        case Expression::kFieldAccess_Kind:
-            abort();
-        case Expression::kFloatLiteral_Kind:
-            return LLVMConstReal(this->getType(expr.fType), ((FloatLiteral&) expr).fValue);
-        case Expression::kFunctionCall_Kind:
-            return this->compileFunctionCall(builder, (FunctionCall&) expr);
-        case Expression::kIndex_Kind:
-            return this->compileIndex(builder, (IndexExpression&) expr);
-        case Expression::kPrefix_Kind:
-            return this->compilePrefix(builder, (PrefixExpression&) expr);
-        case Expression::kPostfix_Kind:
-            return this->compilePostfix(builder, (PostfixExpression&) expr);
-        case Expression::kSetting_Kind:
-            abort();
-        case Expression::kSwizzle_Kind:
-            return this->compileSwizzle(builder, (Swizzle&) expr);
-        case Expression::kVariableReference_Kind:
-            return this->compileVariableReference(builder, (VariableReference&) expr);
-        case Expression::kTernary_Kind:
-            return this->compileTernary(builder, (TernaryExpression&) expr);
-        case Expression::kTypeReference_Kind:
-            abort();
-        default:
-            abort();
-    }
-    ABORT("unsupported expression: %s\n", expr.description().c_str());
-}
-
-void JIT::compileBlock(LLVMBuilderRef builder, const Block& block) {
-    for (const auto& stmt : block.fStatements) {
-        this->compileStatement(builder, *stmt);
-    }
-}
-
-void JIT::compileVarDeclarations(LLVMBuilderRef builder, const VarDeclarationsStatement& decls) {
-    for (const auto& declStatement : decls.fDeclaration->fVars) {
-        const VarDeclaration& decl = (VarDeclaration&) *declStatement;
-        LLVMPositionBuilderAtEnd(builder, fAllocaBlock);
-        LLVMValueRef alloca = LLVMBuildAlloca(builder, this->getType(decl.fVar->fType),
-                                              String(decl.fVar->fName).c_str());
-        fVariables[decl.fVar] = alloca;
-        LLVMPositionBuilderAtEnd(builder, fCurrentBlock);
-        if (decl.fValue) {
-            LLVMValueRef result = this->compileExpression(builder, *decl.fValue);
-            LLVMBuildStore(builder, result, alloca);
-        }
-    }
-}
-
-void JIT::compileIf(LLVMBuilderRef builder, const IfStatement& i) {
-    LLVMValueRef test = this->compileExpression(builder, *i.fTest);
-    LLVMBasicBlockRef ifTrue = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "if true");
-    LLVMBasicBlockRef merge = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                              "if merge");
-    LLVMBasicBlockRef ifFalse;
-    if (i.fIfFalse) {
-        ifFalse = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "if false");
-    } else {
-        ifFalse = merge;
-    }
-    LLVMBuildCondBr(builder, test, ifTrue, ifFalse);
-    this->setBlock(builder, ifTrue);
-    this->compileStatement(builder, *i.fIfTrue);
-    if (!ends_with_branch(*i.fIfTrue)) {
-        LLVMBuildBr(builder, merge);
-    }
-    if (i.fIfFalse) {
-        this->setBlock(builder, ifFalse);
-        this->compileStatement(builder, *i.fIfFalse);
-        if (!ends_with_branch(*i.fIfFalse)) {
-            LLVMBuildBr(builder, merge);
-        }
-    }
-    this->setBlock(builder, merge);
-}
-
-void JIT::compileFor(LLVMBuilderRef builder, const ForStatement& f) {
-    if (f.fInitializer) {
-        this->compileStatement(builder, *f.fInitializer);
-    }
-    LLVMBasicBlockRef start;
-    LLVMBasicBlockRef body = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "for body");
-    LLVMBasicBlockRef next = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "for next");
-    LLVMBasicBlockRef end = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "for end");
-    if (f.fTest) {
-        start = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "for test");
-        LLVMBuildBr(builder, start);
-        this->setBlock(builder, start);
-        LLVMValueRef test = this->compileExpression(builder, *f.fTest);
-        LLVMBuildCondBr(builder, test, body, end);
-    } else {
-        start = body;
-        LLVMBuildBr(builder, body);
-    }
-    this->setBlock(builder, body);
-    fBreakTarget.push_back(end);
-    fContinueTarget.push_back(next);
-    this->compileStatement(builder, *f.fStatement);
-    fBreakTarget.pop_back();
-    fContinueTarget.pop_back();
-    if (!ends_with_branch(*f.fStatement)) {
-        LLVMBuildBr(builder, next);
-    }
-    this->setBlock(builder, next);
-    if (f.fNext) {
-        this->compileExpression(builder, *f.fNext);
-    }
-    LLVMBuildBr(builder, start);
-    this->setBlock(builder, end);
-}
-
-void JIT::compileDo(LLVMBuilderRef builder, const DoStatement& d) {
-    LLVMBasicBlockRef testBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                                "do test");
-    LLVMBasicBlockRef body = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                           "do body");
-    LLVMBasicBlockRef end = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                          "do end");
-    LLVMBuildBr(builder, body);
-    this->setBlock(builder, testBlock);
-    LLVMValueRef test = this->compileExpression(builder, *d.fTest);
-    LLVMBuildCondBr(builder, test, body, end);
-    this->setBlock(builder, body);
-    fBreakTarget.push_back(end);
-    fContinueTarget.push_back(body);
-    this->compileStatement(builder, *d.fStatement);
-    fBreakTarget.pop_back();
-    fContinueTarget.pop_back();
-    if (!ends_with_branch(*d.fStatement)) {
-        LLVMBuildBr(builder, testBlock);
-    }
-    this->setBlock(builder, end);
-}
-
-void JIT::compileWhile(LLVMBuilderRef builder, const WhileStatement& w) {
-    LLVMBasicBlockRef testBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                           "while test");
-    LLVMBasicBlockRef body = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                           "while body");
-    LLVMBasicBlockRef end = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction,
-                                                          "while end");
-    LLVMBuildBr(builder, testBlock);
-    this->setBlock(builder, testBlock);
-    LLVMValueRef test = this->compileExpression(builder, *w.fTest);
-    LLVMBuildCondBr(builder, test, body, end);
-    this->setBlock(builder, body);
-    fBreakTarget.push_back(end);
-    fContinueTarget.push_back(testBlock);
-    this->compileStatement(builder, *w.fStatement);
-    fBreakTarget.pop_back();
-    fContinueTarget.pop_back();
-    if (!ends_with_branch(*w.fStatement)) {
-        LLVMBuildBr(builder, testBlock);
-    }
-    this->setBlock(builder, end);
-}
-
-void JIT::compileBreak(LLVMBuilderRef builder, const BreakStatement& b) {
-    LLVMBuildBr(builder, fBreakTarget.back());
-}
-
-void JIT::compileContinue(LLVMBuilderRef builder, const ContinueStatement& b) {
-    LLVMBuildBr(builder, fContinueTarget.back());
-}
-
-void JIT::compileReturn(LLVMBuilderRef builder, const ReturnStatement& r) {
-    if (r.fExpression) {
-        LLVMBuildRet(builder, this->compileExpression(builder, *r.fExpression));
-    } else {
-        LLVMBuildRetVoid(builder);
-    }
-}
-
-void JIT::compileStatement(LLVMBuilderRef builder, const Statement& stmt) {
-    switch (stmt.fKind) {
-        case Statement::kBlock_Kind:
-            this->compileBlock(builder, (Block&) stmt);
-            break;
-        case Statement::kBreak_Kind:
-            this->compileBreak(builder, (BreakStatement&) stmt);
-            break;
-        case Statement::kContinue_Kind:
-            this->compileContinue(builder, (ContinueStatement&) stmt);
-            break;
-        case Statement::kDiscard_Kind:
-            abort();
-        case Statement::kDo_Kind:
-            this->compileDo(builder, (DoStatement&) stmt);
-            break;
-        case Statement::kExpression_Kind:
-            this->compileExpression(builder, *((ExpressionStatement&) stmt).fExpression);
-            break;
-        case Statement::kFor_Kind:
-            this->compileFor(builder, (ForStatement&) stmt);
-            break;
-        case Statement::kGroup_Kind:
-            abort();
-        case Statement::kIf_Kind:
-            this->compileIf(builder, (IfStatement&) stmt);
-            break;
-        case Statement::kNop_Kind:
-            break;
-        case Statement::kReturn_Kind:
-            this->compileReturn(builder, (ReturnStatement&) stmt);
-            break;
-        case Statement::kSwitch_Kind:
-            abort();
-        case Statement::kVarDeclarations_Kind:
-            this->compileVarDeclarations(builder, (VarDeclarationsStatement&) stmt);
-            break;
-        case Statement::kWhile_Kind:
-            this->compileWhile(builder, (WhileStatement&) stmt);
-            break;
-        default:
-            abort();
-    }
-}
-
-void JIT::compileStageFunctionLoop(const FunctionDefinition& f, LLVMValueRef newFunc) {
-    // loop over fVectorCount pixels, running the body of the stage function for each of them
-    LLVMValueRef oldFunction = fCurrentFunction;
-    fCurrentFunction = newFunc;
-    std::unique_ptr<LLVMValueRef[]> params(new LLVMValueRef[STAGE_PARAM_COUNT]);
-    LLVMGetParams(fCurrentFunction, params.get());
-    LLVMValueRef programParam = params.get()[1];
-    LLVMBuilderRef builder = LLVMCreateBuilderInContext(fContext);
-    LLVMBasicBlockRef oldAllocaBlock = fAllocaBlock;
-    LLVMBasicBlockRef oldCurrentBlock = fCurrentBlock;
-    fAllocaBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "alloca");
-    this->setBlock(builder, fAllocaBlock);
-    // temporaries to store the color channel vectors
-    LLVMValueRef rVec = LLVMBuildAlloca(builder, fFloat32VectorType, "rVec");
-    LLVMBuildStore(builder, params.get()[4], rVec);
-    LLVMValueRef gVec = LLVMBuildAlloca(builder, fFloat32VectorType, "gVec");
-    LLVMBuildStore(builder, params.get()[5], gVec);
-    LLVMValueRef bVec = LLVMBuildAlloca(builder, fFloat32VectorType, "bVec");
-    LLVMBuildStore(builder, params.get()[6], bVec);
-    LLVMValueRef aVec = LLVMBuildAlloca(builder, fFloat32VectorType, "aVec");
-    LLVMBuildStore(builder, params.get()[7], aVec);
-    LLVMValueRef color = LLVMBuildAlloca(builder, fFloat32Vector4Type, "color");
-    fVariables[f.fDeclaration.fParameters[1]] = LLVMBuildTrunc(builder, params.get()[3], fInt32Type,
-                                                               "y->Int32");
-    fVariables[f.fDeclaration.fParameters[2]] = color;
-    LLVMValueRef ivar = LLVMBuildAlloca(builder, fInt32Type, "i");
-    LLVMBuildStore(builder, LLVMConstInt(fInt32Type, 0, false), ivar);
-    LLVMBasicBlockRef start = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "start");
-    this->setBlock(builder, start);
-    LLVMValueRef iload = LLVMBuildLoad(builder, ivar, "load i");
-    fVariables[f.fDeclaration.fParameters[0]] = LLVMBuildAdd(builder,
-                                                             LLVMBuildTrunc(builder,
-                                                                            params.get()[2],
-                                                                            fInt32Type,
-                                                                            "x->Int32"),
-                                                             iload,
-                                                             "x");
-    LLVMValueRef vectorSize = LLVMConstInt(fInt32Type, fVectorCount, false);
-    LLVMValueRef test = LLVMBuildICmp(builder, LLVMIntSLT, iload, vectorSize, "i < vectorSize");
-    LLVMBasicBlockRef loopBody = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "body");
-    LLVMBasicBlockRef loopEnd = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "end");
-    LLVMBuildCondBr(builder, test, loopBody, loopEnd);
-    this->setBlock(builder, loopBody);
-    LLVMValueRef vec = LLVMGetUndef(fFloat32Vector4Type);
-    // extract the r, g, b, and a values from the color channel vectors and store them into "color"
-    for (int i = 0; i < 4; ++i) {
-        vec = LLVMBuildInsertElement(builder, vec,
-                                     LLVMBuildExtractElement(builder,
-                                                             params.get()[4 + i],
-                                                             iload, "initial"),
-                                     LLVMConstInt(fInt32Type, i, false),
-                                     "vec build");
-    }
-    LLVMBuildStore(builder, vec, color);
-    // write actual loop body
-    this->compileStatement(builder, *f.fBody);
-    // extract the r, g, b, and a values from "color" and stick them back into the color channel
-    // vectors
-    LLVMValueRef colorLoad = LLVMBuildLoad(builder, color, "color load");
-    LLVMBuildStore(builder,
-                   LLVMBuildInsertElement(builder, LLVMBuildLoad(builder, rVec, "rVec"),
-                                          LLVMBuildExtractElement(builder, colorLoad,
-                                                                  LLVMConstInt(fInt32Type, 0,
-                                                                               false),
-                                                                  "rExtract"),
-                                          iload, "rInsert"),
-                   rVec);
-    LLVMBuildStore(builder,
-                   LLVMBuildInsertElement(builder, LLVMBuildLoad(builder, gVec, "gVec"),
-                                          LLVMBuildExtractElement(builder, colorLoad,
-                                                                  LLVMConstInt(fInt32Type, 1,
-                                                                               false),
-                                                                  "gExtract"),
-                                          iload, "gInsert"),
-                   gVec);
-    LLVMBuildStore(builder,
-                   LLVMBuildInsertElement(builder, LLVMBuildLoad(builder, bVec, "bVec"),
-                                          LLVMBuildExtractElement(builder, colorLoad,
-                                                                  LLVMConstInt(fInt32Type, 2,
-                                                                               false),
-                                                                  "bExtract"),
-                                          iload, "bInsert"),
-                   bVec);
-    LLVMBuildStore(builder,
-                   LLVMBuildInsertElement(builder, LLVMBuildLoad(builder, aVec, "aVec"),
-                                          LLVMBuildExtractElement(builder, colorLoad,
-                                                                  LLVMConstInt(fInt32Type, 3,
-                                                                               false),
-                                                                  "aExtract"),
-                                          iload, "aInsert"),
-                   aVec);
-    LLVMValueRef inc = LLVMBuildAdd(builder, iload, LLVMConstInt(fInt32Type, 1, false), "inc i");
-    LLVMBuildStore(builder, inc, ivar);
-    LLVMBuildBr(builder, start);
-    this->setBlock(builder, loopEnd);
-    // increment program pointer, call the next stage
-    LLVMValueRef rawNextPtr = LLVMBuildLoad(builder, programParam, "next load");
-    LLVMTypeRef stageFuncType = LLVMTypeOf(newFunc);
-    LLVMValueRef nextPtr = LLVMBuildBitCast(builder, rawNextPtr, stageFuncType, "cast next->func");
-    LLVMValueRef nextInc = LLVMBuildIntToPtr(builder,
-                                             LLVMBuildAdd(builder,
-                                                          LLVMBuildPtrToInt(builder,
-                                                                            programParam,
-                                                                            fInt64Type,
-                                                                            "cast 1"),
-                                                          LLVMConstInt(fInt64Type, PTR_SIZE, false),
-                                                          "add"),
-                                            LLVMPointerType(fInt8PtrType, 0), "cast 2");
-    LLVMValueRef args[STAGE_PARAM_COUNT] = {
-        params.get()[0],
-        nextInc,
-        params.get()[2],
-        params.get()[3],
-        LLVMBuildLoad(builder, rVec, "rVec"),
-        LLVMBuildLoad(builder, gVec, "gVec"),
-        LLVMBuildLoad(builder, bVec, "bVec"),
-        LLVMBuildLoad(builder, aVec, "aVec"),
-        params.get()[8],
-        params.get()[9],
-        params.get()[10],
-        params.get()[11]
-    };
-    LLVMBuildCall(builder, nextPtr, args, STAGE_PARAM_COUNT, "");
-    LLVMBuildRetVoid(builder);
-    // finish
-    LLVMPositionBuilderAtEnd(builder, fAllocaBlock);
-    LLVMBuildBr(builder, start);
-    LLVMDisposeBuilder(builder);
-    if (LLVMVerifyFunction(fCurrentFunction, LLVMPrintMessageAction)) {
-        ABORT("verify failed\n");
-    }
-    fAllocaBlock = oldAllocaBlock;
-    fCurrentBlock = oldCurrentBlock;
-    fCurrentFunction = oldFunction;
-}
-
-// FIXME maybe pluggable code generators? Need to do something to separate all
-// of the normal codegen from the vector codegen and break this up into multiple
-// classes.
-
-bool JIT::getVectorLValue(LLVMBuilderRef builder, const Expression& e,
-                          LLVMValueRef out[CHANNELS]) {
-    switch (e.fKind) {
-        case Expression::kVariableReference_Kind:
-            if (fColorParam == &((VariableReference&) e).fVariable) {
-                memcpy(out, fChannels, sizeof(fChannels));
-                return true;
-            }
-            return false;
-        case Expression::kSwizzle_Kind: {
-            const Swizzle& s = (const Swizzle&) e;
-            LLVMValueRef base[CHANNELS];
-            if (!this->getVectorLValue(builder, *s.fBase, base)) {
-                return false;
-            }
-            for (size_t i = 0; i < s.fComponents.size(); ++i) {
-                out[i] = base[s.fComponents[i]];
-            }
-            return true;
-        }
-        default:
-            return false;
-    }
-}
-
-bool JIT::getVectorBinaryOperands(LLVMBuilderRef builder, const Expression& left,
-                                  LLVMValueRef outLeft[CHANNELS], const Expression& right,
-                                  LLVMValueRef outRight[CHANNELS]) {
-    if (!this->compileVectorExpression(builder, left, outLeft)) {
-        return false;
-    }
-    int leftColumns = left.fType.columns();
-    int rightColumns = right.fType.columns();
-    if (leftColumns == 1 && rightColumns > 1) {
-        for (int i = 1; i < rightColumns; ++i) {
-            outLeft[i] = outLeft[0];
-        }
-    }
-    if (!this->compileVectorExpression(builder, right, outRight)) {
-        return false;
-    }
-    if (rightColumns == 1 && leftColumns > 1) {
-        for (int i = 1; i < leftColumns; ++i) {
-            outRight[i] = outRight[0];
-        }
-    }
-    return true;
-}
-
-bool JIT::compileVectorBinary(LLVMBuilderRef builder, const BinaryExpression& b,
-                              LLVMValueRef out[CHANNELS]) {
-    LLVMValueRef left[CHANNELS];
-    LLVMValueRef right[CHANNELS];
-    #define VECTOR_BINARY(signedOp, unsignedOp, floatOp) {                               \
-        if (!this->getVectorBinaryOperands(builder, *b.fLeft, left, *b.fRight, right)) { \
-            return false;                                                                \
-        }                                                                                \
-        for (int i = 0; i < b.fLeft->fType.columns(); ++i) {                             \
-            switch (this->typeKind(b.fLeft->fType)) {                                    \
-                case kInt_TypeKind:                                                      \
-                    out[i] = signedOp(builder, left[i], right[i], "binary");             \
-                    break;                                                               \
-                case kUInt_TypeKind:                                                     \
-                    out[i] = unsignedOp(builder, left[i], right[i], "binary");           \
-                    break;                                                               \
-                case kFloat_TypeKind:                                                    \
-                    out[i] = floatOp(builder, left[i], right[i], "binary");              \
-                    break;                                                               \
-                case kBool_TypeKind:                                                     \
-                    SkASSERT(false);                                                       \
-                    break;                                                               \
-            }                                                                            \
-        }                                                                                \
-        return true;                                                                     \
-    }
-    switch (b.fOperator) {
-        case Token::EQ: {
-            if (!this->getVectorLValue(builder, *b.fLeft, left)) {
-                return false;
-            }
-            if (!this->compileVectorExpression(builder, *b.fRight, right)) {
-                return false;
-            }
-            int columns = b.fRight->fType.columns();
-            for (int i = 0; i < columns; ++i) {
-                LLVMBuildStore(builder, right[i], left[i]);
-            }
-            return true;
-        }
-        case Token::PLUS:
-            VECTOR_BINARY(LLVMBuildAdd, LLVMBuildAdd, LLVMBuildFAdd);
-        case Token::MINUS:
-            VECTOR_BINARY(LLVMBuildSub, LLVMBuildSub, LLVMBuildFSub);
-        case Token::STAR:
-            VECTOR_BINARY(LLVMBuildMul, LLVMBuildMul, LLVMBuildFMul);
-        case Token::SLASH:
-            VECTOR_BINARY(LLVMBuildSDiv, LLVMBuildUDiv, LLVMBuildFDiv);
-        case Token::PERCENT:
-            VECTOR_BINARY(LLVMBuildSRem, LLVMBuildURem, LLVMBuildSRem);
-        case Token::BITWISEAND:
-            VECTOR_BINARY(LLVMBuildAnd, LLVMBuildAnd, LLVMBuildAnd);
-        case Token::BITWISEOR:
-            VECTOR_BINARY(LLVMBuildOr, LLVMBuildOr, LLVMBuildOr);
-        default:
-            printf("unsupported operator: %s\n", b.description().c_str());
-            return false;
-    }
-}
-
-bool JIT::compileVectorConstructor(LLVMBuilderRef builder, const Constructor& c,
-                                   LLVMValueRef out[CHANNELS]) {
-    switch (c.fType.kind()) {
-        case Type::kScalar_Kind: {
-            SkASSERT(c.fArguments.size() == 1);
-            TypeKind from = this->typeKind(c.fArguments[0]->fType);
-            TypeKind to = this->typeKind(c.fType);
-            LLVMValueRef base[CHANNELS];
-            if (!this->compileVectorExpression(builder, *c.fArguments[0], base)) {
-                return false;
-            }
-            #define CONSTRUCT(fn)                                                                \
-                out[0] = LLVMGetUndef(LLVMVectorType(this->getType(c.fType), fVectorCount));     \
-                for (int i = 0; i < fVectorCount; ++i) {                                         \
-                    LLVMValueRef index = LLVMConstInt(fInt32Type, i, false);                     \
-                    LLVMValueRef baseVal = LLVMBuildExtractElement(builder, base[0], index,      \
-                                                                   "construct extract");         \
-                    out[0] = LLVMBuildInsertElement(builder, out[0],                             \
-                                                    fn(builder, baseVal, this->getType(c.fType), \
-                                                       "cast"),                                  \
-                                                    index, "construct insert");                  \
-                }                                                                                \
-                return true;
-            if (kFloat_TypeKind == to) {
-                if (kInt_TypeKind == from) {
-                    CONSTRUCT(LLVMBuildSIToFP);
-                }
-                if (kUInt_TypeKind == from) {
-                    CONSTRUCT(LLVMBuildUIToFP);
-                }
-            }
-            if (kInt_TypeKind == to) {
-                if (kFloat_TypeKind == from) {
-                    CONSTRUCT(LLVMBuildFPToSI);
-                }
-                if (kUInt_TypeKind == from) {
-                    return true;
-                }
-            }
-            if (kUInt_TypeKind == to) {
-                if (kFloat_TypeKind == from) {
-                    CONSTRUCT(LLVMBuildFPToUI);
-                }
-                if (kInt_TypeKind == from) {
-                    return base;
-                }
-            }
-            printf("%s\n", c.description().c_str());
-            ABORT("unsupported constructor");
-        }
-        case Type::kVector_Kind: {
-            if (c.fArguments.size() == 1) {
-                LLVMValueRef base[CHANNELS];
-                if (!this->compileVectorExpression(builder, *c.fArguments[0], base)) {
-                    return false;
-                }
-                for (int i = 0; i < c.fType.columns(); ++i) {
-                    out[i] = base[0];
-                }
-            } else {
-                SkASSERT(c.fArguments.size() == (size_t) c.fType.columns());
-                for (int i = 0; i < c.fType.columns(); ++i) {
-                    LLVMValueRef base[CHANNELS];
-                    if (!this->compileVectorExpression(builder, *c.fArguments[i], base)) {
-                        return false;
-                    }
-                    out[i] = base[0];
-                }
-            }
-            return true;
-        }
-        default:
-            break;
-    }
-    ABORT("unsupported constructor");
-}
-
-bool JIT::compileVectorFloatLiteral(LLVMBuilderRef builder,
-                                    const FloatLiteral& f,
-                                    LLVMValueRef out[CHANNELS]) {
-    LLVMValueRef value = LLVMConstReal(this->getType(f.fType), f.fValue);
-    LLVMValueRef values[MAX_VECTOR_COUNT];
-    for (int i = 0; i < fVectorCount; ++i) {
-        values[i] = value;
-    }
-    out[0] = LLVMConstVector(values, fVectorCount);
-    return true;
-}
-
-
-bool JIT::compileVectorSwizzle(LLVMBuilderRef builder, const Swizzle& s,
-                               LLVMValueRef out[CHANNELS]) {
-    LLVMValueRef all[CHANNELS];
-    if (!this->compileVectorExpression(builder, *s.fBase, all)) {
-        return false;
-    }
-    for (size_t i = 0; i < s.fComponents.size(); ++i) {
-        out[i] = all[s.fComponents[i]];
-    }
-    return true;
-}
-
-bool JIT::compileVectorVariableReference(LLVMBuilderRef builder, const VariableReference& v,
-                                         LLVMValueRef out[CHANNELS]) {
-    if (&v.fVariable == fColorParam) {
-        for (int i = 0; i < CHANNELS; ++i) {
-            out[i] = LLVMBuildLoad(builder, fChannels[i], "variable reference");
-        }
-        return true;
-    }
-    return false;
-}
-
-bool JIT::compileVectorExpression(LLVMBuilderRef builder, const Expression& expr,
-                                  LLVMValueRef out[CHANNELS]) {
-    switch (expr.fKind) {
-        case Expression::kBinary_Kind:
-            return this->compileVectorBinary(builder, (const BinaryExpression&) expr, out);
-        case Expression::kConstructor_Kind:
-            return this->compileVectorConstructor(builder, (const Constructor&) expr, out);
-        case Expression::kFloatLiteral_Kind:
-            return this->compileVectorFloatLiteral(builder, (const FloatLiteral&) expr, out);
-        case Expression::kSwizzle_Kind:
-            return this->compileVectorSwizzle(builder, (const Swizzle&) expr, out);
-        case Expression::kVariableReference_Kind:
-            return this->compileVectorVariableReference(builder, (const VariableReference&) expr,
-                                                        out);
-        default:
-            return false;
-    }
-}
-
-bool JIT::compileVectorStatement(LLVMBuilderRef builder, const Statement& stmt) {
-    switch (stmt.fKind) {
-        case Statement::kBlock_Kind:
-            for (const auto& s : ((const Block&) stmt).fStatements) {
-                if (!this->compileVectorStatement(builder, *s)) {
-                    return false;
-                }
-            }
-            return true;
-        case Statement::kExpression_Kind:
-            LLVMValueRef result;
-            return this->compileVectorExpression(builder,
-                                                 *((const ExpressionStatement&) stmt).fExpression,
-                                                 &result);
-        default:
-            return false;
-    }
-}
-
-bool JIT::compileStageFunctionVector(const FunctionDefinition& f, LLVMValueRef newFunc) {
-    LLVMValueRef oldFunction = fCurrentFunction;
-    fCurrentFunction = newFunc;
-    std::unique_ptr<LLVMValueRef[]> params(new LLVMValueRef[STAGE_PARAM_COUNT]);
-    LLVMGetParams(fCurrentFunction, params.get());
-    LLVMValueRef programParam = params.get()[1];
-    LLVMBuilderRef builder = LLVMCreateBuilderInContext(fContext);
-    LLVMBasicBlockRef oldAllocaBlock = fAllocaBlock;
-    LLVMBasicBlockRef oldCurrentBlock = fCurrentBlock;
-    fAllocaBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "alloca");
-    this->setBlock(builder, fAllocaBlock);
-    fChannels[0] = LLVMBuildAlloca(builder, fFloat32VectorType, "rVec");
-    LLVMBuildStore(builder, params.get()[4], fChannels[0]);
-    fChannels[1] = LLVMBuildAlloca(builder, fFloat32VectorType, "gVec");
-    LLVMBuildStore(builder, params.get()[5], fChannels[1]);
-    fChannels[2] = LLVMBuildAlloca(builder, fFloat32VectorType, "bVec");
-    LLVMBuildStore(builder, params.get()[6], fChannels[2]);
-    fChannels[3] = LLVMBuildAlloca(builder, fFloat32VectorType, "aVec");
-    LLVMBuildStore(builder, params.get()[7], fChannels[3]);
-    LLVMBasicBlockRef start = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "start");
-    this->setBlock(builder, start);
-    bool success = this->compileVectorStatement(builder, *f.fBody);
-    if (success) {
-        // increment program pointer, call next
-        LLVMValueRef rawNextPtr = LLVMBuildLoad(builder, programParam, "next load");
-        LLVMTypeRef stageFuncType = LLVMTypeOf(newFunc);
-        LLVMValueRef nextPtr = LLVMBuildBitCast(builder, rawNextPtr, stageFuncType,
-                                                "cast next->func");
-        LLVMValueRef nextInc = LLVMBuildIntToPtr(builder,
-                                                 LLVMBuildAdd(builder,
-                                                              LLVMBuildPtrToInt(builder,
-                                                                                programParam,
-                                                                                fInt64Type,
-                                                                                "cast 1"),
-                                                              LLVMConstInt(fInt64Type, PTR_SIZE,
-                                                                           false),
-                                                              "add"),
-                                                LLVMPointerType(fInt8PtrType, 0), "cast 2");
-        LLVMValueRef args[STAGE_PARAM_COUNT] = {
-            params.get()[0],
-            nextInc,
-            params.get()[2],
-            params.get()[3],
-            LLVMBuildLoad(builder, fChannels[0], "rVec"),
-            LLVMBuildLoad(builder, fChannels[1], "gVec"),
-            LLVMBuildLoad(builder, fChannels[2], "bVec"),
-            LLVMBuildLoad(builder, fChannels[3], "aVec"),
-            params.get()[8],
-            params.get()[9],
-            params.get()[10],
-            params.get()[11]
-        };
-        LLVMBuildCall(builder, nextPtr, args, STAGE_PARAM_COUNT, "");
-        LLVMBuildRetVoid(builder);
-        // finish
-        LLVMPositionBuilderAtEnd(builder, fAllocaBlock);
-        LLVMBuildBr(builder, start);
-        LLVMDisposeBuilder(builder);
-        if (LLVMVerifyFunction(fCurrentFunction, LLVMPrintMessageAction)) {
-            ABORT("verify failed\n");
-        }
-    } else {
-        LLVMDeleteBasicBlock(fAllocaBlock);
-        LLVMDeleteBasicBlock(start);
-    }
-
-    fAllocaBlock = oldAllocaBlock;
-    fCurrentBlock = oldCurrentBlock;
-    fCurrentFunction = oldFunction;
-    return success;
-}
-
-LLVMValueRef JIT::compileStageFunction(const FunctionDefinition& f) {
-    LLVMTypeRef returnType = fVoidType;
-    LLVMTypeRef parameterTypes[12] = { fSizeTType, LLVMPointerType(fInt8PtrType, 0), fSizeTType,
-                                       fSizeTType, fFloat32VectorType, fFloat32VectorType,
-                                       fFloat32VectorType, fFloat32VectorType, fFloat32VectorType,
-                                       fFloat32VectorType, fFloat32VectorType, fFloat32VectorType };
-    LLVMTypeRef stageFuncType = LLVMFunctionType(returnType, parameterTypes, 12, false);
-    LLVMValueRef result = LLVMAddFunction(fModule,
-                                          (String(f.fDeclaration.fName) + "$stage").c_str(),
-                                          stageFuncType);
-    fColorParam = f.fDeclaration.fParameters[2];
-    if (!this->compileStageFunctionVector(f, result)) {
-        // vectorization failed, fall back to looping over the pixels
-        this->compileStageFunctionLoop(f, result);
-    }
-    return result;
-}
-
-bool JIT::hasStageSignature(const FunctionDeclaration& f) {
-    return f.fReturnType == *fProgram->fContext->fVoid_Type &&
-           f.fParameters.size() == 3 &&
-           f.fParameters[0]->fType == *fProgram->fContext->fInt_Type &&
-           f.fParameters[0]->fModifiers.fFlags == 0 &&
-           f.fParameters[1]->fType == *fProgram->fContext->fInt_Type &&
-           f.fParameters[1]->fModifiers.fFlags == 0 &&
-           f.fParameters[2]->fType == *fProgram->fContext->fHalf4_Type &&
-           f.fParameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag | Modifiers::kOut_Flag);
-}
-
-LLVMValueRef JIT::compileFunction(const FunctionDefinition& f) {
-    if (this->hasStageSignature(f.fDeclaration)) {
-        this->compileStageFunction(f);
-        // we compile foo$stage *in addition* to compiling foo, as we can't be sure that the intent
-        // was to produce an SkJumper stage just because the signature matched or that the function
-        // is not otherwise called. May need a better way to handle this.
-    }
-    LLVMTypeRef returnType = this->getType(f.fDeclaration.fReturnType);
-    std::vector<LLVMTypeRef> parameterTypes;
-    for (const auto& p : f.fDeclaration.fParameters) {
-        LLVMTypeRef type = this->getType(p->fType);
-        if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
-            type = LLVMPointerType(type, 0);
-        }
-        parameterTypes.push_back(type);
-    }
-    fCurrentFunction  = LLVMAddFunction(fModule,
-                                        String(f.fDeclaration.fName).c_str(),
-                                        LLVMFunctionType(returnType, parameterTypes.data(),
-                                                         parameterTypes.size(), false));
-    fFunctions[&f.fDeclaration] = fCurrentFunction;
-
-    std::unique_ptr<LLVMValueRef[]> params(new LLVMValueRef[parameterTypes.size()]);
-    LLVMGetParams(fCurrentFunction, params.get());
-    for (size_t i = 0; i < f.fDeclaration.fParameters.size(); ++i) {
-        fVariables[f.fDeclaration.fParameters[i]] = params.get()[i];
-    }
-    LLVMBuilderRef builder = LLVMCreateBuilderInContext(fContext);
-    fAllocaBlock = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "alloca");
-    LLVMBasicBlockRef start = LLVMAppendBasicBlockInContext(fContext, fCurrentFunction, "start");
-    fCurrentBlock = start;
-    LLVMPositionBuilderAtEnd(builder, fCurrentBlock);
-    this->compileStatement(builder, *f.fBody);
-    if (!ends_with_branch(*f.fBody)) {
-        if (f.fDeclaration.fReturnType == *fProgram->fContext->fVoid_Type) {
-            LLVMBuildRetVoid(builder);
-        } else {
-            LLVMBuildUnreachable(builder);
-        }
-    }
-    LLVMPositionBuilderAtEnd(builder, fAllocaBlock);
-    LLVMBuildBr(builder, start);
-    LLVMDisposeBuilder(builder);
-    if (LLVMVerifyFunction(fCurrentFunction, LLVMPrintMessageAction)) {
-        ABORT("verify failed\n");
-    }
-    return fCurrentFunction;
-}
-
-void JIT::createModule() {
-    fPromotedParameters.clear();
-    fModule = LLVMModuleCreateWithNameInContext("skslmodule", fContext);
-    this->loadBuiltinFunctions();
-    LLVMTypeRef fold2Params[1] = { fInt1Vector2Type };
-    fFoldAnd2Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.and.i1.v2i1",
-                                    LLVMFunctionType(fInt1Type, fold2Params, 1, false));
-    fFoldOr2Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.or.i1.v2i1",
-                                   LLVMFunctionType(fInt1Type, fold2Params, 1, false));
-    LLVMTypeRef fold3Params[1] = { fInt1Vector3Type };
-    fFoldAnd3Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.and.i1.v3i1",
-                                    LLVMFunctionType(fInt1Type, fold3Params, 1, false));
-    fFoldOr3Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.or.i1.v3i1",
-                                   LLVMFunctionType(fInt1Type, fold3Params, 1, false));
-    LLVMTypeRef fold4Params[1] = { fInt1Vector4Type };
-    fFoldAnd4Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.and.i1.v4i1",
-                                    LLVMFunctionType(fInt1Type, fold4Params, 1, false));
-    fFoldOr4Func = LLVMAddFunction(fModule, "llvm.experimental.vector.reduce.or.i1.v4i1",
-                                   LLVMFunctionType(fInt1Type, fold4Params, 1, false));
-    // LLVM doesn't do void*, have to declare it as int8*
-    LLVMTypeRef appendParams[3] = { fInt8PtrType, fInt32Type, fInt8PtrType };
-    fAppendFunc = LLVMAddFunction(fModule, "sksl_pipeline_append", LLVMFunctionType(fVoidType,
-                                                                                    appendParams,
-                                                                                    3,
-                                                                                    false));
-    LLVMTypeRef appendCallbackParams[2] = { fInt8PtrType, fInt8PtrType };
-    fAppendCallbackFunc = LLVMAddFunction(fModule, "sksl_pipeline_append_callback",
-                                          LLVMFunctionType(fVoidType, appendCallbackParams, 2,
-                                                           false));
-
-    LLVMTypeRef debugParams[3] = { fFloat32Type };
-    fDebugFunc = LLVMAddFunction(fModule, "sksl_debug_print", LLVMFunctionType(fVoidType,
-                                                                               debugParams,
-                                                                               1,
-                                                                               false));
-
-    for (const auto& e : *fProgram) {
-        if (e.fKind == ProgramElement::kFunction_Kind) {
-            this->compileFunction((FunctionDefinition&) e);
-        }
-    }
-}
-
-std::unique_ptr<JIT::Module> JIT::compile(std::unique_ptr<Program> program) {
-    fCompiler.optimize(*program);
-    fProgram = std::move(program);
-    this->createModule();
-    this->optimize();
-    return std::unique_ptr<Module>(new Module(std::move(fProgram), fSharedModule, fJITStack));
-}
-
-void JIT::optimize() {
-    LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
-    LLVMPassManagerBuilderSetOptLevel(pmb, 3);
-    LLVMPassManagerRef functionPM = LLVMCreateFunctionPassManagerForModule(fModule);
-    LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, functionPM);
-    LLVMPassManagerRef modulePM = LLVMCreatePassManager();
-    LLVMPassManagerBuilderPopulateModulePassManager(pmb, modulePM);
-    LLVMInitializeFunctionPassManager(functionPM);
-
-    LLVMValueRef func = LLVMGetFirstFunction(fModule);
-    for (;;) {
-        if (!func) {
-            break;
-        }
-        LLVMRunFunctionPassManager(functionPM, func);
-        func = LLVMGetNextFunction(func);
-    }
-    LLVMRunPassManager(modulePM, fModule);
-    LLVMDisposePassManager(functionPM);
-    LLVMDisposePassManager(modulePM);
-    LLVMPassManagerBuilderDispose(pmb);
-
-    std::string error_string;
-    if (LLVMLoadLibraryPermanently(nullptr)) {
-        ABORT("LLVMLoadLibraryPermanently failed");
-    }
-    char* defaultTriple = LLVMGetDefaultTargetTriple();
-    char* error;
-    LLVMTargetRef target;
-    if (LLVMGetTargetFromTriple(defaultTriple, &target, &error)) {
-        ABORT("LLVMGetTargetFromTriple failed");
-    }
-
-    if (!LLVMTargetHasJIT(target)) {
-        ABORT("!LLVMTargetHasJIT");
-    }
-    LLVMTargetMachineRef targetMachine = LLVMCreateTargetMachine(target,
-                                                                 defaultTriple,
-                                                                 fCPU,
-                                                                 nullptr,
-                                                                 LLVMCodeGenLevelDefault,
-                                                                 LLVMRelocDefault,
-                                                                 LLVMCodeModelJITDefault);
-    LLVMDisposeMessage(defaultTriple);
-    LLVMTargetDataRef dataLayout = LLVMCreateTargetDataLayout(targetMachine);
-    LLVMSetModuleDataLayout(fModule, dataLayout);
-    LLVMDisposeTargetData(dataLayout);
-
-    fJITStack = LLVMOrcCreateInstance(targetMachine);
-    fSharedModule = LLVMOrcMakeSharedModule(fModule);
-    LLVMOrcModuleHandle orcModule;
-    LLVMOrcAddEagerlyCompiledIR(fJITStack, &orcModule, fSharedModule,
-                                (LLVMOrcSymbolResolverFn) resolveSymbol, this);
-    LLVMDisposeTargetMachine(targetMachine);
-}
-
-void* JIT::Module::getSymbol(const char* name) {
-    LLVMOrcTargetAddress result;
-    if (LLVMOrcGetSymbolAddress(fJITStack, &result, name)) {
-        ABORT("GetSymbolAddress error");
-    }
-    if (!result) {
-        ABORT("symbol not found");
-    }
-    return (void*) result;
-}
-
-void* JIT::Module::getJumperStage(const char* name) {
-    return this->getSymbol((String(name) + "$stage").c_str());
-}
-
-} // namespace
-
-#endif // SK_LLVM_AVAILABLE
-
-#endif // SKSL_STANDALONE
diff --git a/src/sksl/SkSLJIT.h b/src/sksl/SkSLJIT.h
deleted file mode 100644
index 8b815ff..0000000
--- a/src/sksl/SkSLJIT.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * 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_JIT
-#define SKSL_JIT
-
-#ifdef SK_LLVM_AVAILABLE
-
-#include "src/sksl/ir/SkSLBinaryExpression.h"
-#include "src/sksl/ir/SkSLBreakStatement.h"
-#include "src/sksl/ir/SkSLContinueStatement.h"
-#include "src/sksl/ir/SkSLDoStatement.h"
-#include "src/sksl/ir/SkSLExpression.h"
-#include "src/sksl/ir/SkSLForStatement.h"
-#include "src/sksl/ir/SkSLFunctionCall.h"
-#include "src/sksl/ir/SkSLFunctionDefinition.h"
-#include "src/sksl/ir/SkSLIfStatement.h"
-#include "src/sksl/ir/SkSLIndexExpression.h"
-#include "src/sksl/ir/SkSLPostfixExpression.h"
-#include "src/sksl/ir/SkSLPrefixExpression.h"
-#include "src/sksl/ir/SkSLProgram.h"
-#include "src/sksl/ir/SkSLReturnStatement.h"
-#include "src/sksl/ir/SkSLStatement.h"
-#include "src/sksl/ir/SkSLSwizzle.h"
-#include "src/sksl/ir/SkSLTernaryExpression.h"
-#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
-#include "src/sksl/ir/SkSLVariableReference.h"
-#include "src/sksl/ir/SkSLWhileStatement.h"
-
-#include "llvm-c/Analysis.h"
-#include "llvm-c/Core.h"
-#include "llvm-c/OrcBindings.h"
-#include "llvm-c/Support.h"
-#include "llvm-c/Target.h"
-#include "llvm-c/Transforms/PassManagerBuilder.h"
-#include "llvm-c/Types.h"
-#include <stack>
-
-class SkRasterPipeline;
-
-namespace SkSL {
-
-struct AppendStage;
-
-/**
- * A just-in-time compiler for SkSL code which uses an LLVM backend. Only available when the
- * skia_llvm_path gn arg is set.
- *
- * Example of using SkSLJIT to set up an SkJumper pipeline stage:
- *
- * #ifdef SK_LLVM_AVAILABLE
- *   SkSL::Compiler compiler;
- *   SkSL::Program::Settings settings;
- *   std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
-         SkSL::Program::kPipelineStage_Kind,
- *       "void swap(int x, int y, inout float4 color) {"
- *       "    color.rb = color.br;"
- *       "}",
- *       settings);
- *   if (!program) {
- *       printf("%s\n", compiler.errorText().c_str());
- *       abort();
- *   }
- *   SkSL::JIT& jit = *scratch->make<SkSL::JIT>(&compiler);
- *   std::unique_ptr<SkSL::JIT::Module> module = jit.compile(std::move(program));
- *   void* func = module->getJumperStage("swap");
- *   p->append(func, nullptr);
- * #endif
- */
-class JIT {
-    typedef int StackIndex;
-
-public:
-    class Module {
-    public:
-        /**
-         * Returns the address of a symbol in the module.
-         */
-        void* getSymbol(const char* name);
-
-        /**
-         * Returns the address of a function as an SkJumper pipeline stage. The function must have
-         * the signature void <name>(int x, int y, inout float4 color). The returned function will
-         * have the correct signature to function as an SkJumper stage (meaning it will actually
-         * have a different signature at runtime, accepting vector parameters and operating on
-         * multiple pixels simultaneously as is normal for SkJumper stages).
-         */
-        void* getJumperStage(const char* name);
-
-        ~Module() {
-            LLVMOrcDisposeSharedModuleRef(fSharedModule);
-        }
-
-    private:
-        Module(std::unique_ptr<Program> program,
-               LLVMSharedModuleRef sharedModule,
-               LLVMOrcJITStackRef jitStack)
-        : fProgram(std::move(program))
-        , fSharedModule(sharedModule)
-        , fJITStack(jitStack) {}
-
-        std::unique_ptr<Program> fProgram;
-        LLVMSharedModuleRef fSharedModule;
-        LLVMOrcJITStackRef fJITStack;
-
-        friend class JIT;
-    };
-
-    JIT(Compiler* compiler);
-
-    ~JIT();
-
-    /**
-     * Just-in-time compiles an SkSL program and returns the resulting Module. The JIT must not be
-     * destroyed before all of its Modules are destroyed.
-     */
-    std::unique_ptr<Module> compile(std::unique_ptr<Program> program);
-
-private:
-    static constexpr int CHANNELS = 4;
-
-    enum TypeKind {
-        kFloat_TypeKind,
-        kInt_TypeKind,
-        kUInt_TypeKind,
-        kBool_TypeKind
-    };
-
-    class LValue {
-    public:
-        virtual ~LValue() {}
-
-        virtual LLVMValueRef load(LLVMBuilderRef builder) = 0;
-
-        virtual void store(LLVMBuilderRef builder, LLVMValueRef value) = 0;
-    };
-
-    void addBuiltinFunction(const char* ourName, const char* realName, LLVMTypeRef returnType,
-                            std::vector<LLVMTypeRef> parameters);
-
-    void loadBuiltinFunctions();
-
-    void setBlock(LLVMBuilderRef builder, LLVMBasicBlockRef block);
-
-    LLVMTypeRef getType(const Type& type);
-
-    TypeKind typeKind(const Type& type);
-
-    std::unique_ptr<LValue> getLValue(LLVMBuilderRef builder, const Expression& expr);
-
-    void vectorize(LLVMBuilderRef builder, LLVMValueRef* value, int columns);
-
-    void vectorize(LLVMBuilderRef builder, const BinaryExpression& b, LLVMValueRef* left,
-                   LLVMValueRef* right);
-
-    LLVMValueRef compileBinary(LLVMBuilderRef builder, const BinaryExpression& b);
-
-    LLVMValueRef compileConstructor(LLVMBuilderRef builder, const Constructor& c);
-
-    LLVMValueRef compileFunctionCall(LLVMBuilderRef builder, const FunctionCall& fc);
-
-    LLVMValueRef compileIndex(LLVMBuilderRef builder, const IndexExpression& v);
-
-    LLVMValueRef compilePostfix(LLVMBuilderRef builder, const PostfixExpression& p);
-
-    LLVMValueRef compilePrefix(LLVMBuilderRef builder, const PrefixExpression& p);
-
-    LLVMValueRef compileSwizzle(LLVMBuilderRef builder, const Swizzle& s);
-
-    LLVMValueRef compileVariableReference(LLVMBuilderRef builder, const VariableReference& v);
-
-    LLVMValueRef compileTernary(LLVMBuilderRef builder, const TernaryExpression& t);
-
-    LLVMValueRef compileExpression(LLVMBuilderRef builder, const Expression& expr);
-
-    void appendStage(LLVMBuilderRef builder, const AppendStage& a);
-
-    void compileBlock(LLVMBuilderRef builder, const Block& block);
-
-    void compileBreak(LLVMBuilderRef builder, const BreakStatement& b);
-
-    void compileContinue(LLVMBuilderRef builder, const ContinueStatement& c);
-
-    void compileDo(LLVMBuilderRef builder, const DoStatement& d);
-
-    void compileFor(LLVMBuilderRef builder, const ForStatement& f);
-
-    void compileIf(LLVMBuilderRef builder, const IfStatement& i);
-
-    void compileReturn(LLVMBuilderRef builder, const ReturnStatement& r);
-
-    void compileVarDeclarations(LLVMBuilderRef builder, const VarDeclarationsStatement& decls);
-
-    void compileWhile(LLVMBuilderRef builder, const WhileStatement& w);
-
-    void compileStatement(LLVMBuilderRef builder, const Statement& stmt);
-
-    // The "Vector" variants of functions attempt to compile a given expression or statement as part
-    // of a vectorized SkJumper stage function - that is, with r, g, b, and a each being vectors of
-    // fVectorCount floats. So a statement like "color.r = 0;" looks like it modifies a single
-    // channel of a single pixel, but the compiled code will actually modify the red channel of
-    // fVectorCount pixels at once.
-    //
-    // As not everything can be vectorized, these calls return a bool to indicate whether they were
-    // successful. If anything anywhere in the function cannot be vectorized, the JIT will fall back
-    // to looping over the pixels instead.
-    //
-    // Since we process multiple pixels at once, and each pixel consists of multiple color channels,
-    // expressions may effectively result in a vector-of-vectors. We produce zero to four outputs
-    // when compiling expression, each of which is a vector, so that e.g. float2(1, 0) actually
-    // produces two vectors, one containing all 1s, the other all 0s. The out parameter always
-    // allows for 4 channels, but the functions produce 0 to 4 channels depending on the type they
-    // are operating on. Thus evaluating "color.rgb" actually fills in out[0] through out[2],
-    // leaving out[3] uninitialized.
-    // As the number of outputs can be inferred from the type of the expression, it is not
-    // explicitly signalled anywhere.
-    bool compileVectorBinary(LLVMBuilderRef builder, const BinaryExpression& b,
-                             LLVMValueRef out[CHANNELS]);
-
-    bool compileVectorConstructor(LLVMBuilderRef builder, const Constructor& c,
-                                  LLVMValueRef out[CHANNELS]);
-
-    bool compileVectorFloatLiteral(LLVMBuilderRef builder, const FloatLiteral& f,
-                                   LLVMValueRef out[CHANNELS]);
-
-    bool compileVectorSwizzle(LLVMBuilderRef builder, const Swizzle& s,
-                              LLVMValueRef out[CHANNELS]);
-
-    bool compileVectorVariableReference(LLVMBuilderRef builder, const VariableReference& v,
-                                        LLVMValueRef out[CHANNELS]);
-
-    bool compileVectorExpression(LLVMBuilderRef builder, const Expression& expr,
-                                 LLVMValueRef out[CHANNELS]);
-
-    bool getVectorLValue(LLVMBuilderRef builder, const Expression& e, LLVMValueRef out[CHANNELS]);
-
-    /**
-     * Evaluates the left and right operands of a binary operation, promoting one of them to a
-     * vector if necessary to make the types match.
-     */
-    bool getVectorBinaryOperands(LLVMBuilderRef builder, const Expression& left,
-                                 LLVMValueRef outLeft[CHANNELS], const Expression& right,
-                                 LLVMValueRef outRight[CHANNELS]);
-
-    bool compileVectorStatement(LLVMBuilderRef builder, const Statement& stmt);
-
-    /**
-     * Returns true if this function has the signature void(int, int, inout float4) and thus can be
-     * used as an SkJumper stage.
-     */
-    bool hasStageSignature(const FunctionDeclaration& f);
-
-    /**
-     * Attempts to compile a vectorized stage function, returning true on success. A stage function
-     * of e.g. "color.r = 0;" will produce code which sets the entire red vector to zeros in a
-     * single instruction, thus calculating several pixels at once.
-     */
-    bool compileStageFunctionVector(const FunctionDefinition& f, LLVMValueRef newFunc);
-
-    /**
-     * Fallback function which loops over the pixels, for when vectorization fails. A stage function
-     * of e.g. "color.r = 0;" will produce a loop which iterates over the entries in the red vector,
-     * setting each one to zero individually.
-     */
-    void compileStageFunctionLoop(const FunctionDefinition& f, LLVMValueRef newFunc);
-
-    /**
-     * Called when compiling a function which has the signature of an SkJumper stage. Produces a
-     * version of the function which can be plugged into SkJumper (thus having a signature which
-     * accepts four vectors, one for each color channel, containing the color data of multiple
-     * pixels at once). To go from SkSL code which operates on a single pixel at a time to CPU code
-     * which operates on multiple pixels at once, the code is either vectorized using
-     * compileStageFunctionVector or wrapped in a loop using compileStageFunctionLoop.
-     */
-    LLVMValueRef compileStageFunction(const FunctionDefinition& f);
-
-    /**
-     * Compiles an SkSL function to an LLVM function. If the function has the signature of an
-     * SkJumper stage, it will *also* be compiled by compileStageFunction, resulting in both a stage
-     * and non-stage version of the function.
-     */
-    LLVMValueRef compileFunction(const FunctionDefinition& f);
-
-    void createModule();
-
-    void optimize();
-
-    bool isColorRef(const Expression& expr);
-
-    static uint64_t resolveSymbol(const char* name, JIT* jit);
-
-    const char* fCPU;
-    int fVectorCount;
-    Compiler& fCompiler;
-    std::unique_ptr<Program> fProgram;
-    LLVMContextRef fContext;
-    LLVMModuleRef fModule;
-    LLVMSharedModuleRef fSharedModule;
-    LLVMOrcJITStackRef fJITStack;
-    LLVMValueRef fCurrentFunction;
-    LLVMBasicBlockRef fAllocaBlock;
-    LLVMBasicBlockRef fCurrentBlock;
-    LLVMTypeRef fVoidType;
-    LLVMTypeRef fInt1Type;
-    LLVMTypeRef fInt1VectorType;
-    LLVMTypeRef fInt1Vector2Type;
-    LLVMTypeRef fInt1Vector3Type;
-    LLVMTypeRef fInt1Vector4Type;
-    LLVMTypeRef fInt8Type;
-    LLVMTypeRef fInt8PtrType;
-    LLVMTypeRef fInt32Type;
-    LLVMTypeRef fInt32VectorType;
-    LLVMTypeRef fInt32Vector2Type;
-    LLVMTypeRef fInt32Vector3Type;
-    LLVMTypeRef fInt32Vector4Type;
-    LLVMTypeRef fInt64Type;
-    LLVMTypeRef fSizeTType;
-    LLVMTypeRef fFloat32Type;
-    LLVMTypeRef fFloat32VectorType;
-    LLVMTypeRef fFloat32Vector2Type;
-    LLVMTypeRef fFloat32Vector3Type;
-    LLVMTypeRef fFloat32Vector4Type;
-    // Our SkSL stage functions have a single float4 for color, but the actual SkJumper stage
-    // function has four separate vectors, one for each channel. These four values are references to
-    // the red, green, blue, and alpha vectors respectively.
-    LLVMValueRef fChannels[CHANNELS];
-    // when processing a stage function, this points to the SkSL color parameter (an inout float4)
-    const Variable* fColorParam;
-    std::unordered_map<const FunctionDeclaration*, LLVMValueRef> fFunctions;
-    std::unordered_map<const Variable*, LLVMValueRef> fVariables;
-    // LLVM function parameters are read-only, so when modifying function parameters we need to
-    // first promote them to variables. This keeps track of which parameters have been promoted.
-    std::set<const Variable*> fPromotedParameters;
-    std::vector<LLVMBasicBlockRef> fBreakTarget;
-    std::vector<LLVMBasicBlockRef> fContinueTarget;
-
-    LLVMValueRef fFoldAnd2Func;
-    LLVMValueRef fFoldOr2Func;
-    LLVMValueRef fFoldAnd3Func;
-    LLVMValueRef fFoldOr3Func;
-    LLVMValueRef fFoldAnd4Func;
-    LLVMValueRef fFoldOr4Func;
-    LLVMValueRef fAppendFunc;
-    LLVMValueRef fAppendCallbackFunc;
-    LLVMValueRef fDebugFunc;
-};
-
-} // namespace
-
-#endif // SK_LLVM_AVAILABLE
-
-#endif // SKSL_JIT
diff --git a/src/sksl/SkSLSectionAndParameterHelper.cpp b/src/sksl/SkSLSectionAndParameterHelper.cpp
index 08299bb..edd9fbe 100644
--- a/src/sksl/SkSLSectionAndParameterHelper.cpp
+++ b/src/sksl/SkSLSectionAndParameterHelper.cpp
@@ -140,7 +140,6 @@
         }
         case Expression::kVariableReference_Kind:
             return false;
-        case Expression::kAppendStage_Kind:
         case Expression::kBoolLiteral_Kind:
         case Expression::kDefined_Kind:
         case Expression::kExternalFunctionCall_Kind:
diff --git a/src/sksl/ir/SkSLAppendStage.h b/src/sksl/ir/SkSLAppendStage.h
deleted file mode 100644
index 88ff8b7..0000000
--- a/src/sksl/ir/SkSLAppendStage.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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_APPENDSTAGE
-#define SKSL_APPENDSTAGE
-
-#ifndef SKSL_STANDALONE
-
-#include "src/core/SkRasterPipeline.h"
-#include "src/sksl/SkSLContext.h"
-#include "src/sksl/ir/SkSLExpression.h"
-
-namespace SkSL {
-
-struct AppendStage : public Expression {
-    AppendStage(const Context& context, int offset, SkRasterPipeline::StockStage stage,
-                std::vector<std::unique_ptr<Expression>> arguments)
-    : INHERITED(offset, kAppendStage_Kind, *context.fVoid_Type)
-    , fStage(stage)
-    , fArguments(std::move(arguments)) {}
-
-    std::unique_ptr<Expression> clone() const override {
-        std::vector<std::unique_ptr<Expression>> cloned;
-        for (const auto& arg : fArguments) {
-            cloned.push_back(arg->clone());
-        }
-        return std::unique_ptr<Expression>(new AppendStage(fOffset, fStage, std::move(cloned),
-                                                           &fType));
-    }
-
-    String description() const override {
-        String result = "append(";
-        const char* separator = "";
-        for (const auto& a : fArguments) {
-            result += separator;
-            result += a->description();
-            separator = ", ";
-        }
-        result += ")";
-        return result;
-    }
-
-    bool hasSideEffects() const override {
-        return true;
-    }
-
-    SkRasterPipeline::StockStage fStage;
-
-    std::vector<std::unique_ptr<Expression>> fArguments;
-
-    typedef Expression INHERITED;
-
-private:
-    AppendStage(int offset, SkRasterPipeline::StockStage stage,
-                std::vector<std::unique_ptr<Expression>> arguments, const Type* type)
-    : INHERITED(offset, kAppendStage_Kind, *type)
-    , fStage(stage)
-    , fArguments(std::move(arguments)) {}
-
-};
-
-} // namespace
-
-#endif // SKSL_STANDALONE
-
-#endif // SKSL_APPENDSTAGE
diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h
index 2302bdf..928295d 100644
--- a/src/sksl/ir/SkSLExpression.h
+++ b/src/sksl/ir/SkSLExpression.h
@@ -25,7 +25,6 @@
  */
 struct Expression : public IRNode {
     enum Kind {
-        kAppendStage_Kind,
         kBinary_Kind,
         kBoolLiteral_Kind,
         kConstructor_Kind,
diff --git a/src/sksl/sksl_mixer.inc b/src/sksl/sksl_mixer.inc
deleted file mode 100644
index 3fc56d4..0000000
--- a/src/sksl/sksl_mixer.inc
+++ /dev/null
@@ -1,8 +0,0 @@
-STRINGIFY(
-in fragmentProcessor _child1;
-in fragmentProcessor _child2;
-
-layout(builtin=10004) out half4 sk_OutColor;
-
-half4 sample(fragmentProcessor fp);
-)
diff --git a/src/sksl/sksl_pipeline.inc b/src/sksl/sksl_pipeline.inc
index f6e2268..56f189e 100644
--- a/src/sksl/sksl_pipeline.inc
+++ b/src/sksl/sksl_pipeline.inc
@@ -1,21 +1,3 @@
 STRINGIFY(
-    // special-cased within the compiler - append takes various arguments depending on what kind of
-    // stage is being appended
-    sk_has_side_effects void append();
-
-    float abs(float x);
-    float sin(float x);
-    float cos(float y);
-    float tan(float x);
-    float sqrt(float x);
-    float clamp(float x, float min, float max);
-    float2 clamp(float2 x, float min, float max);
-    float3 clamp(float3 x, float min, float max);
-    float4 clamp(float4 x, float min, float max);
-    sk_has_side_effects void print(float x);
-    layout(builtin=10009) int sk_x;
-    layout(builtin=10010) int sk_y;
-    layout(builtin=10004) out half4 sk_OutColor;
-
     half4 sample(fragmentProcessor fp);
 )
diff --git a/tests/SkSLJITTest.cpp b/tests/SkSLJITTest.cpp
deleted file mode 100644
index a435b3a..0000000
--- a/tests/SkSLJITTest.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/sksl/SkSLJIT.h"
-
-#include "tests/Test.h"
-
-#ifdef SK_LLVM_AVAILABLE
-
-template<typename type>
-void test(skiatest::Reporter* r, const char* src, type x, type y, type result) {
-    SkSL::Compiler compiler;
-    SkSL::Program::Settings settings;
-    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
-                                                                 SkSL::Program::kPipelineStage_Kind,
-                                                                 SkSL::String(src), settings);
-    REPORTER_ASSERT(r, program);
-    if (program) {
-       SkSL::JIT jit(&compiler);
-       std::unique_ptr<SkSL::JIT::Module> module = jit.compile(std::move(program));
-       type (*test)(type, type) = (type(*)(type, type)) module->getSymbol("test");
-       REPORTER_ASSERT(r, test(x, y) == result);
-    } else {
-        printf("%s", compiler.errorText().c_str());
-    }
-}
-
-DEF_TEST(SkSLJITAdd, r) {
-    test<int>(r, "int test(int x, int y) { return x + y; }", 12, 5, 17);
-    test<float>(r, "float test(float x, float y) { return x + y; }", -1, 76, 75);
-    test<int>(r, "int test(int x, int y) { x += y; return x; }", 12, 5, 17);
-    test<float>(r, "float test(float x, float y) { x += y; return x; }", -1, 76, 75);
-    test<int>(r, "int test(int x, int y) { return (int2(x) + int2(y)).x; }", 0, -100, -100);
-    test<float>(r, "float test(float x, float y) { return (float2(x) + float2(y)).x; }", 36, 6, 42);
-}
-
-DEF_TEST(SkSLJITSub, r) {
-    test<int>(r, "int test(int x, int y) { return x - y; }", 12, 5, 7);
-    test<float>(r, "float test(float x, float y) { return x - y; }", -1, 76, -77);
-    test<int>(r, "int test(int x, int y) { x -= y; return x; }", 12, 5, 7);
-    test<float>(r, "float test(float x, float y) { x -= y; return x; }", -1, 76, -77);
-    test<int>(r, "int test(int x, int y) { return (int2(x) - int2(y)).x; }", 0, -100, 100);
-    test<float>(r, "float test(float x, float y) { return (float2(x) - float2(y)).x; }", 36, 6, 30);
-}
-
-DEF_TEST(SkSLJITMul, r) {
-    test<int>(r, "int test(int x, int y) { return x * y; }", 12, 5, 60);
-    test<float>(r, "float test(float x, float y) { return x * y; }", -1, 76, -76);
-    test<int>(r, "int test(int x, int y) { x *= y; return x; }", 12, 5, 60);
-    test<float>(r, "float test(float x, float y) { x *= y; return x; }", -1, 76, -76);
-    test<int>(r, "int test(int x, int y) { return (int2(x) * int2(y)).x; }", 0, -100, 0);
-    test<float>(r, "float test(float x, float y) { return (float2(x) * float2(y)).x; }", 36, 6,
-                216);
-}
-
-DEF_TEST(SkSLJITDiv, r) {
-    test<int>(r, "int test(int x, int y) { return x / y; }", 12, 5, 2);
-    test<float>(r, "float test(float x, float y) { return x / y; }", -1, 76, -1.0 / 76.0);
-    test<int>(r, "int test(int x, int y) { x /= y; return x; }", 12, 5, 2);
-    test<float>(r, "float test(float x, float y) { x /= y; return x; }", -1, 76, -1.0 / 76.0);
-    test<int>(r, "int test(int x, int y) { return (int2(x) / int2(y)).x; }", 0, -100, 0);
-    test<float>(r, "float test(float x, float y) { return (float2(x) / float2(y)).x; }", 36, 6,
-                6);
-}
-
-DEF_TEST(SkSLJITOr, r) {
-    test<int>(r, "int test(int x, int y) { return x | y; }", 45, 15, 47);
-    test<int>(r, "int test(int x, int y) { x |= y; return x; }", 45, 15, 47);
-}
-
-DEF_TEST(SkSLJITAnd, r) {
-    test<int>(r, "int test(int x, int y) { return x & y; }", 45, 15, 13);
-    test<int>(r, "int test(int x, int y) { x &= y; return x; }", 45, 15, 13);
-}
-
-DEF_TEST(SkSLJITIf, r) {
-    test<int>(r, "int test(int x, int y) { if (x > y) return x; else return y; }", 17, 8, 17);
-    test<int>(r, "int test(int x, int y) { if (x > y) return x; else return y; }", 8, 17, 17);
-    test<int>(r, "int test(int x, int y) { if (x > y) if (x > 0) return x; else return -x; "
-                 "else if (y > 0) return y; else return -y; }", -8, -17, 8);
-}
-
-DEF_TEST(SkSLJITTernary, r) {
-    test<int>(r, "int test(int x, int y) { return x > y ? x : y; }", 17, 8, 17);
-    test<int>(r, "int test(int x, int y) { return x > y ? x : y; }", 8, 17, 17);
-    test<int>(r, "int test(int x, int y) { return x > y ? (x > 0 ? x : -x) :"
-                 "(y > 0 ? y : -y); }", -8, -17, 8);
-}
-
-DEF_TEST(SkSLJITFor, r) {
-    test<int>(r, "int test(int x, int y) {"
-                 "    int result = 0;"
-                 "    for (int i = 0; i < x; ++i)"
-                 "        result += y;"
-                 "    return result;"
-                 "}", 124, 17, 2108);
-}
-
-DEF_TEST(SkSLJITDo, r) {
-    test<int>(r, "int test(int x, int y) {"
-                 "    int result = -10;"
-                 "    do { result = 0; } while (false);"
-                 "    do { result += x; } while (result < y);"
-                 "    return result;"
-                 "}", 96, 200, 288);
-}
-
-DEF_TEST(SkSLJITWhile, r) {
-    test<int>(r, "int test(int x, int y) {"
-                 "    int result = 0;"
-                 "    while (false) { result = -10; }"
-                 "    while (result < y) { result += x; }"
-                 "    return result;"
-                 "}", 96, 200, 288);
-}
-
-#endif