Snap for 6439596 from 9822b047aa4423932fa8dd9ace11cdf16d309d3b to qt-aml-tzdata-release

Change-Id: I54c40fa3b4bfb7d6a40ebc88977abae6a34e1657
diff --git a/Android.bp b/Android.bp
index 2742741..d90d40a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -270,6 +270,8 @@
     // Treble configuration
     shared_libs: [
         "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
         "libutilscallstack",
         "libutils",
         "android.hardware.renderscript@1.0",
diff --git a/build_rs.py b/build_rs.py
index 0416109..8cdbba5 100755
--- a/build_rs.py
+++ b/build_rs.py
@@ -18,6 +18,7 @@
 
 import argparse
 import glob
+import multiprocessing
 import os
 import shutil
 import subprocess
@@ -78,6 +79,7 @@
     env['TARGET_BUILD_VARIANT'] = 'userdebug'
     env['TARGET_PRODUCT'] = product
 
+    jobs_arg = '-j{}'.format(multiprocessing.cpu_count())
     targets = [
         # PHONY target specified in frameworks/rs/Android.mk.
         'rs-prebuilts-full',
@@ -86,7 +88,7 @@
             'android-support-v8-renderscript_intermediates/classes.jar')
     ]
     subprocess.check_call(
-        ['build/soong/soong_ui.bash', '--make-mode'] + targets, cwd=android_path(), env=env)
+        ['make', jobs_arg] + targets, cwd=android_path(), env=env)
 
 
 def package_toolchain(build_dir, build_name, host, dist_dir):
diff --git a/cpp/Android.bp b/cpp/Android.bp
index 9d9041c..31cb3f8 100644
--- a/cpp/Android.bp
+++ b/cpp/Android.bp
@@ -6,9 +6,7 @@
 
     include_dirs: [
         "frameworks/rs",
-    ],
-    header_libs: [
-        "jni_headers",
+        "libnativehelper/include_jni",
     ],
 
     cflags: [
@@ -65,6 +63,7 @@
     shared_libs: [
         "libdl",
         "liblog",
+        "libz",
     ],
 }
 
@@ -72,15 +71,8 @@
     name: "libRScpp",
     defaults: ["libRScpp-defaults"],
 
-    header_libs: [
-        "libarect_headers",
-        "libbase_headers",
-        "libgui_headers",
-        "libnativebase_headers",
-        "libnativewindow_headers",
-    ],
-
     shared_libs: [
+        "libgui",
         "libutils",
     ],
 
diff --git a/cpu_ref/Android.bp b/cpu_ref/Android.bp
index c409989..e929a9c 100644
--- a/cpu_ref/Android.bp
+++ b/cpu_ref/Android.bp
@@ -73,14 +73,15 @@
         },
 
         x86: {
-            cflags: ["-DARCH_X86_HAVE_SSSE3"],
-            srcs: ["rsCpuIntrinsics_x86.cpp"],
+            ssse3: {
+                cflags: ["-DARCH_X86_HAVE_SSSE3"],
+                srcs: ["rsCpuIntrinsics_x86.cpp"],
+            },
         },
         x86_64: {
-            cflags: ["-DARCH_X86_HAVE_SSSE3"],
-            srcs: ["rsCpuIntrinsics_x86.cpp"],
-	    avx2: {
-                cflags: ["-DARCH_X86_HAVE_AVX2", "-mavx2", "-mfma"],
+            ssse3: {
+                cflags: ["-DARCH_X86_HAVE_SSSE3"],
+                srcs: ["rsCpuIntrinsics_x86.cpp"],
             },
         },
     },
diff --git a/cpu_ref/rsCpuExecutable.cpp b/cpu_ref/rsCpuExecutable.cpp
index 63008ba..87c791a 100644
--- a/cpu_ref/rsCpuExecutable.cpp
+++ b/cpu_ref/rsCpuExecutable.cpp
@@ -207,39 +207,27 @@
     // location for shared libraries first.
     loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName, alreadyLoaded);
 
-    if (loaded != nullptr) {
-       return loaded;
-    }
-    ALOGE("Unable to open shared library (%s): %s", scriptSOName.c_str(), dlerror());
+    if (loaded == nullptr) {
+        ALOGE("Unable to open shared library (%s): %s",
+              scriptSOName.c_str(), dlerror());
 
 #ifdef RS_COMPATIBILITY_LIB
-    // Re-trying without absolute path.
-    // For RS support lib, the shared object may not be extracted from the apk.
-    // In order to access that, we need to load the library without specifying
-    // the absolute path.
-    std::string scriptSONameApk("librs.");
-    scriptSONameApk.append(resName);
-    scriptSONameApk.append(".so");
-    loaded = loadSOHelper(scriptSONameApk.c_str(), cacheDir, resName);
-    if (loaded != nullptr) {
-        return loaded;
-    }
-    ALOGE("Unable to open APK shared library (%s): %s", scriptSONameApk.c_str(), dlerror());
-
-    // One final attempt to find the library in "/system/lib".
-    // We do this to allow bundled applications to use the compatibility
-    // library fallback path. Those applications don't have a private
-    // library path, so they need to install to the system directly.
-    // Note that this is really just a testing path.
-    std::string scriptSONameSystem("/system/lib/librs.");
-    scriptSONameSystem.append(resName);
-    scriptSONameSystem.append(".so");
-    loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir, resName);
-    if (loaded == nullptr) {
-        ALOGE("Unable to open system shared library (%s): %s",
-              scriptSONameSystem.c_str(), dlerror());
-    }
+        // One final attempt to find the library in "/system/lib".
+        // We do this to allow bundled applications to use the compatibility
+        // library fallback path. Those applications don't have a private
+        // library path, so they need to install to the system directly.
+        // Note that this is really just a testing path.
+        std::string scriptSONameSystem("/system/lib/librs.");
+        scriptSONameSystem.append(resName);
+        scriptSONameSystem.append(".so");
+        loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
+                              resName);
+        if (loaded == nullptr) {
+            ALOGE("Unable to open system shared library (%s): %s",
+                  scriptSONameSystem.c_str(), dlerror());
+        }
 #endif
+    }
 
     return loaded;
 }
@@ -307,12 +295,10 @@
 
     void *loaded = nullptr;
 
-#ifndef RS_COMPATIBILITY_LIB
     // Skip everything if we don't even have the original library available.
     if (access(origName, F_OK) != 0) {
         return nullptr;
     }
-#endif  // RS_COMPATIBILITY_LIB
 
     // Common path is that we have not loaded this Script/library before.
     if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
diff --git a/cpu_ref/rsCpuIntrinsicResize.cpp b/cpu_ref/rsCpuIntrinsicResize.cpp
index 8a3dd1a..ff42d79 100644
--- a/cpu_ref/rsCpuIntrinsicResize.cpp
+++ b/cpu_ref/rsCpuIntrinsicResize.cpp
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-#if defined(ARCH_X86_HAVE_AVX2)
-#include <stdint.h>
-#include <x86intrin.h>
-#include <xmmintrin.h>
-#endif
 
 #include "rsCpuIntrinsic.h"
 #include "rsCpuIntrinsicInlines.h"
@@ -83,20 +78,10 @@
             + x * (3.f * (p1 - p2) + p3 - p0)));
 }
 
-
-#if defined(ARCH_X86_HAVE_AVX2)
-static float cubicInterpolate(float p0,float p1,float p2,float p3 , float x) {
-   return p1 + 0.5f * x * (p2 - p0 + x * (2.f * p0 - 5.f * p1 +
-           _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(4.f), _mm_set1_ps(p2),_mm_set1_ps(p3)))
-           + x * (_mm_cvtss_f32(_mm_fmadd_ss (_mm_set1_ps(3.f),_mm_set1_ps(p1 - p2),_mm_set1_ps(p3 - p0))))));
-
-}
-#else
 static float cubicInterpolate(float p0,float p1,float p2,float p3 , float x) {
     return p1 + 0.5f * x * (p2 - p0 + x * (2.f * p0 - 5.f * p1 + 4.f * p2 - p3
             + x * (3.f * (p1 - p2) + p3 - p0)));
 }
-#endif
 
 static uchar4 OneBiCubic(const uchar4 *yp0, const uchar4 *yp1, const uchar4 *yp2, const uchar4 *yp3,
                          float xf, float yf, int width) {
@@ -332,14 +317,7 @@
     const int srcWidth = cp->mAlloc->mHal.drvState.lod[0].dimX;
     const size_t stride = cp->mAlloc->mHal.drvState.lod[0].stride;
 
-
-#if defined(ARCH_X86_HAVE_AVX2)
-    float yf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(info->current.y + 0.5f),_mm_set1_ps(cp->scaleY), _mm_set1_ps(0.5f)));
-#else
     float yf = (info->current.y + 0.5f) * cp->scaleY - 0.5f;
-#endif
-
-
     int starty = (int) floor(yf - 1);
     yf = yf - floor(yf);
     int maxy = srcHeight - 1;
@@ -385,11 +363,7 @@
 #endif
 
     while(x1 < x2) {
-#if defined(ARCH_X86_HAVE_AVX2)
-        float xf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(x1 + 0.5f) , _mm_set1_ps(cp->scaleX) , _mm_set1_ps(0.5f)));
-#else
         float xf = (x1 + 0.5f) * cp->scaleX - 0.5f;
-#endif
         *out = OneBiCubic(yp0, yp1, yp2, yp3, xf, yf, srcWidth);
         out++;
         x1++;
@@ -410,13 +384,7 @@
     const int srcWidth = cp->mAlloc->mHal.drvState.lod[0].dimX;
     const size_t stride = cp->mAlloc->mHal.drvState.lod[0].stride;
 
-
-#if defined(ARCH_X86_HAVE_AVX2)
-    float yf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(info->current.y + 0.5f),_mm_set1_ps(cp->scaleY), _mm_set1_ps(0.5f)));
-#else
     float yf = (info->current.y + 0.5f) * cp->scaleY - 0.5f;
-#endif
-
     int starty = (int) floor(yf - 1);
     yf = yf - floor(yf);
     int maxy = srcHeight - 1;
@@ -462,12 +430,7 @@
 #endif
 
     while(x1 < x2) {
-
-#if defined(ARCH_X86_HAVE_AVX2)
-        float xf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(x1 + 0.5f) , _mm_set1_ps(cp->scaleX) , _mm_set1_ps(0.5f)));
-#else
         float xf = (x1 + 0.5f) * cp->scaleX - 0.5f;
-#endif
         *out = OneBiCubic(yp0, yp1, yp2, yp3, xf, yf, srcWidth);
         out++;
         x1++;
@@ -488,13 +451,7 @@
     const int srcWidth = cp->mAlloc->mHal.drvState.lod[0].dimX;
     const size_t stride = cp->mAlloc->mHal.drvState.lod[0].stride;
 
-
-#if defined(ARCH_X86_HAVE_AVX2)
-    float yf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(info->current.y + 0.5f),_mm_set1_ps(cp->scaleY), _mm_set1_ps(0.5f)));
-#else
     float yf = (info->current.y + 0.5f) * cp->scaleY - 0.5f;
-#endif
-
     int starty = (int) floor(yf - 1);
     yf = yf - floor(yf);
     int maxy = srcHeight - 1;
@@ -540,13 +497,7 @@
 #endif
 
     while(x1 < x2) {
-
-#if defined(ARCH_X86_HAVE_AVX2)
-        float xf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(x1 + 0.5f) , _mm_set1_ps(cp->scaleX) , _mm_set1_ps(0.5f)));
-#else
         float xf = (x1 + 0.5f) * cp->scaleX - 0.5f;
-#endif
-
         *out = OneBiCubic(yp0, yp1, yp2, yp3, xf, yf, srcWidth);
         out++;
         x1++;
@@ -567,12 +518,7 @@
     const int srcWidth = cp->mAlloc->mHal.drvState.lod[0].dimX;
     const size_t stride = cp->mAlloc->mHal.drvState.lod[0].stride;
 
-#if defined(ARCH_X86_HAVE_AVX2)
-    float yf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(info->current.y + 0.5f),_mm_set1_ps(cp->scaleY), _mm_set1_ps(0.5f)));
-#else
     float yf = (info->current.y + 0.5f) * cp->scaleY - 0.5f;
-#endif
-
     int starty = (int) floor(yf - 1);
     yf = yf - floor(yf);
     int maxy = srcHeight - 1;
@@ -591,13 +537,7 @@
     uint32_t x2 = xend;
 
     while(x1 < x2) {
-
-#if defined(ARCH_X86_HAVE_AVX2)
-        float xf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(x1 + 0.5f) , _mm_set1_ps(cp->scaleX) , _mm_set1_ps(0.5f)));
-#else
         float xf = (x1 + 0.5f) * cp->scaleX - 0.5f;
-#endif
-
         *out = OneBiCubic(yp0, yp1, yp2, yp3, xf, yf, srcWidth);
         out++;
         x1++;
@@ -618,13 +558,7 @@
     const int srcWidth = cp->mAlloc->mHal.drvState.lod[0].dimX;
     const size_t stride = cp->mAlloc->mHal.drvState.lod[0].stride;
 
-
-#if defined(ARCH_X86_HAVE_AVX2)
-    float yf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(info->current.y + 0.5f),_mm_set1_ps(cp->scaleY), _mm_set1_ps(0.5f)));
-#else
     float yf = (info->current.y + 0.5f) * cp->scaleY - 0.5f;
-#endif
-
     int starty = (int) floor(yf - 1);
     yf = yf - floor(yf);
     int maxy = srcHeight - 1;
@@ -643,13 +577,7 @@
     uint32_t x2 = xend;
 
     while(x1 < x2) {
-
-#if defined(ARCH_X86_HAVE_AVX2)
-        float xf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(x1 + 0.5f) , _mm_set1_ps(cp->scaleX) , _mm_set1_ps(0.5f)));
-#else
         float xf = (x1 + 0.5f) * cp->scaleX - 0.5f;
-#endif
-
         *out = OneBiCubic(yp0, yp1, yp2, yp3, xf, yf, srcWidth);
         out++;
         x1++;
@@ -670,13 +598,7 @@
     const int srcWidth = cp->mAlloc->mHal.drvState.lod[0].dimX;
     const size_t stride = cp->mAlloc->mHal.drvState.lod[0].stride;
 
-
-#if defined(ARCH_X86_HAVE_AVX2)
-    float yf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(info->current.y + 0.5f),_mm_set1_ps(cp->scaleY), _mm_set1_ps(0.5f)));
-#else
     float yf = (info->current.y + 0.5f) * cp->scaleY - 0.5f;
-#endif
-
     int starty = (int) floor(yf - 1);
     yf = yf - floor(yf);
     int maxy = srcHeight - 1;
@@ -695,13 +617,7 @@
     uint32_t x2 = xend;
 
     while(x1 < x2) {
-
-#if defined(ARCH_X86_HAVE_AVX2)
-        float xf = _mm_cvtss_f32(_mm_fmsub_ss(_mm_set1_ps(x1 + 0.5f) , _mm_set1_ps(cp->scaleX) , _mm_set1_ps(0.5f)));
-#else
         float xf = (x1 + 0.5f) * cp->scaleX - 0.5f;
-#endif
-
         *out = OneBiCubic(yp0, yp1, yp2, yp3, xf, yf, srcWidth);
         out++;
         x1++;
diff --git a/cpu_ref/rsCpuRuntimeMath.cpp b/cpu_ref/rsCpuRuntimeMath.cpp
index 9f14e67..29ea658 100644
--- a/cpu_ref/rsCpuRuntimeMath.cpp
+++ b/cpu_ref/rsCpuRuntimeMath.cpp
@@ -99,7 +99,7 @@
 
 float SC_randf2(float min, float max) {
     float r = (float)rand();
-    r /= (float)RAND_MAX;
+    r /= RAND_MAX;
     r = r * (max - min) + min;
     return r;
 }
diff --git a/rsov/Android.mk b/rsov/Android.mk
new file mode 100644
index 0000000..4afbb7c
--- /dev/null
+++ b/rsov/Android.mk
@@ -0,0 +1,12 @@
+#=====================================================================
+# Include Subdirectories
+#=====================================================================
+
+# Not building RSoV modules in PDK builds, as libSPIRV is not available in PDK.
+ifneq ($(TARGET_BUILD_PDK), true)
+
+LOCAL_PATH:=$(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+endif # TARGET_BUILD_PDK
diff --git a/rsov/compiler/.clang-format b/rsov/compiler/.clang-format
new file mode 100644
index 0000000..21c0dd4
--- /dev/null
+++ b/rsov/compiler/.clang-format
@@ -0,0 +1,95 @@
+---
+Language:        Cpp
+# BasedOnStyle:  LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:   
+  AfterClass:      false
+  AfterControlStatement: false
+  AfterEnum:       false
+  AfterFunction:   false
+  AfterNamespace:  false
+  AfterObjCDeclaration: false
+  AfterStruct:     false
+  AfterUnion:      false
+  BeforeCatch:     false
+  BeforeElse:      false
+  IndentBraces:    false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeCategories: 
+  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
+    Priority:        2
+  - Regex:           '^(<|"(gtest|isl|json)/)'
+    Priority:        3
+  - Regex:           '.*'
+    Priority:        1
+IncludeIsMainRegex: '$'
+IndentCaseLabels: false
+IndentWidth:     2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments:  true
+SortIncludes:    true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Cpp11
+TabWidth:        8
+UseTab:          Never
+...
+
diff --git a/rsov/compiler/Android.bp b/rsov/compiler/Android.bp
new file mode 100644
index 0000000..61dd921
--- /dev/null
+++ b/rsov/compiler/Android.bp
@@ -0,0 +1,109 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//=====================================================================
+// Unit tests for Wrapper module
+//=====================================================================
+
+cc_test_host {
+    name: "Wrapper_test",
+    defaults: [
+        "llvm-defaults",
+        "spirit_defaults",
+    ],
+
+    srcs: [
+        "Builtin.cpp",
+        "Context.cpp",
+        "GlobalAllocSPIRITPass.cpp",
+        "RSAllocationUtils.cpp",
+        "Wrapper.cpp",
+        "Wrapper_test.cpp",
+    ],
+
+    shared_libs: [
+        "libLLVM_android",
+        "libbcinfo",
+        "libspirit",
+    ],
+}
+
+//=====================================================================
+// Unit tests for Builtin module
+//=====================================================================
+
+cc_test_host {
+    name: "Builtin_test",
+    defaults: ["spirit_defaults"],
+
+    srcs: [
+        "Builtin.cpp",
+        "Builtin_test.cpp",
+    ],
+
+    shared_libs: ["libspirit"],
+}
+
+//=====================================================================
+// Host and Device Executable rs2spirv
+//=====================================================================
+
+cc_binary {
+    name: "rs2spirv",
+    defaults: [
+        "llvm-defaults",
+        "spirit_defaults",
+    ],
+    host_supported: true,
+    device_supported: false,
+
+    srcs: [
+        "rs2spirv.cpp",
+        "Builtin.cpp",
+        "Context.cpp",
+        "GlobalAllocPass.cpp",
+        "GlobalAllocSPIRITPass.cpp",
+        "GlobalMergePass.cpp",
+        "InlinePreparationPass.cpp",
+        "RemoveNonkernelsPass.cpp",
+        "RSAllocationUtils.cpp",
+        "RSSPIRVWriter.cpp",
+        "Wrapper.cpp",
+    ],
+
+    // TODO: fix the remaining warnings
+    cflags: [
+        "-D_SPIRV_LLVM_API",
+        "-Wno-error=pessimizing-move",
+        "-Wno-error=unused-variable",
+        "-Wno-error=unused-private-field",
+        "-Wno-error=unused-function",
+        "-Wno-error=dangling-else",
+        "-Wno-error=ignored-qualifiers",
+        "-Wno-error=non-virtual-dtor",
+
+        // For debug builds
+        //"-O0",
+        //"-DRS2SPIRV_DEBUG=1",
+    ],
+
+    shared_libs: [
+        "libLLVM_android",
+        "libbcinfo",
+        "libSPIRV",
+        "libspirit",
+    ],
+}
diff --git a/rsov/compiler/Builtin.cpp b/rsov/compiler/Builtin.cpp
new file mode 100644
index 0000000..02f7546
--- /dev/null
+++ b/rsov/compiler/Builtin.cpp
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builtin.h"
+
+#include "cxxabi.h"
+#include "spirit.h"
+#include "transformer.h"
+
+#include <stdint.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+namespace {
+
+Instruction *translateClampVector(const char *name,
+                                  const FunctionCallInst *call, Transformer *tr,
+                                  Builder *b, Module *m) {
+  int width = name[10] - '0';
+  if (width < 2 || width > 4) {
+    return nullptr;
+  }
+
+  uint32_t extOpCode = 0;
+  switch (name[strlen(name) - 1]) {
+  case 'f':
+    extOpCode = 43;
+    break; // FClamp
+  // TODO: Do we get _Z5clampDV_uuu at all? Does LLVM convert u into i?
+  case 'u':
+    extOpCode = 44;
+    break; // UClamp
+  case 'i':
+    extOpCode = 45;
+    break; // SClamp
+  default:
+    return nullptr;
+  }
+
+  std::vector<IdRef> minConstituents(width, call->mOperand2[1]);
+  std::unique_ptr<Instruction> min(
+      b->MakeCompositeConstruct(call->mResultType, minConstituents));
+  tr->insert(min.get());
+
+  std::vector<IdRef> maxConstituents(width, call->mOperand2[2]);
+  std::unique_ptr<Instruction> max(
+      b->MakeCompositeConstruct(call->mResultType, maxConstituents));
+  tr->insert(max.get());
+
+  std::vector<IdRef> extOpnds = {call->mOperand2[0], min.get(), max.get()};
+  return b->MakeExtInst(call->mResultType, m->getGLExt(), extOpCode, extOpnds);
+}
+
+Instruction *translateExtInst(const uint32_t extOpCode,
+                              const FunctionCallInst *call, Builder *b,
+                              Module *m) {
+  return b->MakeExtInst(call->mResultType, m->getGLExt(), extOpCode,
+                        {call->mOperand2[0]});
+}
+
+} // anonymous namespace
+
+typedef std::function<Instruction *(const char *, const FunctionCallInst *,
+                                    Transformer *, Builder *, Module *)>
+    InstTrTy;
+
+class BuiltinLookupTable {
+public:
+  BuiltinLookupTable() {
+    for (sNameCode const *p = &mFPMathFuncOpCode[0]; p->name; p++) {
+      const char *name = p->name;
+      const uint32_t extOpCode = p->code;
+      addMapping(name, {"*"}, {{"float+"}}, {1, 2, 3, 4},
+                 [extOpCode](const char *, const FunctionCallInst *call,
+                             Transformer *, Builder *b, Module *m) {
+                   return translateExtInst(extOpCode, call, b, m);
+                 });
+    }
+
+    addMapping("abs", {"*"}, {{"int+"}, {"char+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 return translateExtInst(5, call, b, m); // SAbs
+               });
+
+    addMapping("clamp", {"*"},
+               {{"int+", "int", "int"}, {"float+", "float", "float"}},
+               {1, 2, 3, 4}, [](const char *name, const FunctionCallInst *call,
+                                Transformer *tr, Builder *b, Module *m) {
+                 return translateClampVector(name, call, tr, b, m);
+               });
+
+    addMapping("convert", {"char+", "int+", "uchar+", "uint+"},
+               {{"char+"}, {"int+"}, {"uchar+"}, {"uint+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *) -> Instruction * {
+                 return b->MakeUConvert(call->mResultType, call->mOperand2[0]);
+               });
+
+    addMapping(
+        "convert", {"char+", "int+", "uchar+", "uint+"}, {{"float+"}},
+        {1, 2, 3, 4}, [](const char *, const FunctionCallInst *call,
+                         Transformer *, Builder *b, Module *) -> Instruction * {
+          return b->MakeConvertFToU(call->mResultType, call->mOperand2[0]);
+        });
+
+    addMapping(
+        "convert", {"float+"}, {{"char+"}, {"int+"}, {"uchar+"}, {"uint+"}},
+        {1, 2, 3, 4}, [](const char *, const FunctionCallInst *call,
+                         Transformer *, Builder *b, Module *) {
+          return b->MakeConvertUToF(call->mResultType, call->mOperand2[0]);
+        });
+
+    addMapping("dot", {"*"}, {{"float+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *) {
+                 return b->MakeDot(call->mResultType, call->mOperand2[0],
+                                   call->mOperand2[1]);
+               });
+
+    addMapping("min", {"*"}, {{"uint+"}, {"uchar+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 return translateExtInst(38, call, b, m); // UMin
+               });
+
+    addMapping("min", {"*"}, {{"int+"}, {"char+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 return translateExtInst(39, call, b, m); // SMin
+               });
+
+    addMapping("max", {"*"}, {{"uint+"}, {"uchar+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 return translateExtInst(41, call, b, m); // UMax
+               });
+
+    addMapping("max", {"*"}, {{"int+"}, {"char+"}}, {1, 2, 3, 4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 return translateExtInst(42, call, b, m); // SMax
+               });
+
+    addMapping("rsUnpackColor8888", {"*"}, {{"uchar+"}}, {4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 auto cast = b->MakeBitcast(m->getUnsignedIntType(32),
+                                            call->mOperand2[0]);
+                 return b->MakeExtInst(call->mResultType, m->getGLExt(), 64,
+                                       {cast}); // UnpackUnorm4x8
+               });
+
+    addMapping("rsPackColorTo8888", {"*"}, {{"float+"}}, {4},
+               [](const char *, const FunctionCallInst *call, Transformer *,
+                  Builder *b, Module *m) {
+                 // PackUnorm4x8
+                 auto packed = b->MakeExtInst(call->mResultType, m->getGLExt(),
+                                              55, {call->mOperand2[0]});
+                 return b->MakeBitcast(
+                     m->getVectorType(m->getUnsignedIntType(8), 4), packed);
+               });
+  }
+
+  static const BuiltinLookupTable &getInstance() {
+    static BuiltinLookupTable table;
+    return table;
+  }
+
+  void addMapping(const char *funcName,
+                  const std::vector<std::string> &retTypes,
+                  const std::vector<std::vector<std::string>> &argTypes,
+                  const std::vector<uint8_t> &vecWidths, InstTrTy fp) {
+    for (auto width : vecWidths) {
+      for (auto retType : retTypes) {
+        std::string suffixed(funcName);
+        if (retType != "*") {
+          if (retType.back() == '+') {
+            retType.pop_back();
+            if (width > 1) {
+              retType.append(1, '0' + width);
+            }
+          }
+          suffixed.append("_").append(retType);
+        }
+
+        for (auto argList : argTypes) {
+          std::string args("(");
+          bool first = true;
+          for (auto argType : argList) {
+            if (first) {
+              first = false;
+            } else {
+              args.append(", ");
+            }
+            if (argType.front() == 'u') {
+              argType.replace(0, 1, "unsigned ");
+            }
+            if (argType.back() == '+') {
+              argType.pop_back();
+              if (width > 1) {
+                argType.append(" vector[");
+                argType.append(1, '0' + width);
+                argType.append("]");
+              }
+            }
+            args.append(argType);
+          }
+          args.append(")");
+          mFuncNameMap[suffixed + args] = fp;
+        }
+      }
+    }
+  }
+
+  InstTrTy lookupTranslation(const char *mangled) const {
+    const char *demangled =
+        __cxxabiv1::__cxa_demangle(mangled, nullptr, nullptr, nullptr);
+
+    if (!demangled) {
+      // All RS runtime/builtin functions are overloaded, therefore
+      // name-mangled.
+      return nullptr;
+    }
+
+    std::string strDemangled(demangled);
+
+    auto it = mFuncNameMap.find(strDemangled);
+    if (it == mFuncNameMap.end()) {
+      return nullptr;
+    }
+    return it->second;
+  }
+
+private:
+  std::map<std::string, InstTrTy> mFuncNameMap;
+
+  struct sNameCode {
+    const char *name;
+    uint32_t code;
+  };
+
+  static sNameCode constexpr mFPMathFuncOpCode[] = {
+      {"abs", 4},        {"sin", 13},   {"cos", 14},   {"tan", 15},
+      {"asin", 16},      {"acos", 17},  {"atan", 18},  {"sinh", 19},
+      {"cosh", 20},      {"tanh", 21},  {"asinh", 22}, {"acosh", 23},
+      {"atanh", 24},     {"atan2", 25}, {"pow", 26},   {"exp", 27},
+      {"log", 28},       {"exp2", 29},  {"log2", 30},  {"sqrt", 31},
+      {"modf", 35},      {"min", 37},   {"max", 40},   {"length", 66},
+      {"normalize", 69}, {nullptr, 0},
+  };
+
+}; // BuiltinLookupTable
+
+BuiltinLookupTable::sNameCode constexpr BuiltinLookupTable::mFPMathFuncOpCode[];
+
+class BuiltinTransformer : public Transformer {
+public:
+  // BEGIN: cleanup unrelated to builtin functions, but necessary for LLVM-SPIRV
+  // converter generated code.
+
+  // TODO: Move these in its own pass
+
+  std::vector<uint32_t> runAndSerialize(Module *module, int *error) override {
+    module->addExtInstImport("GLSL.std.450");
+    return Transformer::runAndSerialize(module, error);
+  }
+
+  Instruction *transform(CapabilityInst *inst) override {
+    // Remove capabilities Address, Linkage, and Kernel.
+    if (inst->mOperand1 == Capability::Addresses ||
+        inst->mOperand1 == Capability::Linkage ||
+        inst->mOperand1 == Capability::Kernel) {
+      return nullptr;
+    }
+    return inst;
+  }
+
+  Instruction *transform(ExtInstImportInst *inst) override {
+    if (inst->mOperand1.compare("OpenCL.std") == 0) {
+      return nullptr;
+    }
+    return inst;
+  }
+
+  Instruction *transform(InBoundsPtrAccessChainInst *inst) override {
+    // Transform any OpInBoundsPtrAccessChain instruction to an
+    // OpInBoundsAccessChain instruction, since the former is not allowed by
+    // the Vulkan validation rules.
+    auto newInst = mBuilder.MakeInBoundsAccessChain(inst->mResultType,
+                                                    inst->mOperand1,
+                                                    inst->mOperand3);
+    newInst->setId(inst->getId());
+    return newInst;
+  }
+
+  Instruction *transform(SourceInst *inst) override {
+    if (inst->mOperand1 == SourceLanguage::Unknown) {
+      return nullptr;
+    }
+    return inst;
+  }
+
+  Instruction *transform(DecorateInst *inst) override {
+    if (inst->mOperand2 == Decoration::LinkageAttributes ||
+        inst->mOperand2 == Decoration::Alignment) {
+      return nullptr;
+    }
+    return inst;
+  }
+
+  // END: cleanup unrelated to builtin functions
+
+  Instruction *transform(FunctionCallInst *call) {
+    FunctionInst *func =
+        static_cast<FunctionInst *>(call->mOperand1.mInstruction);
+    // TODO: attach name to the instruction to avoid linear search in the debug
+    // section, i.e.,
+    // const char *name = func->getName();
+    const char *name = getModule()->lookupNameByInstruction(func);
+    if (!name) {
+      return call;
+    }
+
+    // Maps name into a SPIR-V instruction
+    auto fpTranslate =
+        BuiltinLookupTable::getInstance().lookupTranslation(name);
+    if (!fpTranslate) {
+      return call;
+    }
+    Instruction *inst = fpTranslate(name, call, this, &mBuilder, getModule());
+
+    if (inst) {
+      inst->setId(call->getId());
+    }
+
+    return inst;
+  }
+
+private:
+  Builder mBuilder;
+};
+
+} // namespace spirit
+} // namespace android
+
+namespace rs2spirv {
+
+android::spirit::Pass *CreateBuiltinPass() {
+  return new android::spirit::BuiltinTransformer();
+}
+
+} // namespace rs2spirv
+
diff --git a/rsov/compiler/Builtin.h b/rsov/compiler/Builtin.h
new file mode 100644
index 0000000..2a28097
--- /dev/null
+++ b/rsov/compiler/Builtin.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUILTIN_H
+#define BUILTIN_H
+
+namespace android {
+namespace spirit {
+
+class Pass;
+
+} // namespace spirit
+} // namespace android
+
+namespace rs2spirv {
+
+android::spirit::Pass *CreateBuiltinPass();
+
+} // namespace rs2spirv
+
+#endif // BUILTIN_H
diff --git a/rsov/compiler/Builtin_test.cpp b/rsov/compiler/Builtin_test.cpp
new file mode 100644
index 0000000..256703b
--- /dev/null
+++ b/rsov/compiler/Builtin_test.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Builtin.h"
+
+#include "file_utils.h"
+#include "pass_queue.h"
+#include "spirit.h"
+#include "test_utils.h"
+#include "gtest/gtest.h"
+
+namespace android {
+namespace spirit {
+
+TEST(BuiltinTest, testBuiltinTranslation) {
+  const std::string testFile("greyscale.spv");
+  const std::string testDataPath(
+      "frameworks/rs/rsov/compiler/spirit/test_data/");
+  const std::string &fullPath = getAbsolutePath(testDataPath + testFile);
+  auto words = readFile<uint32_t>(fullPath);
+
+  PassQueue passes;
+  passes.append(rs2spirv::CreateBuiltinPass());
+  auto words1 = passes.run(words);
+
+  std::unique_ptr<Module> m1(Deserialize<Module>(words1));
+
+  ASSERT_NE(nullptr, m1);
+}
+
+} // spirit
+} // android
diff --git a/rsov/compiler/Context.cpp b/rsov/compiler/Context.cpp
new file mode 100644
index 0000000..858aa8a
--- /dev/null
+++ b/rsov/compiler/Context.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Context.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <limits>
+
+#define DEBUG_TYPE "rs2spirv-context"
+
+namespace rs2spirv {
+
+Context &Context::getInstance() {
+  static Context c;
+  return c;
+}
+
+Context::Context() : mInitialized(false) {}
+
+bool Context::Initialize(std::unique_ptr<bcinfo::MetadataExtractor> ME) {
+  if (mInitialized) {
+    return true;
+  }
+
+  mMetadata = std::move(ME);
+
+  if (!mMetadata->extract()) {
+    llvm::errs() << "cannot extract metadata\n";
+    return false;
+  }
+
+  const char **varNames = mMetadata->getExportVarNameList();
+  size_t varCount = mMetadata->getExportVarCount();
+  mExportVarIndices.resize(varCount);
+
+  // Builds the lookup table from a variable name to its slot number
+  for (size_t slot = 0; slot < varCount; slot++) {
+    std::string varName(varNames[slot]);
+    mVarNameToSlot.insert(std::make_pair(varName, (uint32_t)slot));
+  }
+
+  const size_t kernelCount = mMetadata->getExportForEachSignatureCount();
+  const char **kernelNames = mMetadata->getExportForEachNameList();
+  for (size_t slot = 0; slot < kernelCount; slot++) {
+    mForEachNameToSlot.insert(std::make_pair(kernelNames[slot], slot));
+  }
+
+  mInitialized = true;
+
+  return true;
+}
+
+void Context::addExportVarIndex(const char *varName, uint32_t index) {
+  DEBUG(llvm::dbgs() << varName << " index=" << index << '\n');
+  const uint32_t slot = getSlotForExportVar(varName);
+  if (slot == std::numeric_limits<uint32_t>::max()) {
+    return;
+  }
+  addExportVarIndex(slot, index);
+}
+
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/Context.h b/rsov/compiler/Context.h
new file mode 100644
index 0000000..9b38226
--- /dev/null
+++ b/rsov/compiler/Context.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_CONTEXT_H
+#define RS2SPIRV_CONTEXT_H
+
+#include "RSAllocationUtils.h"
+#include "bcinfo/MetadataExtractor.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <stdint.h>
+
+// Declare a friend relationship in a class with a test. Used rather that
+// FRIEND_TEST to avoid globally importing gtest/gtest.h into the main
+// RSoV header files.
+#ifdef __HOST__
+#define RSOV_FRIEND_TEST(test_set_name, individual_test)                       \
+  friend class test_set_name##_##individual_test##_Test
+#else
+#define RSOV_FRIEND_TEST(test_set_name, individual_test)
+#endif // __HOST__
+
+namespace bcinfo {
+class MetadataExtractor;
+}
+
+namespace llvm {
+class Module;
+}
+
+namespace rs2spirv {
+
+// A singleton that keeps state during the compilation from RS LLVM bitcode to
+// SPIR-V, which provides quick lookup of metadata and shares information
+// between the passes.
+class Context {
+  RSOV_FRIEND_TEST(ContextTest, testInitialize);
+
+public:
+  static Context &getInstance();
+
+  Context();
+
+  // Initialize the internal data struture such as the slot number lookup table,
+  // etc.
+  bool Initialize(std::unique_ptr<bcinfo::MetadataExtractor> ME);
+
+  // Returns the total number of exported variables
+  uint32_t getNumExportVar() const { return mExportVarIndices.size(); }
+
+  // Adds the mapping from the slot number of an exported variable to the index
+  // of its field in the global buffer
+  void addExportVarIndex(uint32_t slot, uint32_t index) {
+    mExportVarIndices[slot] = index;
+  }
+
+  // Adds the mapping from the name of an exported variable to the index of its
+  // field in the global buffer
+  void addExportVarIndex(const char *varName, uint32_t index);
+
+  // Given the slot number of an exported variable, returns the index of its
+  // field in the global buffer
+  uint32_t getExportVarIndex(uint32_t slot) const {
+    return mExportVarIndices[slot];
+  }
+
+  void setGlobalSize(uint64_t size) {
+    mGlobalSize = size;
+  }
+
+  uint64_t getGlobalSize() const {
+    return mGlobalSize;
+  }
+
+  // Returns the total number of foreach kernels
+  uint32_t getNumForEachKernel() const { return mForEachNameToSlot.size(); }
+
+  // Checks if a name refers to a foreach kernel function
+  bool isForEachKernel(llvm::StringRef name) const {
+    return mForEachNameToSlot.count(name) != 0;
+  }
+
+  const bcinfo::MetadataExtractor &getMetadata() const { return *mMetadata; }
+
+  llvm::SmallVectorImpl<RSAllocationInfo> &getGlobalAllocs() {
+    return mGlobalAllocs;
+  }
+
+private:
+  uint32_t getSlotForExportVar(const char *varName) {
+    const llvm::StringRef strVarName(varName);
+    auto it = mVarNameToSlot.find(strVarName);
+    if (it == mVarNameToSlot.end()) {
+      return std::numeric_limits<uint32_t>::max();
+    }
+    return it->second;
+  }
+
+  bool mInitialized;
+  // RenderScript metadata embedded in the input LLVM Moduel
+  std::unique_ptr<bcinfo::MetadataExtractor> mMetadata;
+  // A map from exported variable names to their slot numbers
+  llvm::StringMap<uint32_t> mVarNameToSlot;
+  // The size of memory needed to store all global variables (static variables)
+  uint64_t mGlobalSize;
+  // A map from exported foreach kernel names to their slot numbers
+  llvm::StringMap<uint32_t> mForEachNameToSlot;
+  // These are the indices for each exported variable in the global buffer
+  llvm::SmallVector<uint32_t, 8> mExportVarIndices;
+  // For Global Allocations; carries global variable -> metadata offset
+  // mapping from an LLVM pass to a SPIRIT pass
+  llvm::SmallVector<RSAllocationInfo, 8> mGlobalAllocs;
+};
+
+} // namespace rs2spirv
+
+#endif // RS2SPIRV_CONTEXT_H
diff --git a/rsov/compiler/GlobalAllocPass.cpp b/rsov/compiler/GlobalAllocPass.cpp
new file mode 100644
index 0000000..92c441a
--- /dev/null
+++ b/rsov/compiler/GlobalAllocPass.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlobalAllocPass.h"
+
+#include "Context.h"
+#include "RSAllocationUtils.h"
+
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "rs2spirv-global-alloc"
+
+using namespace llvm;
+
+namespace rs2spirv {
+
+namespace {
+bool collectGlobalAllocs(Module &M,
+                         SmallVectorImpl<GlobalVariable *> &GlobalAllocs) {
+  for (auto &GV : M.globals()) {
+    if (!isRSAllocation(GV))
+      continue;
+
+    DEBUG(GV.dump());
+    GlobalAllocs.push_back(&GV);
+  }
+
+  return !GlobalAllocs.empty();
+}
+
+//
+// This pass would enumerate used global rs_allocations (TBD) and
+// lowers calls to accessors of the following type:
+//
+//    rsGetAllocationDimX(g)
+//
+// to
+//
+//    __rsov_rsGetAllocationDimX(some uninque constant identifying g) */
+//
+// Note the __rsov_* variant is used as a marker for another SPIRIT
+// transformations (see GlobalAllocSPIRITPass.cpp) to expand them into
+// SPIR-V instructions that loads the metadata.
+//
+class GlobalAllocPass : public ModulePass {
+public:
+  static char ID;
+  GlobalAllocPass()
+      : ModulePass(ID), Allocs(Context::getInstance().getGlobalAllocs()) {}
+
+  const char *getPassName() const override { return "GlobalAllocPass"; }
+
+  bool runOnModule(Module &M) override {
+    DEBUG(dbgs() << "RS2SPIRVGlobalAllocPass\n");
+    DEBUG(M.dump());
+
+    SmallVector<GlobalVariable *, 8> GlobalAllocs;
+    const bool CollectRes = collectGlobalAllocs(M, GlobalAllocs);
+    if (!CollectRes)
+      return false; // Module not modified.
+
+    SmallVector<RSAllocationCallInfo, 8> Calls;
+    getRSAllocationInfo(M, Allocs);
+    getRSAllocAccesses(Allocs, Calls);
+
+    // Lower the found accessors
+    for (auto &C : Calls) {
+      assert(C.Kind == RSAllocAccessKind::DIMX &&
+             "Unsupported type of accessor call types");
+      solidifyRSAllocAccess(M, C);
+    }
+    // Return true, as the pass modifies module.
+    DEBUG(dbgs() << "RS2SPIRVGlobalAllocPass end\n");
+    return true;
+  }
+
+private:
+  SmallVectorImpl<RSAllocationInfo> &Allocs;
+};
+
+// A simple pass to remove all global allocations forcibly
+class RemoveAllGlobalAllocPass : public ModulePass {
+public:
+  static char ID;
+  RemoveAllGlobalAllocPass() : ModulePass(ID) {}
+  const char *getPassName() const override {
+    return "RemoveAllGlobalAllocPass";
+  }
+
+  bool runOnModule(Module &M) override {
+    DEBUG(dbgs() << "RemoveAllGlobalAllocPass\n");
+    DEBUG(M.dump());
+
+    SmallVector<GlobalVariable *, 8> GlobalAllocs;
+    const bool CollectRes = collectGlobalAllocs(M, GlobalAllocs);
+    if (!CollectRes)
+      return false; // Module not modified.
+    // Remove global allocations
+    for (auto *G : GlobalAllocs) {
+      G->eraseFromParent();
+    }
+    DEBUG(dbgs() << "RemoveAllGlobalAllocPass end\n");
+    DEBUG(M.dump());
+    // Return true, as the pass modifies module.
+    return true;
+  }
+};
+
+} // namespace
+char GlobalAllocPass::ID = 0;
+char RemoveAllGlobalAllocPass::ID = 0;
+
+ModulePass *createRemoveAllGlobalAllocPass() {
+  return new RemoveAllGlobalAllocPass();
+}
+ModulePass *createGlobalAllocPass() { return new GlobalAllocPass(); }
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/GlobalAllocPass.h b/rsov/compiler/GlobalAllocPass.h
new file mode 100644
index 0000000..9312c21
--- /dev/null
+++ b/rsov/compiler/GlobalAllocPass.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_GLOBAL_ALLOC_PASS_H
+#define RS2SPIRV_GLOBAL_ALLOC_PASS_H
+
+namespace llvm {
+class ModulePass;
+} // namespace llvm
+
+namespace rs2spirv {
+
+llvm::ModulePass *createGlobalAllocPass();
+llvm::ModulePass *createRemoveAllGlobalAllocPass();
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/GlobalAllocSPIRITPass.cpp b/rsov/compiler/GlobalAllocSPIRITPass.cpp
new file mode 100644
index 0000000..5d2ab15
--- /dev/null
+++ b/rsov/compiler/GlobalAllocSPIRITPass.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlobalAllocSPIRITPass.h"
+
+#include "Context.h"
+#include "spirit.h"
+#include "transformer.h"
+
+#include <sstream>
+
+namespace android {
+namespace spirit {
+
+namespace {
+
+// Metadata buffer for global allocations
+// struct metadata {
+//  uint32_t element_size;
+//  uint32_t x_size;
+//  uint32_t y_size;
+//  uint32_t unused
+// };
+
+VariableInst *AddGAMetadata(Builder &b, Module *m) {
+  TypeIntInst *UInt32Ty = m->getUnsignedIntType(32);
+  std::vector<Instruction *> metadata{UInt32Ty, UInt32Ty, UInt32Ty, UInt32Ty};
+  auto MetadataStructTy = m->getStructType(metadata.data(), metadata.size());
+  // FIXME: workaround on a weird OpAccessChain member offset problem. Somehow
+  // when given constant indices, OpAccessChain returns pointers that are 4
+  // bytes less than what are supposed to be (at runtime). For now workaround
+  // this with +4 the member offsets.
+  MetadataStructTy->memberDecorate(0, Decoration::Offset)->addExtraOperand(4);
+  MetadataStructTy->memberDecorate(1, Decoration::Offset)->addExtraOperand(8);
+  MetadataStructTy->memberDecorate(2, Decoration::Offset)->addExtraOperand(12);
+  MetadataStructTy->memberDecorate(3, Decoration::Offset)->addExtraOperand(16);
+  // TBD: Implement getArrayType. RuntimeArray requires buffers and hence we
+  // cannot use PushConstant underneath
+  auto MetadataBufSTy = m->getRuntimeArrayType(MetadataStructTy);
+  // Stride of metadata.
+  MetadataBufSTy->decorate(Decoration::ArrayStride)
+      ->addExtraOperand(metadata.size() * sizeof(uint32_t));
+  auto MetadataSSBO = m->getStructType(MetadataBufSTy);
+  MetadataSSBO->decorate(Decoration::BufferBlock);
+  auto MetadataPtrTy = m->getPointerType(StorageClass::Uniform, MetadataSSBO);
+
+  VariableInst *MetadataVar =
+      b.MakeVariable(MetadataPtrTy, StorageClass::Uniform);
+  MetadataVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
+  MetadataVar->decorate(Decoration::Binding)->addExtraOperand(1);
+  m->addVariable(MetadataVar);
+
+  return MetadataVar;
+}
+
+std::string CreateGAIDMetadata(
+    const llvm::SmallVectorImpl<rs2spirv::RSAllocationInfo> &Allocs) {
+
+  std::stringstream mapping;
+  bool printed = false;
+
+  mapping << "{\"__RSoV_GA\": {";
+  for (auto &A : Allocs) {
+    // Skip unused GAs
+    if (!A.hasID()) {
+      continue;
+    }
+    if (printed)
+      mapping << ", ";
+    // "GA name" to the ID of the GA
+    mapping << "\"" << A.VarName.substr(1) << "\":" << A.ID;
+    printed = true;
+  }
+  mapping << "}}";
+
+  if (printed)
+    return mapping.str().c_str();
+  else
+    return "";
+}
+} // anonymous namespace
+
+// Replacing calls to lowered accessors, e.g., __rsov_rsAllocationGetDimX
+// which was created from rsAllocationGetDimX by replacing the allocation
+// with an ID in an earlier LLVM pass (see GlobalAllocationPass.cpp),
+// to access the global allocation metadata.
+//
+// For example, the source code may look like:
+//
+// rs_allocation g;
+// ...
+//    uint32_t foo = rsAllocationGetDimX(g);
+//
+// After the  GlobalAllocPass, it would look like the LLVM IR
+// equivalent of:
+//
+//    uint32_t foo = __rsov_rsAllocationGetDimX(0);
+//
+// After that pass, g is removed, and references in intrinsics
+// to g would be replaced with an assigned unique id (0 here), and
+// rsAllocationGetDimX() would be replaced by __rsov_rsAllocationGetDimX()
+// where the only difference is the argument being replaced by the unique
+// ID. __rsov_rsAllocationGetDimX() does not really exist - it is used
+// as a marker for this pass to work on.
+//
+// After this GAAccessTransformer pass, it would look like (in SPIRIT):
+//
+//   uint32_t foo = Metadata[0].size_x;
+//
+// where the OpFunctionCall to __rsov_rsAllocationGetDim() is replaced by
+// an OpAccessChain and OpLoad from the metadata buffer.
+
+class GAAccessorTransformer : public Transformer {
+public:
+  GAAccessorTransformer()
+      : mBuilder(), mMetadata(nullptr),
+        mAllocs(rs2spirv::Context::getInstance().getGlobalAllocs()) {}
+
+  std::vector<uint32_t> runAndSerialize(Module *module, int *error) override {
+    std::string GAMD = CreateGAIDMetadata(mAllocs);
+    if (GAMD.size() > 0) {
+      module->addString(GAMD.c_str());
+    }
+    mMetadata = AddGAMetadata(mBuilder, module);
+    return Transformer::runAndSerialize(module, error);
+  }
+
+  Instruction *transform(FunctionCallInst *call) {
+    FunctionInst *func =
+        static_cast<FunctionInst *>(call->mOperand1.mInstruction);
+    const char *name = getModule()->lookupNameByInstruction(func);
+    if (!name) {
+      return call;
+    }
+
+    Instruction *inst = nullptr;
+    // Maps name into a SPIR-V instruction
+    // TODO: generalize it to support more accessors
+    if (!strcmp(name, "__rsov_rsAllocationGetDimX")) {
+      TypeIntInst *UInt32Ty = getModule()->getUnsignedIntType(32);
+      // TODO: hardcoded layout
+      auto ConstZero = getModule()->getConstant(UInt32Ty, 0U);
+      auto ConstOne = getModule()->getConstant(UInt32Ty, 1U);
+
+      // TODO: Use constant memory later
+      auto resultPtrType =
+          getModule()->getPointerType(StorageClass::Uniform, UInt32Ty);
+      AccessChainInst *LoadPtr = mBuilder.MakeAccessChain(
+          resultPtrType, mMetadata, {ConstZero, ConstZero, ConstOne});
+      insert(LoadPtr);
+
+      inst = mBuilder.MakeLoad(UInt32Ty, LoadPtr);
+      inst->setId(call->getId());
+    } else {
+      inst = call;
+    }
+    return inst;
+  }
+
+private:
+  Builder mBuilder;
+  VariableInst *mMetadata;
+  llvm::SmallVectorImpl<rs2spirv::RSAllocationInfo> &mAllocs;
+};
+
+} // namespace spirit
+} // namespace android
+
+namespace rs2spirv {
+
+android::spirit::Pass *CreateGAPass(void) {
+  return new android::spirit::GAAccessorTransformer();
+}
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/GlobalAllocSPIRITPass.h b/rsov/compiler/GlobalAllocSPIRITPass.h
new file mode 100644
index 0000000..b3a6ecb
--- /dev/null
+++ b/rsov/compiler/GlobalAllocSPIRITPass.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GLOBALALLOCSPIRITPASS_H
+#define GLOBALALLOCSPIRITPASS_H
+
+namespace android {
+namespace spirit {
+
+class Pass;
+
+} // namespace spirit
+} // namespace android
+
+namespace rs2spirv {
+
+android::spirit::Pass *CreateGAPass();
+
+} // namespace rs2spirv
+
+#endif // GLOBALALLOCSPIRITPASS_H
diff --git a/rsov/compiler/GlobalMergePass.cpp b/rsov/compiler/GlobalMergePass.cpp
new file mode 100644
index 0000000..deb82f0
--- /dev/null
+++ b/rsov/compiler/GlobalMergePass.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2016-2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlobalMergePass.h"
+
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "Context.h"
+#include "RSAllocationUtils.h"
+
+#include <functional>
+
+#define DEBUG_TYPE "rs2spirv-global-merge"
+
+using namespace llvm;
+
+namespace rs2spirv {
+
+namespace {
+
+class GlobalMergePass : public ModulePass {
+public:
+  static char ID;
+  GlobalMergePass(bool CPU = false) : ModulePass(ID), mForCPU(CPU) {}
+  const char *getPassName() const override { return "GlobalMergePass"; }
+
+  bool runOnModule(Module &M) override {
+    DEBUG(dbgs() << "RS2SPIRVGlobalMergePass\n");
+
+    SmallVector<GlobalVariable *, 8> Globals;
+    if (!collectGlobals(M, Globals)) {
+      return false; // Module not modified.
+    }
+
+    SmallVector<Type *, 8> Tys;
+    Tys.reserve(Globals.size());
+
+    Context &RS2SPIRVCtxt = Context::getInstance();
+
+    uint32_t index = 0;
+    for (GlobalVariable *GV : Globals) {
+      Tys.push_back(GV->getValueType());
+      const char *name = GV->getName().data();
+      RS2SPIRVCtxt.addExportVarIndex(name, index);
+      index++;
+    }
+
+    LLVMContext &LLVMCtxt = M.getContext();
+
+    StructType *MergedTy = StructType::create(LLVMCtxt, "struct.__GPUBuffer");
+    MergedTy->setBody(Tys, false);
+
+    // Size calculation has to consider data layout
+    const DataLayout &DL = M.getDataLayout();
+    const uint64_t BufferSize = DL.getTypeAllocSize(MergedTy);
+    RS2SPIRVCtxt.setGlobalSize(BufferSize);
+
+    Type *BufferVarTy = mForCPU ? static_cast<Type *>(PointerType::getUnqual(
+                                      Type::getInt8Ty(M.getContext())))
+                                : static_cast<Type *>(MergedTy);
+    GlobalVariable *MergedGV =
+        new GlobalVariable(M, BufferVarTy, false, GlobalValue::ExternalLinkage,
+                           nullptr, "__GPUBlock");
+
+    // For CPU, create a constant struct for initial values, which has each of
+    // its fields initialized to the original value of the corresponding global
+    // variable.
+    // During the script initialization, the driver should copy these initial
+    // values to the global buffer.
+    if (mForCPU) {
+      CreateInitFunction(LLVMCtxt, M, MergedGV, MergedTy, BufferSize, Globals);
+    }
+
+    const bool forCPU = mForCPU;
+    IntegerType *const Int32Ty = Type::getInt32Ty(LLVMCtxt);
+    ConstantInt *const Zero = ConstantInt::get(Int32Ty, 0);
+    Value *Idx[] = {Zero, nullptr};
+
+    auto InstMaker = [forCPU, MergedGV, MergedTy,
+                      &Idx](Instruction *InsertBefore) {
+      Value *Base = MergedGV;
+      if (forCPU) {
+        LoadInst *Load = new LoadInst(MergedGV, "", InsertBefore);
+        DEBUG(Load->dump());
+        Base = new BitCastInst(Load, PointerType::getUnqual(MergedTy), "",
+                               InsertBefore);
+        DEBUG(Base->dump());
+      }
+      GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(
+          MergedTy, Base, Idx, "", InsertBefore);
+      DEBUG(GEP->dump());
+      return GEP;
+    };
+
+    for (size_t i = 0, e = Globals.size(); i != e; ++i) {
+      GlobalVariable *G = Globals[i];
+      Idx[1] = ConstantInt::get(Int32Ty, i);
+      ReplaceAllUsesWithNewInstructions(G, std::cref(InstMaker));
+      G->eraseFromParent();
+    }
+
+    // Return true, as the pass modifies module.
+    return true;
+  }
+
+private:
+  // In the User of Value Old, replaces all references of Old with Value New
+  static inline void ReplaceUse(User *U, Value *Old, Value *New) {
+    for (unsigned i = 0, n = U->getNumOperands(); i < n; ++i) {
+      if (U->getOperand(i) == Old) {
+        U->getOperandUse(i) = New;
+      }
+    }
+  }
+
+  // Replaces each use of V with new instructions created by
+  // funcCreateAndInsert and inserted right before that use. In the cases where
+  // the use is not an instruction, but a constant expression, recursively
+  // replaces that constant expression with a newly constructed equivalent
+  // instruction, before replacing V in that new instruction.
+  static inline void ReplaceAllUsesWithNewInstructions(
+      Value *V,
+      std::function<Instruction *(Instruction *)> funcCreateAndInsert) {
+    SmallVector<User *, 8> Users(V->user_begin(), V->user_end());
+    for (User *U : Users) {
+      if (Instruction *Inst = dyn_cast<Instruction>(U)) {
+        DEBUG(dbgs() << "\nBefore replacement:\n");
+        DEBUG(Inst->dump());
+        DEBUG(dbgs() << "----\n");
+
+        ReplaceUse(U, V, funcCreateAndInsert(Inst));
+
+        DEBUG(Inst->dump());
+      } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
+        auto InstMaker([CE, V, &funcCreateAndInsert](Instruction *UserOfU) {
+          Instruction *Inst = CE->getAsInstruction();
+          Inst->insertBefore(UserOfU);
+          ReplaceUse(Inst, V, funcCreateAndInsert(Inst));
+
+          DEBUG(Inst->dump());
+          return Inst;
+        });
+        ReplaceAllUsesWithNewInstructions(U, InstMaker);
+      } else {
+        DEBUG(U->dump());
+        llvm_unreachable("Expecting only Instruction or ConstantExpr");
+      }
+    }
+  }
+
+  static inline void
+  CreateInitFunction(LLVMContext &LLVMCtxt, Module &M, GlobalVariable *MergedGV,
+                     StructType *MergedTy, const uint64_t BufferSize,
+                     const SmallVectorImpl<GlobalVariable *> &Globals) {
+    SmallVector<Constant *, 8> Initializers;
+    Initializers.reserve(Globals.size());
+    for (size_t i = 0, e = Globals.size(); i != e; ++i) {
+      GlobalVariable *G = Globals[i];
+      Initializers.push_back(G->getInitializer());
+    }
+    ArrayRef<Constant *> ArrInit(Initializers.begin(), Initializers.end());
+    Constant *MergedInitializer = ConstantStruct::get(MergedTy, ArrInit);
+    GlobalVariable *MergedInit =
+        new GlobalVariable(M, MergedTy, true, GlobalValue::InternalLinkage,
+                           MergedInitializer, "__GPUBlock0");
+
+    Function *UserInit = M.getFunction("init");
+    // If there is no user-defined init() function, make the new global
+    // initialization function the init().
+    StringRef FName(UserInit ? ".rsov.global_init" : "init");
+    Function *Func;
+    FunctionType *FTy = FunctionType::get(Type::getVoidTy(LLVMCtxt), false);
+    Func = Function::Create(FTy, GlobalValue::ExternalLinkage, FName, &M);
+    BasicBlock *Blk = BasicBlock::Create(LLVMCtxt, "entry", Func);
+    IRBuilder<> LLVMIRBuilder(Blk);
+    LoadInst *Load = LLVMIRBuilder.CreateLoad(MergedGV);
+    LLVMIRBuilder.CreateMemCpy(Load, MergedInit, BufferSize, 0);
+    LLVMIRBuilder.CreateRetVoid();
+
+    // If there is a user-defined init() function, add a call to the global
+    // initialization function in the beginning of that function.
+    if (UserInit) {
+      BasicBlock &EntryBlk = UserInit->getEntryBlock();
+      CallInst::Create(Func, {}, "", &EntryBlk.front());
+    }
+  }
+
+  bool collectGlobals(Module &M, SmallVectorImpl<GlobalVariable *> &Globals) {
+    for (GlobalVariable &GV : M.globals()) {
+      assert(!GV.hasComdat() && "global variable has a comdat section");
+      assert(!GV.hasSection() && "global variable has a non-default section");
+      assert(!GV.isDeclaration() && "global variable is only a declaration");
+      assert(!GV.isThreadLocal() && "global variable is thread-local");
+      assert(GV.getType()->getAddressSpace() == 0 &&
+             "global variable has non-default address space");
+
+      // TODO: Constants accessed by kernels should be handled differently
+      if (GV.isConstant()) {
+        continue;
+      }
+
+      // Global Allocations are handled differently in separate passes
+      if (isRSAllocation(GV)) {
+        continue;
+      }
+
+      Globals.push_back(&GV);
+    }
+
+    return !Globals.empty();
+  }
+
+  bool mForCPU;
+};
+
+} // namespace
+
+char GlobalMergePass::ID = 0;
+
+ModulePass *createGlobalMergePass(bool CPU) { return new GlobalMergePass(CPU); }
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/GlobalMergePass.h b/rsov/compiler/GlobalMergePass.h
new file mode 100644
index 0000000..e43ab7b
--- /dev/null
+++ b/rsov/compiler/GlobalMergePass.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_GLOBAL_MERGE_PASS_H
+#define RS2SPIRV_GLOBAL_MERGE_PASS_H
+
+namespace llvm {
+class ModulePass;
+} // namespace llvm
+
+namespace rs2spirv {
+
+llvm::ModulePass *createGlobalMergePass(bool CPU = false);
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/InlinePreparationPass.cpp b/rsov/compiler/InlinePreparationPass.cpp
new file mode 100644
index 0000000..fc1a50d
--- /dev/null
+++ b/rsov/compiler/InlinePreparationPass.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InlinePreparationPass.h"
+
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "Context.h"
+
+#define DEBUG_TYPE "rs2spirv-inline"
+
+using namespace llvm;
+
+namespace rs2spirv {
+
+namespace {
+
+class InlinePreparationPass : public ModulePass {
+public:
+  static char ID;
+  explicit InlinePreparationPass() : ModulePass(ID) {}
+
+  const char *getPassName() const override { return "InlinePreparationPass"; }
+
+  bool runOnModule(Module &M) override {
+    DEBUG(dbgs() << "InlinePreparationPass\n");
+
+    rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
+
+    for (auto &F : M.functions()) {
+      if (F.isDeclaration()) {
+        continue;
+      }
+
+      if (Ctxt.isForEachKernel(F.getName())) {
+        continue; // Skip kernels.
+      }
+
+      F.addFnAttr(Attribute::AlwaysInline);
+      F.setLinkage(GlobalValue::InternalLinkage);
+
+      DEBUG(dbgs() << "Marked as alwaysinline:\t" << F.getName() << '\n');
+    }
+
+    // Returns true, because this pass modifies the Module.
+    return true;
+  }
+};
+
+} // namespace
+
+char InlinePreparationPass::ID = 0;
+
+ModulePass *createInlinePreparationPass() {
+  return new InlinePreparationPass();
+}
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/InlinePreparationPass.h b/rsov/compiler/InlinePreparationPass.h
new file mode 100644
index 0000000..12bbfa3
--- /dev/null
+++ b/rsov/compiler/InlinePreparationPass.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_INLINE_PREPARATION_PASS_H
+#define RS2SPIRV_INLINE_PREPARATION_PASS_H
+
+namespace llvm {
+class ModulePass;
+} // namespace llvm
+
+namespace rs2spirv {
+
+llvm::ModulePass *createInlinePreparationPass();
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/RSAllocationUtils.cpp b/rsov/compiler/RSAllocationUtils.cpp
new file mode 100644
index 0000000..8b66a6c
--- /dev/null
+++ b/rsov/compiler/RSAllocationUtils.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RSAllocationUtils.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "cxxabi.h"
+
+#include <sstream>
+#include <unordered_map>
+
+#define DEBUG_TYPE "rs2spirv-rs-allocation-utils"
+
+using namespace llvm;
+
+namespace rs2spirv {
+
+bool isRSAllocation(const GlobalVariable &GV) {
+  auto *PT = cast<PointerType>(GV.getType());
+  DEBUG(PT->dump());
+
+  auto *VT = PT->getElementType();
+  DEBUG(VT->dump());
+  std::string TypeName;
+  raw_string_ostream RSO(TypeName);
+  VT->print(RSO);
+  RSO.str(); // Force flush.
+  DEBUG(dbgs() << "TypeName: " << TypeName << '\n');
+
+  return TypeName.find("struct.rs_allocation") != std::string::npos;
+}
+
+bool getRSAllocationInfo(Module &M, SmallVectorImpl<RSAllocationInfo> &Allocs) {
+  DEBUG(dbgs() << "getRSAllocationInfo\n");
+  for (auto &GV : M.globals()) {
+    if (GV.isDeclaration() || !isRSAllocation(GV))
+      continue;
+
+    Allocs.push_back({'%' + GV.getName().str(), None, &GV, -1});
+  }
+
+  return true;
+}
+
+// Collect Allocation access calls into the Calls
+// Also update Allocs with assigned ID.
+// After calling this function, Allocs would contain the mapping from
+// GV name to the corresponding ID.
+bool getRSAllocAccesses(SmallVectorImpl<RSAllocationInfo> &Allocs,
+                        SmallVectorImpl<RSAllocationCallInfo> &Calls) {
+  DEBUG(dbgs() << "getRSGEATCalls\n");
+  DEBUG(dbgs() << "\n\n~~~~~~~~~~~~~~~~~~~~~\n\n");
+
+  std::unordered_map<const Value *, const GlobalVariable *> Mapping;
+  int id_assigned = 0;
+
+  for (auto &A : Allocs) {
+    auto *GV = A.GlobalVar;
+    std::vector<User *> WorkList(GV->user_begin(), GV->user_end());
+    size_t Idx = 0;
+
+    while (Idx < WorkList.size()) {
+      auto *U = WorkList[Idx];
+      DEBUG(dbgs() << "Visiting ");
+      DEBUG(U->dump());
+      ++Idx;
+      auto It = Mapping.find(U);
+      if (It != Mapping.end()) {
+        if (It->second == GV) {
+          continue;
+        } else {
+          errs() << "Duplicate global mapping discovered!\n";
+          errs() << "\nGlobal: ";
+          GV->print(errs());
+          errs() << "\nExisting mapping: ";
+          It->second->print(errs());
+          errs() << "\nUser: ";
+          U->print(errs());
+          errs() << '\n';
+
+          return false;
+        }
+      }
+
+      Mapping[U] = GV;
+      DEBUG(dbgs() << "New mapping: ");
+      DEBUG(U->print(dbgs()));
+      DEBUG(dbgs() << " -> " << GV->getName() << '\n');
+
+      if (auto *FCall = dyn_cast<CallInst>(U)) {
+        if (auto *F = FCall->getCalledFunction()) {
+          const auto FName = F->getName();
+          DEBUG(dbgs() << "Discovered function call to : " << FName << '\n');
+          // Treat memcpy as moves for the purpose of this analysis
+          if (FName.startswith("llvm.memcpy")) {
+            assert(FCall->getNumArgOperands() > 0);
+            Value *CopyDest = FCall->getArgOperand(0);
+            // We are interested in the users of the dest operand of
+            // memcpy here
+            Value *LocalCopy = CopyDest->stripPointerCasts();
+            User *NewU = dyn_cast<User>(LocalCopy);
+            assert(NewU);
+            WorkList.push_back(NewU);
+            continue;
+          }
+
+          char *demangled = __cxxabiv1::__cxa_demangle(
+              FName.str().c_str(), nullptr, nullptr, nullptr);
+          if (!demangled)
+            continue;
+          const StringRef DemangledNameRef(demangled);
+          DEBUG(dbgs() << "Demangled name: " << DemangledNameRef << '\n');
+
+          const StringRef GEAPrefix = "rsGetElementAt_";
+          const StringRef SEAPrefix = "rsSetElementAt_";
+          const StringRef DIMXPrefix = "rsAllocationGetDimX";
+          assert(GEAPrefix.size() == SEAPrefix.size());
+
+          const bool IsGEA = DemangledNameRef.startswith(GEAPrefix);
+          const bool IsSEA = DemangledNameRef.startswith(SEAPrefix);
+          const bool IsDIMX = DemangledNameRef.startswith(DIMXPrefix);
+
+          assert(IsGEA || IsSEA || IsDIMX);
+          if (!A.hasID()) {
+            A.assignID(id_assigned++);
+          }
+
+          if (IsGEA || IsSEA) {
+            DEBUG(dbgs() << "Found rsAlloc function!\n");
+
+            const auto Kind =
+                IsGEA ? RSAllocAccessKind::GEA : RSAllocAccessKind::SEA;
+
+            const auto RSElementTy =
+                DemangledNameRef.drop_front(GEAPrefix.size());
+
+            Calls.push_back({A, FCall, Kind, RSElementTy.str()});
+            continue;
+          } else if (DemangledNameRef.startswith(GEAPrefix.drop_back()) ||
+                     DemangledNameRef.startswith(SEAPrefix.drop_back())) {
+            errs() << "Untyped accesses to global rs_allocations are not "
+                      "supported.\n";
+            return false;
+          } else if (IsDIMX) {
+            DEBUG(dbgs() << "Found rsAllocationGetDimX function!\n");
+            const auto Kind = RSAllocAccessKind::DIMX;
+            Calls.push_back({A, FCall, Kind, ""});
+          }
+        }
+      }
+
+      // TODO: Consider using set-like container to reduce computational
+      // complexity.
+      for (auto *NewU : U->users())
+        if (std::find(WorkList.begin(), WorkList.end(), NewU) == WorkList.end())
+          WorkList.push_back(NewU);
+    }
+  }
+
+  std::unordered_map<const GlobalVariable *, std::string> GVAccessTypes;
+
+  for (auto &Access : Calls) {
+    auto AccessElemTyIt = GVAccessTypes.find(Access.RSAlloc.GlobalVar);
+    if (AccessElemTyIt != GVAccessTypes.end() &&
+        AccessElemTyIt->second != Access.RSElementTy) {
+      errs() << "Could not infere element type for: ";
+      Access.RSAlloc.GlobalVar->print(errs());
+      errs() << '\n';
+      return false;
+    } else if (AccessElemTyIt == GVAccessTypes.end()) {
+      GVAccessTypes.emplace(Access.RSAlloc.GlobalVar, Access.RSElementTy);
+      Access.RSAlloc.RSElementType = Access.RSElementTy;
+    }
+  }
+
+  DEBUG(dbgs() << "\n\n~~~~~~~~~~~~~~~~~~~~~\n\n");
+  return true;
+}
+
+bool solidifyRSAllocAccess(Module &M, RSAllocationCallInfo CallInfo) {
+  DEBUG(dbgs() << "solidifyRSAllocAccess " << CallInfo.RSAlloc.VarName << '\n');
+  auto *FCall = CallInfo.FCall;
+  auto *Fun = FCall->getCalledFunction();
+  assert(Fun);
+
+  StringRef FName;
+  if (CallInfo.Kind == RSAllocAccessKind::DIMX)
+    FName = "rsAllocationGetDimX";
+  else
+    FName = Fun->getName();
+
+  std::ostringstream OSS;
+  OSS << "__rsov_" << FName.str();
+  // Make up uint32_t F(uint32_t)
+  Type *UInt32Ty = IntegerType::get(M.getContext(), 32);
+  auto *NewFT = FunctionType::get(UInt32Ty, ArrayRef<Type *>(UInt32Ty), false);
+
+  auto *NewF = Function::Create(NewFT, // Fun->getFunctionType(),
+                                Function::ExternalLinkage, OSS.str(), &M);
+  FCall->setCalledFunction(NewF);
+  FCall->setArgOperand(0, ConstantInt::get(UInt32Ty, 0, false));
+  NewF->setAttributes(Fun->getAttributes());
+
+  DEBUG(M.dump());
+
+  return true;
+}
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/RSAllocationUtils.h b/rsov/compiler/RSAllocationUtils.h
new file mode 100644
index 0000000..b25cfde
--- /dev/null
+++ b/rsov/compiler/RSAllocationUtils.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_RS_ALLOCATION_UTILS_H
+#define RS2SPIRV_RS_ALLOCATION_UTILS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include <string>
+
+namespace llvm {
+class CallInst;
+class GlobalVariable;
+class Module;
+class Type;
+} // namespace llvm
+
+namespace rs2spirv {
+
+struct RSAllocationInfo {
+  std::string VarName;
+  llvm::Optional<std::string> RSElementType;
+  llvm::GlobalVariable *GlobalVar;
+  // Assigned unique identifier for this allocation;
+  // not the slot #.
+  // Represents the index of this allocation's metadata
+  // in the global allocation metadata Vulkan buffer
+  int ID;
+  bool hasID(void) const { return ID >= 0; }
+  void assignID(int no) { ID = no; }
+};
+
+enum class RSAllocAccessKind { GEA, SEA, DIMX };
+
+struct RSAllocationCallInfo {
+  RSAllocationInfo &RSAlloc;
+  llvm::CallInst *FCall;
+  RSAllocAccessKind Kind;
+  std::string RSElementTy;
+};
+
+bool isRSAllocation(const llvm::GlobalVariable &GV);
+bool getRSAllocationInfo(llvm::Module &M,
+                         llvm::SmallVectorImpl<RSAllocationInfo> &Allocs);
+bool getRSAllocAccesses(llvm::SmallVectorImpl<RSAllocationInfo> &Allocs,
+                        llvm::SmallVectorImpl<RSAllocationCallInfo> &Calls);
+bool solidifyRSAllocAccess(llvm::Module &M, RSAllocationCallInfo CallInfo);
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/RSSPIRVWriter.cpp b/rsov/compiler/RSSPIRVWriter.cpp
new file mode 100644
index 0000000..e95db6b
--- /dev/null
+++ b/rsov/compiler/RSSPIRVWriter.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RSSPIRVWriter.h"
+
+#include "Builtin.h"
+#include "Context.h"
+#include "GlobalAllocPass.h"
+#include "GlobalAllocSPIRITPass.h"
+#include "GlobalMergePass.h"
+#include "InlinePreparationPass.h"
+#include "RemoveNonkernelsPass.h"
+#include "SPIRVModule.h"
+#include "Wrapper.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "pass_queue.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/SPIRV.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+
+#define DEBUG_TYPE "rs2spirv-writer"
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace rs2spirv {
+
+void addPassesForRS2SPIRV(llvm::legacy::PassManager &PassMgr) {
+  PassMgr.add(createGlobalMergePass());
+
+  PassMgr.add(createInlinePreparationPass());
+  PassMgr.add(createAlwaysInlinerPass());
+  PassMgr.add(createRemoveNonkernelsPass());
+  // Delete unreachable globals.
+  PassMgr.add(createGlobalDCEPass());
+  // Remove dead debug info.
+  PassMgr.add(createStripDeadDebugInfoPass());
+  // Remove dead func decls.
+  PassMgr.add(createStripDeadPrototypesPass());
+  // Transform global allocations and accessors (rs[GS]etElementAt)
+  PassMgr.add(createGlobalAllocPass());
+  // Removed dead MemCpys in 64-bit targets after global alloc pass
+  PassMgr.add(createDeadStoreEliminationPass());
+  PassMgr.add(createAggressiveDCEPass());
+  // Delete unreachable globals (after removing global allocations)
+  PassMgr.add(createRemoveAllGlobalAllocPass());
+  PassMgr.add(createPromoteMemoryToRegisterPass());
+  PassMgr.add(createTransOCLMD());
+  // TODO: investigate removal of OCLTypeToSPIRV pass.
+  PassMgr.add(createOCLTypeToSPIRV());
+  PassMgr.add(createSPIRVRegularizeLLVM());
+  PassMgr.add(createSPIRVLowerConstExpr());
+  PassMgr.add(createSPIRVLowerBool());
+}
+
+bool WriteSPIRV(Context &Ctxt, Module *M,
+                llvm::raw_ostream &OS, std::string &ErrMsg) {
+  llvm::legacy::PassManager PassMgr;
+  addPassesForRS2SPIRV(PassMgr);
+
+  std::unique_ptr<SPIRVModule> BM(SPIRVModule::createSPIRVModule());
+
+  PassMgr.add(createLLVMToSPIRV(BM.get()));
+  PassMgr.run(*M);
+  DEBUG(M->dump());
+
+  if (BM->getError(ErrMsg) != SPIRVEC_Success) {
+    return false;
+  }
+
+  llvm::SmallString<4096> O;
+  llvm::raw_svector_ostream SVOS(O);
+
+  SVOS << *BM;
+
+  llvm::StringRef str = SVOS.str();
+  std::vector<uint32_t> words(str.size() / 4);
+
+  memcpy(words.data(), str.data(), str.size());
+
+  android::spirit::PassQueue spiritPasses;
+  spiritPasses.append(CreateWrapperPass(*M));
+  spiritPasses.append(CreateBuiltinPass());
+  spiritPasses.append(CreateGAPass());
+
+  int error;
+  auto wordsOut = spiritPasses.run(words, &error);
+
+  if (error != 0) {
+    OS << *BM;
+    ErrMsg = "Failed to generate wrappers for kernels";
+    return false;
+  }
+
+  OS.write(reinterpret_cast<const char *>(wordsOut.data()),
+           wordsOut.size() * 4);
+
+  return true;
+}
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/RSSPIRVWriter.h b/rsov/compiler/RSSPIRVWriter.h
new file mode 100644
index 0000000..f2689fc
--- /dev/null
+++ b/rsov/compiler/RSSPIRVWriter.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS_SPIRV_WRITER_H
+#define RS_SPIRV_WRITER_H
+
+#include <string>
+
+namespace llvm {
+class Module;
+class raw_ostream;
+} // namespace llvm
+
+namespace bcinfo {
+class MetadataExtractor;
+} // namespace bcinfo
+
+namespace rs2spirv {
+
+class Context;
+
+bool WriteSPIRV(rs2spirv::Context &Ctxt, llvm::Module *M,
+                llvm::raw_ostream &OS, std::string &ErrMsg);
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/RemoveNonkernelsPass.cpp b/rsov/compiler/RemoveNonkernelsPass.cpp
new file mode 100644
index 0000000..82d2a30
--- /dev/null
+++ b/rsov/compiler/RemoveNonkernelsPass.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RemoveNonkernelsPass.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "Context.h"
+
+#define DEBUG_TYPE "rs2spirv-remove"
+
+using namespace llvm;
+
+namespace rs2spirv {
+
+namespace {
+
+void HandleTargetTriple(llvm::Module &M) {
+  Triple TT(M.getTargetTriple());
+  auto Arch = TT.getArch();
+
+  StringRef NewTriple;
+  switch (Arch) {
+  default:
+    llvm_unreachable("Unrecognized architecture");
+    break;
+  case Triple::arm:
+    NewTriple = "spir-unknown-unknown";
+    break;
+  case Triple::aarch64:
+    NewTriple = "spir64-unknown-unknown";
+    break;
+  case Triple::spir:
+  case Triple::spir64:
+    DEBUG(dbgs() << "!!! Already a spir triple !!!\n");
+  }
+
+  DEBUG(dbgs() << "New triple:\t" << NewTriple << "\n");
+  M.setTargetTriple(NewTriple);
+}
+
+class RemoveNonkernelsPass : public ModulePass {
+public:
+  static char ID;
+  explicit RemoveNonkernelsPass() : ModulePass(ID) {}
+
+  const char *getPassName() const override { return "RemoveNonkernelsPass"; }
+
+  bool runOnModule(Module &M) override {
+    DEBUG(dbgs() << "RemoveNonkernelsPass\n");
+    DEBUG(M.dump());
+
+    HandleTargetTriple(M);
+
+    rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
+
+    if (Ctxt.getNumForEachKernel() == 0) {
+      DEBUG(dbgs() << "RemoveNonkernelsPass detected no kernel\n");
+      // Returns false, since no modification is made to the Module.
+      return false;
+    }
+
+    std::vector<Function *> Functions;
+    for (auto &F : M.functions()) {
+      Functions.push_back(&F);
+    }
+
+    for (auto &F : Functions) {
+      if (F->isDeclaration())
+        continue;
+
+      if (Ctxt.isForEachKernel(F->getName())) {
+        continue; // Skip kernels.
+      }
+
+      F->replaceAllUsesWith(UndefValue::get((Type *)F->getType()));
+      F->eraseFromParent();
+
+      DEBUG(dbgs() << "Removed:\t" << F->getName() << '\n');
+    }
+
+    DEBUG(M.dump());
+    DEBUG(dbgs() << "Done removal\n");
+
+    // Returns true, because the pass modifies the Module.
+    return true;
+  }
+};
+
+} // namespace
+
+char RemoveNonkernelsPass::ID = 0;
+
+ModulePass *createRemoveNonkernelsPass() {
+  return new RemoveNonkernelsPass();
+}
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/RemoveNonkernelsPass.h b/rsov/compiler/RemoveNonkernelsPass.h
new file mode 100644
index 0000000..eed2dc8
--- /dev/null
+++ b/rsov/compiler/RemoveNonkernelsPass.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_REMOVE_NONKERNELS_PASS_H
+#define RS2SPIRV_REMOVE_NONKERNELS_PASS_H
+
+namespace llvm {
+class ModulePass;
+} // namespace llvm
+
+namespace rs2spirv {
+
+llvm::ModulePass *createRemoveNonkernelsPass();
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/Wrapper.cpp b/rsov/compiler/Wrapper.cpp
new file mode 100644
index 0000000..550cc46
--- /dev/null
+++ b/rsov/compiler/Wrapper.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Wrapper.h"
+
+#include "llvm/IR/Module.h"
+
+#include "Builtin.h"
+#include "Context.h"
+#include "GlobalAllocSPIRITPass.h"
+#include "RSAllocationUtils.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "builder.h"
+#include "instructions.h"
+#include "module.h"
+#include "pass.h"
+
+#include <sstream>
+#include <vector>
+
+using bcinfo::MetadataExtractor;
+
+namespace android {
+namespace spirit {
+
+VariableInst *AddBuffer(Instruction *elementType, uint32_t binding, Builder &b,
+                        Module *m) {
+  auto ArrTy = m->getRuntimeArrayType(elementType);
+  const size_t stride = m->getSize(elementType);
+  ArrTy->decorate(Decoration::ArrayStride)->addExtraOperand(stride);
+  auto StructTy = m->getStructType(ArrTy);
+  StructTy->decorate(Decoration::BufferBlock);
+  StructTy->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
+
+  auto StructPtrTy = m->getPointerType(StorageClass::Uniform, StructTy);
+
+  VariableInst *bufferVar = b.MakeVariable(StructPtrTy, StorageClass::Uniform);
+  bufferVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
+  bufferVar->decorate(Decoration::Binding)->addExtraOperand(binding);
+  m->addVariable(bufferVar);
+
+  return bufferVar;
+}
+
+bool AddWrapper(const char *name, const uint32_t signature,
+                const uint32_t numInput, Builder &b, Module *m) {
+  FunctionDefinition *kernel = m->lookupFunctionDefinitionByName(name);
+  if (kernel == nullptr) {
+    // In the metadata for RenderScript LLVM bitcode, the first foreach kernel
+    // is always reserved for the root kernel, even though in the most recent RS
+    // apps it does not exist. Simply bypass wrapper generation here, and return
+    // true for this case.
+    // Otherwise, if a non-root kernel function cannot be found, it is a
+    // fatal internal error which is really unexpected.
+    return (strncmp(name, "root", 4) == 0);
+  }
+
+  // The following three cases are not supported
+  if (!MetadataExtractor::hasForEachSignatureKernel(signature)) {
+    // Not handling old-style kernel
+    return false;
+  }
+
+  if (MetadataExtractor::hasForEachSignatureUsrData(signature)) {
+    // Not handling the user argument
+    return false;
+  }
+
+  if (MetadataExtractor::hasForEachSignatureCtxt(signature)) {
+    // Not handling the context argument
+    return false;
+  }
+
+  TypeVoidInst *VoidTy = m->getVoidType();
+  TypeFunctionInst *FuncTy = m->getFunctionType(VoidTy, nullptr, 0);
+  FunctionDefinition *Func =
+      b.MakeFunctionDefinition(VoidTy, FunctionControl::None, FuncTy);
+  m->addFunctionDefinition(Func);
+
+  Block *Blk = b.MakeBlock();
+  Func->addBlock(Blk);
+
+  Blk->addInstruction(b.MakeLabel());
+
+  TypeIntInst *UIntTy = m->getUnsignedIntType(32);
+
+  Instruction *XValue = nullptr;
+  Instruction *YValue = nullptr;
+  Instruction *ZValue = nullptr;
+  Instruction *Index = nullptr;
+  VariableInst *InvocationId = nullptr;
+  VariableInst *NumWorkgroups = nullptr;
+
+  if (MetadataExtractor::hasForEachSignatureIn(signature) ||
+      MetadataExtractor::hasForEachSignatureOut(signature) ||
+      MetadataExtractor::hasForEachSignatureX(signature) ||
+      MetadataExtractor::hasForEachSignatureY(signature) ||
+      MetadataExtractor::hasForEachSignatureZ(signature)) {
+    TypeVectorInst *V3UIntTy = m->getVectorType(UIntTy, 3);
+    InvocationId = m->getInvocationId();
+    auto IID = b.MakeLoad(V3UIntTy, InvocationId);
+    Blk->addInstruction(IID);
+
+    XValue = b.MakeCompositeExtract(UIntTy, IID, {0});
+    Blk->addInstruction(XValue);
+
+    YValue = b.MakeCompositeExtract(UIntTy, IID, {1});
+    Blk->addInstruction(YValue);
+
+    ZValue = b.MakeCompositeExtract(UIntTy, IID, {2});
+    Blk->addInstruction(ZValue);
+
+    // TODO: Use SpecConstant for workgroup size
+    auto ConstOne = m->getConstant(UIntTy, 1U);
+    auto GroupSize =
+        m->getConstantComposite(V3UIntTy, ConstOne, ConstOne, ConstOne);
+
+    auto GroupSizeX = b.MakeCompositeExtract(UIntTy, GroupSize, {0});
+    Blk->addInstruction(GroupSizeX);
+
+    auto GroupSizeY = b.MakeCompositeExtract(UIntTy, GroupSize, {1});
+    Blk->addInstruction(GroupSizeY);
+
+    NumWorkgroups = m->getNumWorkgroups();
+    auto NumGroup = b.MakeLoad(V3UIntTy, NumWorkgroups);
+    Blk->addInstruction(NumGroup);
+
+    auto NumGroupX = b.MakeCompositeExtract(UIntTy, NumGroup, {0});
+    Blk->addInstruction(NumGroupX);
+
+    auto NumGroupY = b.MakeCompositeExtract(UIntTy, NumGroup, {1});
+    Blk->addInstruction(NumGroupY);
+
+    auto GlobalSizeX = b.MakeIMul(UIntTy, GroupSizeX, NumGroupX);
+    Blk->addInstruction(GlobalSizeX);
+
+    auto GlobalSizeY = b.MakeIMul(UIntTy, GroupSizeY, NumGroupY);
+    Blk->addInstruction(GlobalSizeY);
+
+    auto RowsAlongZ = b.MakeIMul(UIntTy, GlobalSizeY, ZValue);
+    Blk->addInstruction(RowsAlongZ);
+
+    auto NumRows = b.MakeIAdd(UIntTy, YValue, RowsAlongZ);
+    Blk->addInstruction(NumRows);
+
+    auto NumCellsFromYZ = b.MakeIMul(UIntTy, GlobalSizeX, NumRows);
+    Blk->addInstruction(NumCellsFromYZ);
+
+    Index = b.MakeIAdd(UIntTy, NumCellsFromYZ, XValue);
+    Blk->addInstruction(Index);
+  }
+
+  std::vector<IdRef> inputs;
+
+  ConstantInst *ConstZero = m->getConstant(UIntTy, 0);
+
+  for (uint32_t i = 0; i < numInput; i++) {
+    FunctionParameterInst *param = kernel->getParameter(i);
+    Instruction *elementType = param->mResultType.mInstruction;
+    VariableInst *inputBuffer = AddBuffer(elementType, i + 3, b, m);
+
+    TypePointerInst *PtrTy =
+        m->getPointerType(StorageClass::Function, elementType);
+    AccessChainInst *Ptr =
+        b.MakeAccessChain(PtrTy, inputBuffer, {ConstZero, Index});
+    Blk->addInstruction(Ptr);
+
+    Instruction *input = b.MakeLoad(elementType, Ptr);
+    Blk->addInstruction(input);
+
+    inputs.push_back(IdRef(input));
+  }
+
+  // TODO: Convert from unsigned int to signed int if that is what the kernel
+  // function takes for the coordinate parameters
+  if (MetadataExtractor::hasForEachSignatureX(signature)) {
+    inputs.push_back(XValue);
+    if (MetadataExtractor::hasForEachSignatureY(signature)) {
+      inputs.push_back(YValue);
+      if (MetadataExtractor::hasForEachSignatureZ(signature)) {
+        inputs.push_back(ZValue);
+      }
+    }
+  }
+
+  auto resultType = kernel->getReturnType();
+  auto kernelCall =
+      b.MakeFunctionCall(resultType, kernel->getInstruction(), inputs);
+  Blk->addInstruction(kernelCall);
+
+  if (MetadataExtractor::hasForEachSignatureOut(signature)) {
+    VariableInst *OutputBuffer = AddBuffer(resultType, 2, b, m);
+    auto resultPtrType = m->getPointerType(StorageClass::Function, resultType);
+    AccessChainInst *OutPtr =
+        b.MakeAccessChain(resultPtrType, OutputBuffer, {ConstZero, Index});
+    Blk->addInstruction(OutPtr);
+    Blk->addInstruction(b.MakeStore(OutPtr, kernelCall));
+  }
+
+  Blk->addInstruction(b.MakeReturn());
+
+  std::string wrapperName("entry_");
+  wrapperName.append(name);
+
+  EntryPointDefinition *entry = b.MakeEntryPointDefinition(
+      ExecutionModel::GLCompute, Func, wrapperName.c_str());
+
+  entry->setLocalSize(1, 1, 1);
+
+  if (Index != nullptr) {
+    entry->addToInterface(InvocationId);
+    entry->addToInterface(NumWorkgroups);
+  }
+
+  m->addEntryPoint(entry);
+
+  return true;
+}
+
+bool DecorateGlobalBuffer(llvm::Module &LM, Builder &b, Module *m) {
+  Instruction *inst = m->lookupByName("__GPUBlock");
+  if (inst == nullptr) {
+    return true;
+  }
+
+  VariableInst *bufferVar = static_cast<VariableInst *>(inst);
+  bufferVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
+  bufferVar->decorate(Decoration::Binding)->addExtraOperand(0);
+
+  TypePointerInst *StructPtrTy =
+      static_cast<TypePointerInst *>(bufferVar->mResultType.mInstruction);
+  TypeStructInst *StructTy =
+      static_cast<TypeStructInst *>(StructPtrTy->mOperand2.mInstruction);
+  StructTy->decorate(Decoration::BufferBlock);
+
+  // Decorate each member with proper offsets
+
+  const auto GlobalsB = LM.globals().begin();
+  const auto GlobalsE = LM.globals().end();
+  const auto Found =
+      std::find_if(GlobalsB, GlobalsE, [](const llvm::GlobalVariable &GV) {
+        return GV.getName() == "__GPUBlock";
+      });
+
+  if (Found == GlobalsE) {
+    return true; // GPUBlock not found - not an error by itself.
+  }
+
+  const llvm::GlobalVariable &G = *Found;
+
+  rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
+  bool IsCorrectTy = false;
+  if (const auto *LPtrTy = llvm::dyn_cast<llvm::PointerType>(G.getType())) {
+    if (auto *LStructTy =
+            llvm::dyn_cast<llvm::StructType>(LPtrTy->getElementType())) {
+      IsCorrectTy = true;
+
+      const auto &DLayout = LM.getDataLayout();
+      const auto *SLayout = DLayout.getStructLayout(LStructTy);
+      assert(SLayout);
+      if (SLayout == nullptr) {
+        std::cerr << "struct layout is null" << std::endl;
+        return false;
+      }
+      std::vector<uint32_t> offsets;
+      for (uint32_t i = 0, e = LStructTy->getNumElements(); i != e; ++i) {
+        auto decor = StructTy->memberDecorate(i, Decoration::Offset);
+        if (!decor) {
+          std::cerr << "failed creating member decoration for field " << i
+                    << std::endl;
+          return false;
+        }
+        const uint32_t offset = (uint32_t)SLayout->getElementOffset(i);
+        decor->addExtraOperand(offset);
+        offsets.push_back(offset);
+      }
+      std::stringstream ssOffsets;
+      // TODO: define this string in a central place
+      ssOffsets << ".rsov.ExportedVars:";
+      for(uint32_t slot = 0; slot < Ctxt.getNumExportVar(); slot++) {
+        const uint32_t index = Ctxt.getExportVarIndex(slot);
+        const uint32_t offset = offsets[index];
+        ssOffsets << offset << ';';
+      }
+      m->addString(ssOffsets.str().c_str());
+
+      std::stringstream ssGlobalSize;
+      ssGlobalSize << ".rsov.GlobalSize:" << Ctxt.getGlobalSize();
+      m->addString(ssGlobalSize.str().c_str());
+    }
+  }
+
+  if (!IsCorrectTy) {
+    return false;
+  }
+
+  llvm::SmallVector<rs2spirv::RSAllocationInfo, 2> RSAllocs;
+  if (!getRSAllocationInfo(LM, RSAllocs)) {
+    // llvm::errs() << "Extracting rs_allocation info failed\n";
+    return true;
+  }
+
+  // TODO: clean up the binding number assignment
+  size_t BindingNum = 3;
+  for (const auto &A : RSAllocs) {
+    Instruction *inst = m->lookupByName(A.VarName.c_str());
+    if (inst == nullptr) {
+      return false;
+    }
+    VariableInst *bufferVar = static_cast<VariableInst *>(inst);
+    bufferVar->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
+    bufferVar->decorate(Decoration::Binding)->addExtraOperand(BindingNum++);
+  }
+
+  return true;
+}
+
+void AddHeader(Module *m) {
+  m->addCapability(Capability::Shader);
+  m->setMemoryModel(AddressingModel::Logical, MemoryModel::GLSL450);
+
+  m->addSource(SourceLanguage::GLSL, 450);
+  m->addSourceExtension("GL_ARB_separate_shader_objects");
+  m->addSourceExtension("GL_ARB_shading_language_420pack");
+  m->addSourceExtension("GL_GOOGLE_cpp_style_line_directive");
+  m->addSourceExtension("GL_GOOGLE_include_directive");
+}
+
+namespace {
+
+class StorageClassVisitor : public DoNothingVisitor {
+public:
+  void visit(TypePointerInst *inst) override {
+    matchAndReplace(inst->mOperand1);
+  }
+
+  void visit(TypeForwardPointerInst *inst) override {
+    matchAndReplace(inst->mOperand2);
+  }
+
+  void visit(VariableInst *inst) override { matchAndReplace(inst->mOperand1); }
+
+private:
+  void matchAndReplace(StorageClass &storage) {
+    if (storage == StorageClass::Function) {
+      storage = StorageClass::Uniform;
+    }
+  }
+};
+
+void FixGlobalStorageClass(Module *m) {
+  StorageClassVisitor v;
+  m->getGlobalSection()->accept(&v);
+}
+
+} // anonymous namespace
+
+bool AddWrappers(llvm::Module &LM,
+                 android::spirit::Module *m) {
+  rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
+  const bcinfo::MetadataExtractor &metadata = Ctxt.getMetadata();
+  android::spirit::Builder b;
+
+  m->setBuilder(&b);
+
+  FixGlobalStorageClass(m);
+
+  AddHeader(m);
+
+  DecorateGlobalBuffer(LM, b, m);
+
+  const size_t numKernel = metadata.getExportForEachSignatureCount();
+  const char **kernelName = metadata.getExportForEachNameList();
+  const uint32_t *kernelSigature = metadata.getExportForEachSignatureList();
+  const uint32_t *inputCount = metadata.getExportForEachInputCountList();
+
+  for (size_t i = 0; i < numKernel; i++) {
+    bool success =
+        AddWrapper(kernelName[i], kernelSigature[i], inputCount[i], b, m);
+    if (!success) {
+      return false;
+    }
+  }
+
+  m->consolidateAnnotations();
+  return true;
+}
+
+class WrapperPass : public Pass {
+public:
+  WrapperPass(const llvm::Module &LM) : mLLVMModule(const_cast<llvm::Module&>(LM)) {}
+
+  Module *run(Module *m, int *error) override {
+    bool success = AddWrappers(mLLVMModule, m);
+    if (error) {
+      *error = success ? 0 : -1;
+    }
+    return m;
+  }
+
+private:
+  llvm::Module &mLLVMModule;
+};
+
+} // namespace spirit
+} // namespace android
+
+namespace rs2spirv {
+
+android::spirit::Pass* CreateWrapperPass(const llvm::Module &LLVMModule) {
+  return new android::spirit::WrapperPass(LLVMModule);
+}
+
+} // namespace rs2spirv
diff --git a/rsov/compiler/Wrapper.h b/rsov/compiler/Wrapper.h
new file mode 100644
index 0000000..27aaee8
--- /dev/null
+++ b/rsov/compiler/Wrapper.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WRAPPER_H
+#define WRAPPER_H
+
+#include <stdint.h>
+
+namespace llvm {
+class Module;
+}
+
+namespace android {
+namespace spirit {
+
+class Builder;
+class Instruction;
+class Module;
+class Pass;
+class VariableInst;
+
+// TODO: avoid exposing these methods while still unit testing them
+void AddHeader(Module *m);
+VariableInst *AddBuffer(Instruction *elementType, uint32_t binding, Builder &b,
+                        Module *m);
+
+bool AddWrapper(const char *name, const uint32_t signature,
+                const uint32_t numInput, Builder &b, Module *m);
+
+// Find the LLVM generated buffer for all non-allocation glboal variables, and
+// correctly decorate it and its type with annotations for binding numbers, etc.
+bool DecorateGlobalBuffer(llvm::Module &M, Builder &b, Module *m);
+
+} // namespace spirit
+} // namespace android
+
+namespace rs2spirv {
+
+android::spirit::Pass* CreateWrapperPass(const llvm::Module &LLVMModule);
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/compiler/Wrapper_test.cpp b/rsov/compiler/Wrapper_test.cpp
new file mode 100644
index 0000000..1be643a
--- /dev/null
+++ b/rsov/compiler/Wrapper_test.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Wrapper.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "builder.h"
+#include "file_utils.h"
+#include "instructions.h"
+#include "module.h"
+#include "test_utils.h"
+#include "gtest/gtest.h"
+
+namespace android {
+namespace spirit {
+
+class WrapperTest : public ::testing::Test {
+protected:
+  virtual void SetUp() {
+    mWordsGreyscale = readWords("greyscale.spv");
+    mWordsGreyscale2 = readWords("greyscale2.spv");
+    mWordsInvert = readWords("invert.spv");
+  }
+
+  std::vector<uint32_t> mWordsGreyscale;
+  std::vector<uint32_t> mWordsGreyscale2;
+  std::vector<uint32_t> mWordsInvert;
+
+private:
+  std::vector<uint32_t> readWords(const char *testFile) {
+    static const std::string testDataPath(
+        "frameworks/rs/rsov/compiler/spirit/test_data/");
+    const std::string &fullPath = getAbsolutePath(testDataPath + testFile);
+    return readFile<uint32_t>(fullPath);
+  }
+};
+
+TEST_F(WrapperTest, testAddBuffer) {
+  Builder b;
+  Module m(&b);
+  auto elemType = m.getIntType(32);
+  VariableInst *buffer = AddBuffer(elemType, 2, b, &m);
+  ASSERT_NE(nullptr, buffer);
+
+  GlobalSection *gs = m.getGlobalSection();
+
+  EXPECT_EQ(1, countEntity<TypeRuntimeArrayInst>(gs));
+  EXPECT_EQ(1, countEntity<TypeStructInst>(gs));
+  EXPECT_EQ(1, countEntity<VariableInst>(gs));
+}
+
+TEST_F(WrapperTest, testAddWrapper1) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  m->resolveIds();
+
+  Builder b;
+  m->setBuilder(&b);
+
+  constexpr uint32_t sig =
+      bcinfo::MD_SIG_Kernel | bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out;
+
+  EXPECT_FALSE(AddWrapper("foo", sig, 1, b, m.get()));
+
+  EXPECT_TRUE(AddWrapper("greyscale(vf4;", sig, 1, b, m.get()));
+
+  // The input already has an entry point
+  EXPECT_EQ(2, countEntity<EntryPointDefinition>(m.get()));
+}
+
+TEST_F(WrapperTest, testAddWrapper2) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsInvert));
+
+  ASSERT_NE(nullptr, m);
+
+  m->resolveIds();
+
+  Builder b;
+  m->setBuilder(&b);
+
+  uint32_t sig = bcinfo::MD_SIG_Kernel | bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out;
+
+  EXPECT_FALSE(AddWrapper("foo", sig, 1, b, m.get()));
+
+  ASSERT_TRUE(AddWrapper("invert", sig, 1, b, m.get()));
+
+  EXPECT_EQ(1, countEntity<EntryPointDefinition>(m.get()));
+}
+
+TEST_F(WrapperTest, testAddWrapperForRoot) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsInvert));
+
+  ASSERT_NE(nullptr, m);
+
+  Builder b;
+  m->setBuilder(&b);
+
+  bool success = AddWrapper("root", 0, 1, b, m.get());
+  ASSERT_TRUE(success);
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/bcc_rsov.sh b/rsov/compiler/bcc_rsov.sh
new file mode 100755
index 0000000..c09ad57
--- /dev/null
+++ b/rsov/compiler/bcc_rsov.sh
@@ -0,0 +1,57 @@
+#! /system/bin/sh
+#
+# Copyright 2016, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+function help() {
+    echo "USAGE: $0 [options] <input>"
+    echo
+    echo "OPTIONS:"
+    echo "  -h        Show this help message."
+    echo "  -o <file> Write output to file."
+}
+
+OUTPUT_FILE=""
+
+while getopts "ho:" opt; do
+    case "$opt" in
+        h)
+            help
+            exit 0
+            ;;
+        o)
+            OUTPUT_FILE=$OPTARG
+            ;;
+    esac
+done
+
+shift $((OPTIND-1))
+
+if [[ "$#" -ne 1 ]]; then
+  help
+  exit -1
+fi
+
+INPUT_FILE=$1
+
+if [[ -z "$OUTPUT_FILE" ]]; then
+    OUTPUT_FILE="${INPUT_FILE%.*}.spv"
+fi
+
+eval rs2spirv $INPUT_FILE -o $OUTPUT_FILE
+
+#rm -f $INPUT_FILE $KERNEL $KERNEL_TXT $WRAPPER $OUTPUT_TXT
+
+exit $?
diff --git a/rsov/compiler/rs2spirv.cpp b/rsov/compiler/rs2spirv.cpp
new file mode 100644
index 0000000..059f59b
--- /dev/null
+++ b/rsov/compiler/rs2spirv.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RSSPIRVWriter.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "spirit/file_utils.h"
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "Context.h"
+#include "GlobalMergePass.h"
+#include "RSSPIRVWriter.h"
+
+#define DEBUG_TYPE "rs2spirv"
+
+namespace kExt {
+const char SPIRVBinary[] = ".spv";
+} // namespace kExt
+
+using namespace llvm;
+
+static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
+                                      cl::init("-"));
+
+static cl::opt<std::string> OutputFile("o",
+                                       cl::desc("Override output filename"),
+                                       cl::value_desc("filename"));
+
+static cl::opt<std::string> OutputBitcodeFile("bc",
+                                              cl::desc("Override output bitcode filename"),
+                                              cl::value_desc("bitcode filename"));
+
+static std::string removeExt(const std::string &FileName) {
+  size_t Pos = FileName.find_last_of(".");
+  if (Pos != std::string::npos)
+    return FileName.substr(0, Pos);
+  return FileName;
+}
+
+static bool WriteBitcode(rs2spirv::Context &Ctxt, Module *M,
+                         raw_ostream &OS, std::string &ErrMsg) {
+  llvm::legacy::PassManager PassMgr;
+  PassMgr.add(rs2spirv::createGlobalMergePass(true));
+  PassMgr.run(*M);
+
+  WriteBitcodeToFile(M, OS);
+
+  return true;
+}
+
+static int convertLLVMToSPIRV() {
+  LLVMContext Context;
+
+  std::string Err;
+  auto DS = getDataFileStreamer(InputFile, &Err);
+  if (!DS) {
+    errs() << "Fails to open input file: " << Err;
+    return -1;
+  }
+  ErrorOr<std::unique_ptr<Module>> MOrErr =
+      getStreamedBitcodeModule(InputFile, std::move(DS), Context);
+
+  if (std::error_code EC = MOrErr.getError()) {
+    errs() << "Fails to load bitcode: " << EC.message();
+    return -1;
+  }
+
+  std::unique_ptr<Module> M = std::move(*MOrErr);
+
+  if (std::error_code EC = M->materializeAll()) {
+    errs() << "Fails to materialize: " << EC.message();
+    return -1;
+  }
+
+  std::error_code EC;
+
+  std::vector<char> bitcode = android::spirit::readFile<char>(InputFile);
+  std::unique_ptr<bcinfo::MetadataExtractor> ME(
+      new bcinfo::MetadataExtractor(bitcode.data(), bitcode.size()));
+
+  rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
+
+  if (!Ctxt.Initialize(std::move(ME))) {
+    return -2;
+  }
+
+  if (!OutputBitcodeFile.empty()) {
+    llvm::StringRef outBCFile(OutputBitcodeFile);
+    llvm::raw_fd_ostream OFS_BC(outBCFile, EC, llvm::sys::fs::F_None);
+    if (!WriteBitcode(Ctxt, M.get(), OFS_BC, Err)) {
+      errs() << "compiler error: " << Err << '\n';
+      return -3;
+    }
+    return 0;
+  }
+
+  if (OutputFile.empty()) {
+    if (InputFile == "-")
+      OutputFile = "-";
+    else
+      OutputFile = removeExt(InputFile) + kExt::SPIRVBinary;
+  }
+
+  llvm::StringRef outFile(OutputFile);
+  llvm::raw_fd_ostream OFS(outFile, EC, llvm::sys::fs::F_None);
+
+  if (!rs2spirv::WriteSPIRV(Ctxt, M.get(), OFS, Err)) {
+    errs() << "compiler error: " << Err << '\n';
+    return -4;
+  }
+
+  return 0;
+}
+
+int main(int ac, char **av) {
+  EnablePrettyStackTrace();
+  sys::PrintStackTraceOnErrorSignal(av[0]);
+  PrettyStackTraceProgram X(ac, av);
+
+  cl::ParseCommandLineOptions(ac, av, "RenderScript to SPIRV translator");
+
+  return convertLLVMToSPIRV();
+}
diff --git a/rsov/compiler/rs2spirv_driver.sh b/rsov/compiler/rs2spirv_driver.sh
new file mode 100755
index 0000000..7b3b63f
--- /dev/null
+++ b/rsov/compiler/rs2spirv_driver.sh
@@ -0,0 +1,75 @@
+# Copyright 2016, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/bash
+
+ME=$0
+
+function usage {
+  echo >&2 "$ME: $*: Expected [-d|--dump] [-t|--trace] <SPIRV_TOOLS_PATH> <SCRIPT_NAME> <OUTPUT_DIR>)"
+  exit 2
+}
+
+function dump {
+  if [[ -z "${DUMP:-}" ]] ; then
+    return 0
+  fi
+  eval rs2spirv "$output_folder/$script.spv" -print-as-words
+  return $?
+}
+
+DUMP=
+TRACE=
+
+while [[ "${1:-}" = -* ]] ; do
+  case "$1" in
+    -d|--dump)
+      DUMP=t
+      ;;
+    -t|--trace)
+      TRACE=t
+      ;;
+    *)
+      usage "Unexpected option \"$1\""
+      ;;
+  esac
+  shift
+done
+
+if [[ $# -ne 3 ]] ; then
+  usage "Bad argument count (got $#)"
+fi
+
+if [[ -n "${TRACE:-}" ]] ; then
+  set -x
+fi
+
+AND_HOME=$ANDROID_BUILD_TOP
+SPIRV_TOOLS_PATH=$1
+
+script_name="$2"
+script=`basename ${2%.*}` # Remove enclosing directories and extension.
+
+output_folder="$3"
+mkdir -p $output_folder
+
+eval llvm-rs-cc -o "$output_folder" -S -emit-llvm -Wall -Werror -target-api 24 \
+  -I "$AND_HOME/external/clang/lib/Headers" -I "$AND_HOME/frameworks/rs/script_api/include" \
+  "$script_name" &&
+eval llvm-as "$output_folder/bc32/$script.ll" -o "$output_folder/$script.bc" &&
+eval rs2spirv "$output_folder/$script.bc" -o "$output_folder/$script.spv" &&
+dump &&
+eval "$SPIRV_TOOLS_PATH/spirv-val" "$output_folder/$script.spv" &&
+
+exit $?
diff --git a/rsov/compiler/spirit/Android.bp b/rsov/compiler/spirit/Android.bp
new file mode 100644
index 0000000..043e851
--- /dev/null
+++ b/rsov/compiler/spirit/Android.bp
@@ -0,0 +1,172 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+    name: "spirit_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    target: {
+        host: {
+            compile_multilib: "first",
+        },
+    },
+    product_variables: {
+        pdk: {
+            enabled: false,
+        },
+        unbundled_build: {
+            enabled: false,
+        },
+    },
+}
+
+python_binary_host {
+    name: "libspirit_generate_py",
+    main: "generate.py",
+    srcs: ["generate.py"],
+    version: {
+        py2: {
+            enabled: true,
+            embedded_launcher: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+}
+
+genrule {
+    name: "libspirit_gen",
+    tools: ["libspirit_generate_py"],
+    cmd: "$(location libspirit_generate_py) $(location :spirv.core.grammar.json-1.1) " +
+        "--instructions=$(location instructions_generated.h) " +
+        "--types=$(location types_generated.h) " +
+        "--opcodes=$(location opcodes_generated.h) " +
+        "--instruction_dispatches=$(location instruction_dispatches_generated.h) " +
+        "--enum_dispatches=$(location enum_dispatches_generated.h) " +
+        "--type_inst_dispatches=$(location type_inst_dispatches_generated.h) " +
+        "--const_inst_dispatches=$(location const_inst_dispatches_generated.h) " +
+        "--factory_methods=$(location factory_methods_generated.h)",
+    srcs: [":spirv.core.grammar.json-1.1"],
+    out: [
+        "instructions_generated.h",
+        "types_generated.h",
+        "opcodes_generated.h",
+        "instruction_dispatches_generated.h",
+        "enum_dispatches_generated.h",
+        "type_inst_dispatches_generated.h",
+        "const_inst_dispatches_generated.h",
+        "factory_methods_generated.h",
+    ],
+}
+
+//=====================================================================
+// Host and device shared library libspirit.so
+//=====================================================================
+cc_library_shared {
+    name: "libspirit",
+    defaults: ["spirit_defaults"],
+    host_supported: true,
+
+    srcs: [
+        "builder.cpp",
+        "entity.cpp",
+        "instructions.cpp",
+        "module.cpp",
+        "pass.cpp",
+        "pass_queue.cpp",
+        "transformer.cpp",
+        "visitor.cpp",
+        "word_stream.cpp",
+        "word_stream_impl.cpp",
+    ],
+
+    generated_headers: ["libspirit_gen"],
+    export_generated_headers: ["libspirit_gen"],
+
+    export_include_dirs: ["."],
+
+    target: {
+        android: {
+            cflags: ["-Wno-error=non-virtual-dtor"],
+        },
+    },
+}
+
+//=====================================================================
+// Tests for host module word_stream
+//=====================================================================
+cc_test_host {
+    name: "word_stream_test",
+    defaults: ["spirit_defaults"],
+    srcs: [
+        "word_stream.cpp",
+        "word_stream_impl.cpp",
+        "word_stream_test.cpp",
+    ],
+    generated_headers: ["libspirit_gen"],
+}
+
+//=====================================================================
+// Tests for host module instructions
+//=====================================================================
+
+cc_test_host {
+    name: "instructions_test",
+    defaults: ["spirit_defaults"],
+    srcs: [
+        "entity.cpp",
+        "instructions.cpp",
+        "instructions_test.cpp",
+        "visitor.cpp",
+        "word_stream.cpp",
+        "word_stream_impl.cpp",
+    ],
+    generated_headers: ["libspirit_gen"],
+}
+
+//=====================================================================
+// Tests for host module pass queue
+//=====================================================================
+
+cc_test_host {
+    name: "pass_queue_test",
+    defaults: ["spirit_defaults"],
+    srcs: [
+        "pass.cpp",
+        "pass_queue.cpp",
+        "pass_queue_test.cpp",
+    ],
+    shared_libs: ["libspirit"],
+}
+
+//=====================================================================
+// Tests for host shared library
+//=====================================================================
+
+cc_test_host {
+    name: "libspirit_test",
+    defaults: ["spirit_defaults"],
+    srcs: [
+        "builder_test.cpp",
+        "module_test.cpp",
+        "transformer_test.cpp",
+    ],
+    shared_libs: ["libspirit"],
+}
diff --git a/rsov/compiler/spirit/builder.cpp b/rsov/compiler/spirit/builder.cpp
new file mode 100644
index 0000000..140b554
--- /dev/null
+++ b/rsov/compiler/spirit/builder.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "builder.h"
+
+#include "module.h"
+
+namespace android {
+namespace spirit {
+
+Module *Builder::MakeModule() {
+  Module *ret = new Module(this);
+  ret->initialize();
+  return ret;
+}
+
+EntryPointDefinition *
+Builder::MakeEntryPointDefinition(ExecutionModel execModel,
+                                  FunctionDefinition *func, const char *name) {
+  return new EntryPointDefinition(this, execModel, func, name);
+}
+
+DebugInfoSection *Builder::MakeDebugInfoSection() {
+  return new DebugInfoSection(this);
+}
+
+FunctionDefinition *
+Builder::MakeFunctionDefinition(Instruction *retType, FunctionControl ctrl,
+                                TypeFunctionInst *funcType) {
+  FunctionInst *func = MakeFunction(retType, ctrl, funcType);
+  FunctionEndInst *end = MakeFunctionEnd();
+  return new FunctionDefinition(this, func, end);
+}
+
+Block *Builder::MakeBlock() { return new Block(this); }
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/builder.h b/rsov/compiler/spirit/builder.h
new file mode 100644
index 0000000..816246d
--- /dev/null
+++ b/rsov/compiler/spirit/builder.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUILDER_H
+#define BUILDER_H
+
+#include "instructions.h"
+#include "module.h"
+
+namespace android {
+namespace spirit {
+
+class Builder {
+public:
+  Module *MakeModule();
+  EntryPointDefinition *MakeEntryPointDefinition(ExecutionModel execModel,
+                                                 FunctionDefinition *func,
+                                                 const char *name);
+  DebugInfoSection *MakeDebugInfoSection();
+  FunctionDefinition *MakeFunctionDefinition(Instruction *retType,
+                                             FunctionControl ctrl,
+                                             TypeFunctionInst *funcType);
+  Block *MakeBlock();
+
+#include "factory_methods_generated.h"
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // BUILDER_H
diff --git a/rsov/compiler/spirit/builder_test.cpp b/rsov/compiler/spirit/builder_test.cpp
new file mode 100644
index 0000000..4f21310
--- /dev/null
+++ b/rsov/compiler/spirit/builder_test.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "builder.h"
+
+#include "file_utils.h"
+#include "instructions.h"
+#include "module.h"
+#include "test_utils.h"
+#include "gtest/gtest.h"
+
+namespace android {
+namespace spirit {
+
+TEST(BuilderTest, testBuildAndSerialize) {
+  Builder b;
+
+  Module *m = b.MakeModule();
+
+  ASSERT_NE(nullptr, m);
+
+  m->addCapability(Capability::Shader);
+  m->addCapability(Capability::Addresses);
+  m->setMemoryModel(AddressingModel::Physical32, MemoryModel::GLSL450);
+
+  m->addExtInstImport("GLSL.std.450");
+
+  // Shall we explicitly create the debug info section first?
+  m->addSource(SourceLanguage::GLSL, 450);
+  m->addSourceExtension("GL_ARB_separate_shader_objects");
+  m->addSourceExtension("GL_ARB_shading_language_420pack");
+  m->addSourceExtension("GL_GOOGLE_cpp_style_line_directive");
+  m->addSourceExtension("GL_GOOGLE_include_directive");
+  m->addString("Foo Bar Baz");
+
+  auto FloatTy = m->getFloatType(32);
+  auto VF4Ty = m->getVectorType(FloatTy, 4);
+  auto ArrTy = m->getRuntimeArrayType(VF4Ty);
+  ArrTy->decorate(Decoration::ArrayStride)->addExtraOperand(16);
+  auto StructTy = m->getStructType(ArrTy);
+  StructTy->decorate(Decoration::BufferBlock);
+  StructTy->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
+
+  auto StructPtrTy = m->getPointerType(StorageClass::Uniform, StructTy);
+
+  auto InputBuffer = b.MakeVariable(StructPtrTy, StorageClass::Uniform);
+  InputBuffer->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
+  InputBuffer->decorate(Decoration::Binding)->addExtraOperand(2);
+  m->addVariable(InputBuffer);
+
+  auto ArrTy2 = m->getRuntimeArrayType(VF4Ty);
+  ArrTy2->decorate(Decoration::ArrayStride)->addExtraOperand(16);
+
+  auto StructTy2 = m->getStructType(ArrTy2);
+  StructTy2->decorate(Decoration::BufferBlock);
+  StructTy2->memberDecorate(0, Decoration::Offset)->addExtraOperand(0);
+
+  auto StructPtrTy2 = m->getPointerType(StorageClass::Uniform, StructTy2);
+  auto OutputBuffer = b.MakeVariable(StructPtrTy2, StorageClass::Uniform);
+  OutputBuffer->decorate(Decoration::DescriptorSet)->addExtraOperand(0);
+  OutputBuffer->decorate(Decoration::Binding)->addExtraOperand(1);
+  m->addVariable(OutputBuffer);
+
+  auto VoidTy = m->getVoidType();
+  auto FuncTy = m->getFunctionType(VoidTy, nullptr, 0);
+
+  auto UIntTy = m->getUnsignedIntType(32);
+  auto V3UIntTy = m->getVectorType(UIntTy, 3);
+
+  auto InvocationID = m->getInvocationId();
+
+  auto ConstOne = m->getConstant(UIntTy, 1);
+#if 0
+  auto V3UIntPtrTy = m->getPointerType(StorageClass::Input, V3UIntTy);
+  auto GSize = b.MakeVariable(V3UIntPtrTy, StorageClass::Input);
+  GSize->decorate(Decoration::BuiltIn)->addExtraOperand(BuiltIn::WorkgroupSize);
+  m->addVariable(GSize);
+#endif
+
+  auto GNum = m->getNumWorkgroups();
+
+  const char *funcName = "invert";
+
+  auto Func = b.MakeFunctionDefinition(VoidTy, FunctionControl::None, FuncTy);
+  // TODO: Add method setName() to class FunctionDefinition
+  // Func->setName(funcName);  // I.e., OpName %func funcName
+  m->addFunctionDefinition(Func);
+
+  auto Blk = b.MakeBlock();
+  Func->addBlock(Blk);
+
+  Blk->addInstruction(b.MakeLabel());
+
+  auto ConstZero = m->getConstant(UIntTy, 0);
+  auto UIntPtrTy = m->getPointerType(StorageClass::Input, UIntTy);
+
+  auto IID = b.MakeLoad(V3UIntTy, InvocationID);
+  Blk->addInstruction(IID);
+
+  auto XValue = b.MakeCompositeExtract(UIntTy, IID, {0});
+  Blk->addInstruction(XValue);
+
+  auto YValue = b.MakeCompositeExtract(UIntTy, IID, {1});
+  Blk->addInstruction(YValue);
+
+#if 0
+  auto PtrToGSizeX = b.MakeAccessChain(UIntPtrTy, GSize, {ConstZero});
+  Blk->addInstruction(PtrToGSizeX);
+
+  auto GSizeX = b.MakeLoad(UIntTy, PtrToGSizeX);
+  Blk->addInstruction(GSizeX);
+#else
+  auto &GSizeX = ConstOne;
+#endif
+
+  auto Tmp1 = b.MakeIMul(UIntTy, YValue, GSizeX);
+  Blk->addInstruction(Tmp1);
+
+  auto PtrToGNumX = b.MakeAccessChain(UIntPtrTy, GNum, {ConstZero});
+  Blk->addInstruction(PtrToGNumX);
+
+  auto GNumX = b.MakeLoad(UIntTy, PtrToGNumX);
+  Blk->addInstruction(GNumX);
+
+  auto OffsetY = b.MakeIMul(UIntTy, Tmp1, GNumX);
+  Blk->addInstruction(OffsetY);
+
+  auto Index = b.MakeIAdd(UIntTy, OffsetY, XValue);
+  Blk->addInstruction(Index);
+
+  auto VF4PtrTy = m->getPointerType(StorageClass::Function, VF4Ty);
+  auto Ptr = b.MakeAccessChain(VF4PtrTy, InputBuffer, {ConstZero, Index});
+  Blk->addInstruction(Ptr);
+
+  auto Value = b.MakeLoad(VF4Ty, Ptr);
+  Blk->addInstruction(Value);
+
+  // Here is the place to do something about the value. As is, this is a copy
+  // kernel.
+  auto ConstOneF = m->getConstant(FloatTy, 1.0f);
+  auto ConstOneVF4 = m->getConstantComposite(VF4Ty, ConstOneF, ConstOneF,
+                                             ConstOneF, ConstOneF);
+  auto Result = b.MakeFSub(VF4Ty, ConstOneVF4, Value);
+  Blk->addInstruction(Result);
+
+  auto OutPtr = b.MakeAccessChain(VF4PtrTy, OutputBuffer, {ConstZero, Index});
+  Blk->addInstruction(OutPtr);
+
+  Blk->addInstruction(b.MakeStore(OutPtr, Result));
+  Blk->addInstruction(b.MakeReturn());
+
+  m->addEntryPoint(
+      b.MakeEntryPointDefinition(ExecutionModel::GLCompute, Func, funcName)
+          ->addToInterface(InvocationID)
+          ->addToInterface(GNum)
+          //          ->addToInterface(GSize)
+          ->setLocalSize(1, 1, 1));
+
+  EXPECT_EQ(1, countEntity<MemoryModelInst>(m));
+  EXPECT_EQ(1, countEntity<EntryPointInst>(m));
+  EXPECT_EQ(3, countEntity<LoadInst>(m));
+  EXPECT_EQ(1, countEntity<ReturnInst>(m));
+  EXPECT_EQ(1, countEntity<ExecutionModeInst>(m));
+  EXPECT_EQ(2, countEntity<TypeRuntimeArrayInst>(m));
+  EXPECT_EQ(2, countEntity<TypeStructInst>(m));
+  EXPECT_EQ(5, countEntity<TypePointerInst>(m));
+  EXPECT_EQ(1, countEntity<StringInst>(m));
+
+  m->consolidateAnnotations();
+
+  auto words = Serialize<Module>(m);
+
+  auto m1 = Deserialize<Module>(words);
+  ASSERT_NE(nullptr, m1);
+
+  auto words1 = Serialize<Module>(m1);
+
+  EXPECT_TRUE(words == words1);
+}
+
+TEST(BuilderTest, testLoadAndModify) {
+  static const std::string testDataPath(
+      "frameworks/rs/rsov/compiler/spirit/test_data/");
+  const std::string &fullPath = getAbsolutePath(testDataPath + "greyscale.spv");
+
+  Module *m = Deserialize<Module>(readFile<uint32_t>(fullPath.c_str()));
+
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+
+  Builder b;
+
+  auto IntTy = m->getIntType(32);
+  auto FuncTy = m->getFunctionType(IntTy, {IntTy});
+
+  auto Func = b.MakeFunctionDefinition(IntTy, FunctionControl::None, FuncTy);
+  // TODO: Add method setName() to class FunctionDefinition
+  // Func->setName(funcName);  // I.e., OpName %func funcName
+  m->addFunctionDefinition(Func);
+
+  auto Blk = b.MakeBlock();
+  Func->addBlock(Blk);
+
+  Blk->addInstruction(b.MakeReturn());
+
+  m->consolidateAnnotations();
+
+  auto words = Serialize<Module>(m);
+
+  auto m1 = Deserialize<Module>(words);
+  ASSERT_NE(nullptr, m1);
+
+  auto words1 = Serialize<Module>(m1);
+
+  EXPECT_TRUE(words == words1);
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/core_defs.h b/rsov/compiler/spirit/core_defs.h
new file mode 100644
index 0000000..06b1d1b
--- /dev/null
+++ b/rsov/compiler/spirit/core_defs.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CORE_DEFS_H
+#define CORE_DEFS_H
+
+#include <string>
+
+namespace android {
+namespace spirit {
+
+class Instruction;
+
+typedef int32_t LiteralInteger;
+typedef std::string LiteralString;
+typedef union {
+  int32_t intValue;
+  int64_t longValue;
+  float floatValue;
+  double doubleValue;
+} LiteralContextDependentNumber;
+typedef uint32_t LiteralExtInstInteger;
+typedef uint32_t LiteralSpecConstantOpInteger;
+typedef uint32_t IdResult;
+
+struct IdRef {
+  IdRef() : mId(0), mInstruction(nullptr) {}
+  IdRef(Instruction *inst);
+
+  uint32_t mId;
+  mutable Instruction *mInstruction;
+};
+
+// TODO: specialize these ref types
+// TODO: should only reference type instructions
+struct IdResultType : public IdRef {
+  IdResultType() : IdRef() {}
+  IdResultType(Instruction *inst) : IdRef(inst) {}
+};
+
+// TODO: should only reference int representing memory semeantics
+struct IdMemorySemantics : public IdRef {};
+// TODO: should only reference int representing scopes
+struct IdScope : public IdRef {};
+
+struct OpCodeAndWordCount {
+  OpCodeAndWordCount() : mOpCode(0) {}
+  OpCodeAndWordCount(uint32_t codeAndCount)
+      : mOpCode((uint16_t)codeAndCount),
+        mWordCount((uint32_t)(codeAndCount >> 16)) {}
+  OpCodeAndWordCount(uint32_t opcode, uint32_t wordCount)
+      : mOpCode((uint16_t)opcode), mWordCount((uint16_t)wordCount) {}
+
+  operator uint32_t() const {
+    return ((uint32_t)mWordCount << 16) | (uint32_t)mOpCode;
+  }
+
+  uint16_t mOpCode;
+  uint16_t mWordCount;
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // CORE_DEFS_H
diff --git a/rsov/compiler/spirit/entity.cpp b/rsov/compiler/spirit/entity.cpp
new file mode 100644
index 0000000..baeb55c
--- /dev/null
+++ b/rsov/compiler/spirit/entity.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "entity.h"
+
+#include "instructions.h"
+#include "visitor.h"
+#include "word_stream.h"
+
+namespace android {
+namespace spirit {
+
+void Entity::Serialize(OutputWordStream &OS) const {
+  std::unique_ptr<IVisitor> v(CreateInstructionVisitor(
+      [&OS](Instruction *inst) -> void { inst->Serialize(OS); }));
+  v->visit(const_cast<Entity *>(this));
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/entity.h b/rsov/compiler/spirit/entity.h
new file mode 100644
index 0000000..33c112b
--- /dev/null
+++ b/rsov/compiler/spirit/entity.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ENTITY_H
+#define ENTITY_H
+
+#include <memory>
+#include <vector>
+
+#include "word_stream.h"
+
+namespace android {
+namespace spirit {
+
+class Builder;
+class IVisitor;
+
+class Entity {
+public:
+  Entity() {}
+  Entity(Builder *b) : mBuilder(b) {}
+
+  virtual ~Entity() {}
+
+  virtual void accept(IVisitor *visitor) = 0;
+  virtual bool DeserializeInternal(InputWordStream &IS) = 0;
+  virtual void Serialize(OutputWordStream &OS) const;
+  virtual void dump() const {}
+
+  void setBuilder(Builder *builder) { mBuilder = builder; }
+
+protected:
+  Builder *mBuilder;
+};
+
+template <typename T> T *Deserialize(InputWordStream &IS) {
+  std::unique_ptr<T> entity(new T());
+  if (!entity->DeserializeInternal(IS)) {
+    return nullptr;
+  }
+  return entity.release();
+}
+
+template <typename T> T *Deserialize(const std::vector<uint32_t> &words) {
+  std::unique_ptr<InputWordStream> IS(InputWordStream::Create(words));
+  return Deserialize<T>(*IS);
+}
+
+template <class T>
+void DeserializeZeroOrMore(InputWordStream &IS, std::vector<T *> &all) {
+  while (auto entity = Deserialize<T>(IS)) {
+    all.push_back(entity);
+  }
+}
+
+template <class T>
+std::vector<uint32_t> Serialize(T* e) {
+  std::unique_ptr<OutputWordStream> OS(OutputWordStream::Create());
+  e->Serialize(*OS);
+  return OS->getWords();
+}
+
+} // namespace spirit
+} // namespace android
+
+#endif // ENTITY_H
diff --git a/rsov/compiler/spirit/file_utils.h b/rsov/compiler/spirit/file_utils.h
new file mode 100644
index 0000000..4f00c7c
--- /dev/null
+++ b/rsov/compiler/spirit/file_utils.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FILE_UTILS_H
+#define FILE_UTILS_H
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+template <typename T> std::vector<T> readFile(const char *filename) {
+  std::ifstream ifs;
+  std::filebuf *fb = ifs.rdbuf();
+  fb->open(filename, std::ios::in);
+
+  if (!fb->is_open()) {
+    std::cerr << "failed opening " << filename << std::endl;
+    return std::vector<T>();
+  }
+
+  ifs.seekg(0, ifs.end);
+  int length = ifs.tellg();
+  ifs.seekg(0, ifs.beg);
+
+  std::vector<T> ret(length / sizeof(T));
+
+  ifs.read((char *)ret.data(), length);
+
+  fb->close();
+
+  return ret;
+}
+
+template <typename T> std::vector<T> readFile(const std::string &filename) {
+  return readFile<T>(filename.c_str());
+}
+
+template <typename T>
+void writeFile(const char *filename, const std::vector<T> &data) {
+  std::ofstream ofs(filename, std::ios::out);
+
+  ofs.write(reinterpret_cast<const char *>(data.data()),
+            sizeof(T) * data.size());
+}
+
+} // namespace spirit
+} // namespace android
+
+#endif // FILE_UTILS_H
diff --git a/rsov/compiler/spirit/generate.py b/rsov/compiler/spirit/generate.py
new file mode 100755
index 0000000..22b844d
--- /dev/null
+++ b/rsov/compiler/spirit/generate.py
@@ -0,0 +1,507 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import getopt
+import json
+import string
+import sys
+
+def generate_header_file(filename, with_guard, printer):
+    f = open(filename, 'w')
+    orig_stdout = sys.stdout
+    sys.stdout = f
+    print '// DO NOT MODIFY. AUTO-GENERATED.\n'
+    if with_guard:
+        print "#pragma once"
+        print
+        print "namespace android {"
+        print "namespace spirit {"
+        print
+    printer()
+    if with_guard:
+        print "} // namespace spirit"
+        print "} // namespace android"
+    f.close()
+    sys.stdout = orig_stdout
+
+
+
+################################################################################
+#
+# Generate Builder class: the .h and .cpp files.
+#
+################################################################################
+
+def factory_method_name(opname, outlined):
+    if outlined:
+        return "Builder::Make%s" % opname_noprefix(opname)
+    else:
+        return "Make%s" % opname_noprefix(opname)
+
+
+
+def factory_method_prototype(inst, outlined):
+    opname = inst['opname']
+    operands = inst.get('operands')
+    str = "%s *%s(" % (class_name(opname), factory_method_name(opname, outlined))
+    first = True;
+    for type, var, quantifier, comment in generate_member_list(operands):
+        if var != "mResult":
+            param = var[1:]
+            if first:
+                first = False
+            else:
+                str += ', '
+            if quantifier == '?':
+                str += '%s *%s=nullptr' % (type, param)
+            elif quantifier == '*':
+                vecTy = "std::vector<%s>" % type
+                str += '%s %s=%s()' % (vecTy, param, vecTy)
+            else:
+                str +=  '%s %s' % (type, param)
+    str += ')'
+    return str
+
+
+
+def factory_method_body(inst):
+    opname = inst['opname']
+    operands = inst.get('operands')
+    clazz = class_name(opname)
+    str = "%s *ret = new %s(" % (clazz, clazz)
+    first = True
+    for type, var, quantifier, comment in generate_member_list(operands):
+        if var != "mResult" and quantifier != '*' and quantifier != '?':
+            param = var[1:]
+            if first:
+                first = False
+            else:
+                str += ', '
+            str += param
+    str += """);
+    if (!ret) {
+        return nullptr;
+    }
+"""
+    str += """
+    if (ret->hasResult()) {
+      ret->setId(Module::getCurrentModule()->nextId());
+    }
+"""
+    for type, var, quantifier, comment in generate_member_list(operands):
+        param = var[1:]
+        # TODO: use vector::swap() or move instead of copy
+        if quantifier == '?' or quantifier == '*':
+            str += "    ret->%s = %s;\n" % (var, param)
+    str += "    return ret;"
+    return str
+
+
+
+def print_factory_method(inst):
+    print """%s {
+    %s
+}""" % (factory_method_prototype(inst, False),
+        factory_method_body(inst))
+
+
+
+def print_factory_methods(insts):
+    for inst in insts:
+        print_factory_method(inst)
+
+
+
+################################################################################
+#
+# Generate type defintions
+#
+################################################################################
+
+def enum_enumerants(ty, enumerants):
+    str = ""
+    for enumerant in enumerants:
+        name = enumerant['enumerant']
+        val = enumerant['value']
+        if name[0].isalpha():
+            str += "  %s = %sU,\n" % (name, val)
+        else:
+            str += "  %s%s = %sU,\n" % (ty, name, val)
+    return str
+
+
+def generate_enum(ty):
+    typeName = ty['kind']
+    print """enum class %s : uint32_t {\n%s};
+""" % (typeName,
+       enum_enumerants(typeName, ty['enumerants']))
+
+
+def generate_composite_fields(bases):
+    str = ""
+    i = 0
+    for field in bases:
+        str += "  %s mField%d;\n" % (field, i)
+        i = i + 1
+    return str
+
+
+
+def print_type_definitions(operand_kinds):
+    for ty in operand_kinds:
+        category = ty['category']
+        if category == 'BitEnum' or category == 'ValueEnum':
+            generate_enum(ty)
+        elif category == 'Composite':
+            print "struct %s {\n%s};\n" % (ty['kind'],
+                                           generate_composite_fields(ty['bases']))
+
+
+
+################################################################################
+#
+# Generate class defintions for all instructions
+#
+################################################################################
+
+def opname_noprefix(opname):
+    return opname[2:]
+
+def class_name(opname):
+    return "%sInst" % opname_noprefix(opname)
+
+
+
+def generate_member_list(operands):
+    members = []
+    if operands is None:
+        return members
+    index = 1
+    for operand in operands:
+        type = operand['kind']
+        if type == 'IdResultType' or type == 'IdResult':
+            varName = "m%s" % type[2:]
+        else:
+            varName = "mOperand%d" % index
+            index = index + 1
+        quantifier = operand.get('quantifier')
+        comment = operand.get('name');
+        members.append((type, varName, quantifier, comment))
+    return members
+
+def fixed_word_count(member_list):
+    wc = 1 # for the first word of opcode and word count
+    for type, var, quant, comment in member_list:
+        if quant != '?' and quant != '*':
+            wc += 1
+    return wc
+
+def string_for_members(opname, member_list):
+    if member_list == []:
+        return ""
+    member_str = "\n  static constexpr OpCode mOpCode=%s;\n" % opname
+    for type, var, quantifier, comment in member_list:
+        if comment is not None and comment.find('\n') != -1:
+            member_str += "  /* %s\n  */\n" % comment
+        member_str += "  "
+        if quantifier == '?':
+            type = type + '*';
+        elif quantifier == '*':
+            type = 'std::vector<%s>' % type;
+        member_str += "%s %s;" % (type, var)
+        if comment is not None and comment.find('\n') == -1:
+            member_str += "  // %s" % comment
+        member_str += "\n"
+    return member_str
+
+def string_for_constructor(opname, opcode, members):
+    # Default constructor
+    initializer = "Instruction(%s, %d)" % (opname, fixed_word_count(members))
+    first = True
+    for type, var, quantifier, comment in members:
+        if quantifier == '?':
+            initializer += ", %s(nullptr)" % var
+    str = "%s() : %s {}" % (class_name(opname), initializer)
+
+    # Constructor with values for members
+    if members == [] or (len(members) == 1 and members[0][0]=='IdResult'):
+        return str
+    nonOptionalOperandExists = False
+    for type, var, quantifier, comment in members:
+        if quantifier is None:
+            nonOptionalOperandExists = True
+    if not nonOptionalOperandExists:
+        return str
+    params = ""
+    initializer = "Instruction(%s, %d)" % (opname, fixed_word_count(members))
+    first = True
+    for type, var, quantifier, comment in members:
+        if var != "mResult" and quantifier != '*':
+            initializer += ", "
+            if quantifier == '?':
+                initializer += "%s(nullptr)" % var
+            else:
+                if first:
+                    first = False
+                else:
+                    params += ", "
+                param = var[1:]  # remove the prefix "m"
+                params += "%s %s" % (type, param)
+                initializer += "%s(%s)" % (var, param)
+    if params != "":
+        str += "\n  %s(%s) :\n    %s {}" % (class_name(opname), params, initializer)
+    str += "\n  virtual ~%s() {}" % class_name(opname)
+    return str
+
+def string_for_serializer_body(opcode, members):
+    body =  "setWordCount();\n"
+    body += "    OS << mCodeAndCount;\n"
+    for type, var, quantifier, comment in members:
+        if quantifier == '?':
+            body += "    if (%s!=nullptr) { OS << *%s; }\n" % (var, var)
+        elif quantifier == '*':
+            body += """    for (auto val : %s) { OS << val; }\n""" % var
+        else:
+            body += "    OS << %s;\n" % var
+    body += "    SerializeExtraOperands(OS);\n"
+    return body
+
+def string_for_deserializer_body(name, members):
+    body = "return DeserializeFirstWord(IS, %s)" % name
+    for type, var, quantifier, comment in members:
+        body += " &&\n           "
+        if quantifier == '?':
+            body += "DeserializeOptionallyOne(IS, &%s)" % var
+        elif quantifier == '*':
+            body += "DeserializeZeroOrMoreOperands(IS, &%s)" % var
+        else:
+            body += "DeserializeExactlyOne(IS, &%s)" % var
+    body += " &&\n           DeserializeExtraOperands(IS);\n"
+    return body
+
+def string_for_get_word_count(members):
+    str = """uint16_t getWordCount() const override {
+    uint16_t count = mFixedWordCount;\n"""
+    for type, var, quantifier, comment in members:
+        if quantifier == '?':
+            str += "    if (%s) count += WordCount(*%s);\n" % (var, var)
+        elif quantifier == '*':
+            str += "    if (!%s.empty()) count += WordCount(%s[0]) * %s.size();\n" % (var, var, var)
+        elif type == 'LiteralString':
+            str += "    count += WordCount(%s) - 1;\n" % var
+
+    str += """    count += mExtraOperands.size();
+    return count;
+  }"""
+    return str
+
+def string_for_accept():
+    return """
+  void accept(IVisitor *v) override { v->visit(this); }
+"""
+
+def has_result(members):
+    for type, val, quantifier, comment in members:
+        if type == 'IdResult':
+            return True
+    return False
+
+
+def string_for_has_result(hasResult):
+    if hasResult:
+        retVal = "true"
+    else:
+        retVal = "false"
+    return "bool hasResult() const override { return %s; }" % retVal
+
+def string_for_get_all_refs(members):
+    str = """std::vector<const IdRef*> getAllIdRefs() const override {
+    std::vector<const IdRef*> ret = {"""
+    first = True
+    # TODO: what if references are in * operands?
+    for type, var, quantifier, comment in members:
+        if type == 'IdRef' or type == 'IdResultType' or type == 'IdMemorySemantics' or type == 'IdScope':
+            if quantifier == '*':
+                pass
+            else:
+                if first:
+                    first = False
+                else:
+                    str += ", "
+                if quantifier == '?':
+                    str += "%s" % var
+                else:
+                    str += "&%s" % var
+    str += """};
+"""
+    for type, var, quantifier, comment in members:
+        if type == 'IdRef' or type == 'IdResultType' or type == 'IdMemorySemantics' or type == 'IdScope':
+            if quantifier == '*':
+                str+="""
+    for(const auto &ref : %s) {
+        ret.push_back(&ref);
+    }
+""" % var
+    str += """
+    return ret;
+  }"""
+    return str
+
+def string_for_get_set_id(hasResult):
+    if hasResult:
+        return """IdResult getId() const override { return mResult; }
+  void setId(IdResult id) override { mResult = id; }"""
+    else:
+        retVal = "0"
+        return """IdResult getId() const override { return 0; }
+  void setId(IdResult) override {}"""
+
+
+def print_instruction_class(inst):
+    opname = inst['opname']
+    opcode = inst['opcode']
+    operands = inst.get('operands')
+    members = generate_member_list(operands)
+    hasResult = has_result(members)
+    print """class %s : public Instruction {
+ public:
+  %s
+
+  void Serialize(OutputWordStream &OS) const override {
+    %s  }
+
+  bool DeserializeInternal(InputWordStream &IS) override {
+    %s  }
+
+  void accept(IVisitor *v) override { v->visit(this); }
+
+  %s
+
+  %s
+
+  %s
+
+  %s
+%s};
+""" % (class_name(opname),
+       string_for_constructor(opname, opcode, members),
+       string_for_serializer_body(opcode, members),
+       string_for_deserializer_body(opname, members),
+       string_for_get_word_count(members),
+       string_for_has_result(hasResult),
+       string_for_get_set_id(hasResult),
+       string_for_get_all_refs(members),
+       string_for_members(opname, members))
+
+def print_all_instruction_classes(insts):
+    for inst in insts:
+        print_instruction_class(inst)
+
+################################################################################
+#
+# Generate opcode enum
+#
+################################################################################
+
+def print_opcode_enum(insts):
+    print "enum OpCode {"
+    for inst in insts:
+        opname = inst['opname']
+        opcode = inst['opcode']
+        print "  %s = %d," % (opname, opcode)
+    print "};"
+
+
+
+################################################################################
+#
+# Generate dispatching code
+#
+################################################################################
+
+def print_dispatches(insts):
+    for inst in insts:
+        opname = inst['opname']
+        print "HANDLE_INSTRUCTION(%s,%s)" % (opname, class_name(opname))
+
+def print_type_inst_dispatches(insts):
+    for inst in insts:
+        opname = inst['opname']
+        if opname[:6] == "OpType":
+            print "HANDLE_INSTRUCTION(%s, %s)" % (opname, class_name(opname))
+
+def print_const_inst_dispatches(insts):
+    for inst in insts:
+        opname = inst['opname']
+        if opname[:10] == "OpConstant":
+            print "HANDLE_INSTRUCTION(%s, %s)" % (opname, class_name(opname))
+
+def print_enum_dispatches(operand_kinds):
+    for ty in operand_kinds:
+        category = ty['category']
+        if category == 'BitEnum' or category == 'ValueEnum':
+            print "HANDLE_ENUM(%s)" % ty['kind']
+
+
+
+################################################################################
+#
+# main
+#
+################################################################################
+
+def main():
+    try:
+        opts, args = getopt.getopt(sys.argv[2:],"h",["instructions=",
+                                                     "types=",
+                                                     "opcodes=",
+                                                     "instruction_dispatches=",
+                                                     "enum_dispatches=",
+                                                     "type_inst_dispatches=",
+                                                     "const_inst_dispatches=",
+                                                     "factory_methods="])
+    except getopt.GetoptError:
+        print sys.argv[0], ''
+        sys.exit(2)
+
+    with open(sys.argv[1]) as grammar_file:
+        grammar = json.load(grammar_file)
+
+    instructions = grammar['instructions']
+
+    for opt, arg in opts:
+        if opt == "--instructions":
+            generate_header_file(arg, True, lambda: print_all_instruction_classes(instructions))
+        elif opt == "--types":
+            kinds = grammar['operand_kinds']
+            generate_header_file(arg, True, lambda: print_type_definitions(kinds))
+        elif opt == "--opcodes":
+            generate_header_file(arg, True, lambda: print_opcode_enum(instructions))
+        elif opt == "--instruction_dispatches":
+            generate_header_file(arg, False, lambda: print_dispatches(instructions))
+        elif opt == "--enum_dispatches":
+            kinds = grammar['operand_kinds']
+            generate_header_file(arg, False, lambda: print_enum_dispatches(kinds))
+        elif opt == "--type_inst_dispatches":
+            generate_header_file(arg, False, lambda: print_type_inst_dispatches(instructions))
+        elif opt == "--const_inst_dispatches":
+            generate_header_file(arg, False, lambda: print_const_inst_dispatches(instructions))
+        elif opt == "--factory_methods":
+            generate_header_file(arg, False, lambda: print_factory_methods(instructions))
+
+if __name__ == '__main__':
+    main()
diff --git a/rsov/compiler/spirit/instructions.cpp b/rsov/compiler/spirit/instructions.cpp
new file mode 100644
index 0000000..2fee620
--- /dev/null
+++ b/rsov/compiler/spirit/instructions.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "instructions.h"
+
+#include <iostream>
+
+#include "visitor.h"
+
+namespace android {
+namespace spirit {
+
+IdRef::IdRef(Instruction *inst) : mId(inst->getId()), mInstruction(inst) {}
+
+void Instruction::accept(IVisitor *v) { v->visit(this); }
+
+DecorateInst *Instruction::decorate(Decoration decor) {
+  if (mCodeAndCount.mOpCode == OpDecorate) {
+    return nullptr;
+  }
+
+  DecorateInst *decorInst = new DecorateInst(this, decor);
+
+  mDecorations.push_back(decorInst);
+
+  return decorInst;
+}
+
+MemberDecorateInst *Instruction::memberDecorate(int member, Decoration decor) {
+  if (mCodeAndCount.mOpCode != OpTypeStruct) {
+    std::cerr << "OpMemberDecorate applied to non-OpTypeStruct instructions\n";
+    return nullptr;
+  }
+
+  MemberDecorateInst *decorInst = new MemberDecorateInst(this, member, decor);
+
+  mDecorations.push_back(decorInst);
+
+  return decorInst;
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/instructions.h b/rsov/compiler/spirit/instructions.h
new file mode 100644
index 0000000..6e162a1
--- /dev/null
+++ b/rsov/compiler/spirit/instructions.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INSTRUCTIONS_H
+#define INSTRUCTIONS_H
+
+#include <stdint.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "core_defs.h"
+#include "entity.h"
+#include "opcodes_generated.h"
+#include "types_generated.h"
+#include "visitor.h"
+#include "word_stream.h"
+
+namespace android {
+namespace spirit {
+
+// Word count for a serialized operand
+template <typename T> uint16_t WordCount(T) { return 1; }
+
+inline uint16_t WordCount(PairLiteralIntegerIdRef) { return 2; }
+inline uint16_t WordCount(PairIdRefLiteralInteger) { return 2; }
+inline uint16_t WordCount(PairIdRefIdRef) { return 2; }
+inline uint16_t WordCount(const std::string &operand) {
+  return operand.length() / 4 + 1;
+}
+
+class Instruction : public Entity {
+public:
+  Instruction(uint32_t opCode) : mCodeAndCount(opCode) {}
+  Instruction(uint32_t opCode, uint32_t fixedWordCount)
+      : mCodeAndCount(opCode), mFixedWordCount(fixedWordCount) {}
+  virtual ~Instruction() {}
+
+  void accept(IVisitor *v) override;
+
+  void setWordCount() const {
+    if (mCodeAndCount.mWordCount == 0) {
+      mCodeAndCount.mWordCount = getWordCount();
+    }
+  }
+  virtual uint16_t getWordCount() const = 0;
+  virtual bool hasResult() const = 0;
+  virtual IdResult getId() const = 0;
+  virtual void setId(IdResult) = 0;
+  virtual std::vector<const IdRef *> getAllIdRefs() const = 0;
+
+  Instruction *addExtraOperand(uint32_t word) {
+    mExtraOperands.push_back(word);
+    return this;
+  }
+
+  // Adds decoration to the current instruction.
+  // Returns: the result OpDecorate instruction
+  DecorateInst *decorate(Decoration);
+  MemberDecorateInst *memberDecorate(int member, Decoration);
+
+  bool DeserializeFirstWord(InputWordStream &IS, OpCode opcode) {
+    if (IS.empty()) {
+      return false;
+    }
+
+    OpCodeAndWordCount codeAndCount(*IS);
+
+    if (codeAndCount.mOpCode != opcode) {
+      return false;
+    }
+
+    mRemainingWordCount = codeAndCount.mWordCount;
+
+    IS >> &mCodeAndCount;
+
+    mRemainingWordCount--;
+
+    return true;
+  }
+
+  template <typename T>
+  bool DeserializeExactlyOne(InputWordStream &IS, T *operand) {
+    if (IS.empty()) {
+      return false;
+    }
+
+    IS >> operand;
+
+    mRemainingWordCount -= WordCount(*operand);
+
+    return true;
+  }
+
+  template <typename T>
+  bool DeserializeOptionallyOne(InputWordStream &IS, T **operand) {
+    if (mRemainingWordCount == 0) {
+      return true;
+    }
+    *operand = new T();
+    return DeserializeExactlyOne(IS, *operand);
+  }
+
+  template <typename T>
+  bool DeserializeZeroOrMoreOperands(InputWordStream &IS,
+                                     std::vector<T> *operands) {
+    while (mRemainingWordCount > 0) {
+      T tmp;
+      if (!DeserializeExactlyOne(IS, &tmp)) {
+        return false;
+      }
+      operands->push_back(tmp);
+    }
+    return true;
+  }
+
+  bool DeserializeExtraOperands(InputWordStream &IS) {
+    return DeserializeZeroOrMoreOperands(IS, &mExtraOperands);
+  }
+
+  void SerializeExtraOperands(OutputWordStream &OS) const {
+    for (uint32_t w : mExtraOperands) {
+      OS << w;
+    }
+  }
+
+  const std::vector<Instruction *> &getAnnotations() const {
+    return mDecorations;
+  }
+
+  uint16_t getOpCode() const { return mCodeAndCount.mOpCode; }
+
+  mutable OpCodeAndWordCount mCodeAndCount;
+  uint16_t mFixedWordCount;
+  uint16_t mRemainingWordCount;
+  std::vector<uint32_t> mExtraOperands;
+  std::vector<Instruction *> mDecorations;
+};
+
+} // namespace spirit
+} // namespace android
+
+#include "instructions_generated.h"
+
+#endif // INSTRUCTIONS_H
diff --git a/rsov/compiler/spirit/instructions_test.cpp b/rsov/compiler/spirit/instructions_test.cpp
new file mode 100644
index 0000000..ce4325e
--- /dev/null
+++ b/rsov/compiler/spirit/instructions_test.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "instructions.h"
+
+#include "gtest/gtest.h"
+
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+TEST(InstructionTest, testOpCapability) {
+  std::vector<uint32_t> words = {0x00020011, 0x00000001};
+  auto *i = Deserialize<CapabilityInst>(words);
+  EXPECT_NE(nullptr, i);
+}
+
+TEST(InstructionTest, testOpExtension) {
+  uint8_t bytes[] = {0x0a, 0x00, 0x03, 0x00, 0x41, 0x42,
+                     0x43, 0x44, 0x45, 0x46, 'G',  0x00};
+  std::vector<uint32_t> words((uint32_t *)bytes,
+                              (uint32_t *)(bytes + sizeof(bytes)));
+  auto *i = Deserialize<ExtensionInst>(words);
+  ASSERT_NE(nullptr, i);
+  EXPECT_STREQ("ABCDEFG", i->mOperand1.c_str());
+}
+
+TEST(InstructionTest, testOpExtInstImport) {
+  uint8_t bytes[] = {0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+                     0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64,
+                     0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00};
+  std::vector<uint32_t> words((uint32_t *)bytes,
+                              (uint32_t *)(bytes + sizeof(bytes)));
+  auto *i = Deserialize<ExtInstImportInst>(words);
+  ASSERT_NE(nullptr, i);
+  EXPECT_STREQ("GLSL.std.450", i->mOperand1.c_str());
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/module.cpp b/rsov/compiler/spirit/module.cpp
new file mode 100644
index 0000000..d480912
--- /dev/null
+++ b/rsov/compiler/spirit/module.cpp
@@ -0,0 +1,989 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "module.h"
+
+#include <set>
+
+#include "builder.h"
+#include "core_defs.h"
+#include "instructions.h"
+#include "types_generated.h"
+#include "word_stream.h"
+
+namespace android {
+namespace spirit {
+
+Module *Module::mInstance = nullptr;
+
+Module *Module::getCurrentModule() {
+  if (mInstance == nullptr) {
+    return mInstance = new Module();
+  }
+  return mInstance;
+}
+
+Module::Module()
+    : mNextId(1), mCapabilitiesDeleter(mCapabilities),
+      mExtensionsDeleter(mExtensions), mExtInstImportsDeleter(mExtInstImports),
+      mEntryPointInstsDeleter(mEntryPointInsts),
+      mExecutionModesDeleter(mExecutionModes),
+      mEntryPointsDeleter(mEntryPoints),
+      mFunctionDefinitionsDeleter(mFunctionDefinitions) {
+  mInstance = this;
+}
+
+Module::Module(Builder *b)
+    : Entity(b), mNextId(1), mCapabilitiesDeleter(mCapabilities),
+      mExtensionsDeleter(mExtensions), mExtInstImportsDeleter(mExtInstImports),
+      mEntryPointInstsDeleter(mEntryPointInsts),
+      mExecutionModesDeleter(mExecutionModes),
+      mEntryPointsDeleter(mEntryPoints),
+      mFunctionDefinitionsDeleter(mFunctionDefinitions) {
+  mInstance = this;
+}
+
+bool Module::resolveIds() {
+  auto &table = mIdTable;
+
+  std::unique_ptr<IVisitor> v0(
+      CreateInstructionVisitor([&table](Instruction *inst) {
+        if (inst->hasResult()) {
+          table.insert(std::make_pair(inst->getId(), inst));
+        }
+      }));
+  v0->visit(this);
+
+  mNextId = mIdTable.rbegin()->first + 1;
+
+  int err = 0;
+  std::unique_ptr<IVisitor> v(
+      CreateInstructionVisitor([&table, &err](Instruction *inst) {
+        for (auto ref : inst->getAllIdRefs()) {
+          if (ref) {
+            auto it = table.find(ref->mId);
+            if (it != table.end()) {
+              ref->mInstruction = it->second;
+            } else {
+              std::cout << "Found no instruction for id " << ref->mId
+                        << std::endl;
+              err++;
+            }
+          }
+        }
+      }));
+  v->visit(this);
+  return err == 0;
+}
+
+bool Module::DeserializeInternal(InputWordStream &IS) {
+  if (IS.empty()) {
+    return false;
+  }
+
+  IS >> &mMagicNumber;
+  if (mMagicNumber != 0x07230203) {
+    errs() << "Wrong Magic Number: " << mMagicNumber;
+    return false;
+  }
+
+  if (IS.empty()) {
+    return false;
+  }
+
+  IS >> &mVersion.mWord;
+  if (mVersion.mBytes[0] != 0 || mVersion.mBytes[3] != 0) {
+    return false;
+  }
+
+  if (IS.empty()) {
+    return false;
+  }
+
+  IS >> &mGeneratorMagicNumber >> &mBound >> &mReserved;
+
+  DeserializeZeroOrMore<CapabilityInst>(IS, mCapabilities);
+  DeserializeZeroOrMore<ExtensionInst>(IS, mExtensions);
+  DeserializeZeroOrMore<ExtInstImportInst>(IS, mExtInstImports);
+
+  mMemoryModel.reset(Deserialize<MemoryModelInst>(IS));
+  if (!mMemoryModel) {
+    errs() << "Missing memory model specification.\n";
+    return false;
+  }
+
+  DeserializeZeroOrMore<EntryPointDefinition>(IS, mEntryPoints);
+  DeserializeZeroOrMore<ExecutionModeInst>(IS, mExecutionModes);
+  for (auto entry : mEntryPoints) {
+    mEntryPointInsts.push_back(entry->getInstruction());
+    for (auto mode : mExecutionModes) {
+      entry->applyExecutionMode(mode);
+    }
+  }
+
+  mDebugInfo.reset(Deserialize<DebugInfoSection>(IS));
+  mAnnotations.reset(Deserialize<AnnotationSection>(IS));
+  mGlobals.reset(Deserialize<GlobalSection>(IS));
+
+  DeserializeZeroOrMore<FunctionDefinition>(IS, mFunctionDefinitions);
+
+  if (mFunctionDefinitions.empty()) {
+    errs() << "Missing function definitions.\n";
+    for (int i = 0; i < 4; i++) {
+      uint32_t w;
+      IS >> &w;
+      std::cout << std::hex << w << " ";
+    }
+    std::cout << std::endl;
+    return false;
+  }
+
+  return true;
+}
+
+void Module::initialize() {
+  mMagicNumber = 0x07230203;
+  mVersion.mMajorMinor = {.mMinorNumber = 1, .mMajorNumber = 1};
+  mGeneratorMagicNumber = 0x00070000;
+  mBound = 0;
+  mReserved = 0;
+  mAnnotations.reset(new AnnotationSection());
+}
+
+void Module::SerializeHeader(OutputWordStream &OS) const {
+  OS << mMagicNumber;
+  OS << mVersion.mWord << mGeneratorMagicNumber;
+  if (mBound == 0) {
+    OS << mIdTable.end()->first + 1;
+  } else {
+    OS << std::max(mBound, mNextId);
+  }
+  OS << mReserved;
+}
+
+void Module::Serialize(OutputWordStream &OS) const {
+  SerializeHeader(OS);
+  Entity::Serialize(OS);
+}
+
+Module *Module::addCapability(Capability cap) {
+  mCapabilities.push_back(mBuilder->MakeCapability(cap));
+  return this;
+}
+
+Module *Module::setMemoryModel(AddressingModel am, MemoryModel mm) {
+  mMemoryModel.reset(mBuilder->MakeMemoryModel(am, mm));
+  return this;
+}
+
+Module *Module::addExtInstImport(const char *extName) {
+  ExtInstImportInst *extInst = mBuilder->MakeExtInstImport(extName);
+  mExtInstImports.push_back(extInst);
+  if (strcmp(extName, "GLSL.std.450") == 0) {
+    mGLExt = extInst;
+  }
+  return this;
+}
+
+Module *Module::addSource(SourceLanguage lang, int version) {
+  if (!mDebugInfo) {
+    mDebugInfo.reset(mBuilder->MakeDebugInfoSection());
+  }
+  mDebugInfo->addSource(lang, version);
+  return this;
+}
+
+Module *Module::addSourceExtension(const char *ext) {
+  if (!mDebugInfo) {
+    mDebugInfo.reset(mBuilder->MakeDebugInfoSection());
+  }
+  mDebugInfo->addSourceExtension(ext);
+  return this;
+}
+
+Module *Module::addString(const char *str) {
+  if (!mDebugInfo) {
+    mDebugInfo.reset(mBuilder->MakeDebugInfoSection());
+  }
+  mDebugInfo->addString(str);
+  return this;
+}
+
+Module *Module::addEntryPoint(EntryPointDefinition *entry) {
+  mEntryPoints.push_back(entry);
+  auto newModes = entry->getExecutionModes();
+  mExecutionModes.insert(mExecutionModes.end(), newModes.begin(),
+                         newModes.end());
+  return this;
+}
+
+const std::string Module::findStringOfPrefix(const char *prefix) const {
+  if (!mDebugInfo) {
+    return std::string();
+  }
+  return mDebugInfo->findStringOfPrefix(prefix);
+}
+
+GlobalSection *Module::getGlobalSection() {
+  if (!mGlobals) {
+    mGlobals.reset(new GlobalSection());
+  }
+  return mGlobals.get();
+}
+
+ConstantInst *Module::getConstant(TypeIntInst *type, int32_t value) {
+  return getGlobalSection()->getConstant(type, value);
+}
+
+ConstantInst *Module::getConstant(TypeIntInst *type, uint32_t value) {
+  return getGlobalSection()->getConstant(type, value);
+}
+
+ConstantInst *Module::getConstant(TypeFloatInst *type, float value) {
+  return getGlobalSection()->getConstant(type, value);
+}
+
+ConstantCompositeInst *Module::getConstantComposite(TypeVectorInst *type,
+                                                    ConstantInst *components[],
+                                                    size_t width) {
+  return getGlobalSection()->getConstantComposite(type, components, width);
+}
+
+ConstantCompositeInst *Module::getConstantComposite(TypeVectorInst *type,
+                                                    ConstantInst *comp0,
+                                                    ConstantInst *comp1,
+                                                    ConstantInst *comp2) {
+  // TODO: verify that component types are the same and consistent with the
+  // resulting vector type
+  ConstantInst *comps[] = {comp0, comp1, comp2};
+  return getConstantComposite(type, comps, 3);
+}
+
+ConstantCompositeInst *Module::getConstantComposite(TypeVectorInst *type,
+                                                    ConstantInst *comp0,
+                                                    ConstantInst *comp1,
+                                                    ConstantInst *comp2,
+                                                    ConstantInst *comp3) {
+  // TODO: verify that component types are the same and consistent with the
+  // resulting vector type
+  ConstantInst *comps[] = {comp0, comp1, comp2, comp3};
+  return getConstantComposite(type, comps, 4);
+}
+
+TypeVoidInst *Module::getVoidType() {
+  return getGlobalSection()->getVoidType();
+}
+
+TypeIntInst *Module::getIntType(int bits, bool isSigned) {
+  return getGlobalSection()->getIntType(bits, isSigned);
+}
+
+TypeIntInst *Module::getUnsignedIntType(int bits) {
+  return getIntType(bits, false);
+}
+
+TypeFloatInst *Module::getFloatType(int bits) {
+  return getGlobalSection()->getFloatType(bits);
+}
+
+TypeVectorInst *Module::getVectorType(Instruction *componentType, int width) {
+  return getGlobalSection()->getVectorType(componentType, width);
+}
+
+TypePointerInst *Module::getPointerType(StorageClass storage,
+                                        Instruction *pointeeType) {
+  return getGlobalSection()->getPointerType(storage, pointeeType);
+}
+
+TypeRuntimeArrayInst *Module::getRuntimeArrayType(Instruction *elementType) {
+  return getGlobalSection()->getRuntimeArrayType(elementType);
+}
+
+TypeStructInst *Module::getStructType(Instruction *fieldType[], int numField) {
+  return getGlobalSection()->getStructType(fieldType, numField);
+}
+
+TypeStructInst *Module::getStructType(Instruction *fieldType) {
+  return getStructType(&fieldType, 1);
+}
+
+TypeFunctionInst *Module::getFunctionType(Instruction *retType,
+                                          Instruction *const argType[],
+                                          size_t numArg) {
+  return getGlobalSection()->getFunctionType(retType, argType, numArg);
+}
+
+TypeFunctionInst *
+Module::getFunctionType(Instruction *retType,
+                        const std::vector<Instruction *> &argTypes) {
+  return getGlobalSection()->getFunctionType(retType, argTypes.data(),
+                                             argTypes.size());
+}
+
+size_t Module::getSize(TypeVoidInst *) { return 0; }
+
+size_t Module::getSize(TypeIntInst *intTy) { return intTy->mOperand1 / 8; }
+
+size_t Module::getSize(TypeFloatInst *fpTy) { return fpTy->mOperand1 / 8; }
+
+size_t Module::getSize(TypeVectorInst *vTy) {
+  return getSize(vTy->mOperand1.mInstruction) * vTy->mOperand2;
+}
+
+size_t Module::getSize(TypePointerInst *) {
+  return 4; // TODO: or 8?
+}
+
+size_t Module::getSize(TypeStructInst *structTy) {
+  size_t sz = 0;
+  for (auto ty : structTy->mOperand1) {
+    sz += getSize(ty.mInstruction);
+  }
+  return sz;
+}
+
+size_t Module::getSize(TypeFunctionInst *) {
+  return 4; // TODO: or 8? Is this just the size of a pointer?
+}
+
+size_t Module::getSize(Instruction *inst) {
+  switch (inst->getOpCode()) {
+  case OpTypeVoid:
+    return getSize(static_cast<TypeVoidInst *>(inst));
+  case OpTypeInt:
+    return getSize(static_cast<TypeIntInst *>(inst));
+  case OpTypeFloat:
+    return getSize(static_cast<TypeFloatInst *>(inst));
+  case OpTypeVector:
+    return getSize(static_cast<TypeVectorInst *>(inst));
+  case OpTypeStruct:
+    return getSize(static_cast<TypeStructInst *>(inst));
+  case OpTypeFunction:
+    return getSize(static_cast<TypeFunctionInst *>(inst));
+  default:
+    return 0;
+  }
+}
+
+Module *Module::addFunctionDefinition(FunctionDefinition *func) {
+  mFunctionDefinitions.push_back(func);
+  return this;
+}
+
+Instruction *Module::lookupByName(const char *name) const {
+  return mDebugInfo->lookupByName(name);
+}
+
+FunctionDefinition *
+Module::getFunctionDefinitionFromInstruction(FunctionInst *inst) const {
+  for (auto fdef : mFunctionDefinitions) {
+    if (fdef->getInstruction() == inst) {
+      return fdef;
+    }
+  }
+  return nullptr;
+}
+
+FunctionDefinition *
+Module::lookupFunctionDefinitionByName(const char *name) const {
+  FunctionInst *inst = static_cast<FunctionInst *>(lookupByName(name));
+  return getFunctionDefinitionFromInstruction(inst);
+}
+
+const char *Module::lookupNameByInstruction(const Instruction *inst) const {
+  return mDebugInfo->lookupNameByInstruction(inst);
+}
+
+VariableInst *Module::getInvocationId() {
+  return getGlobalSection()->getInvocationId();
+}
+
+VariableInst *Module::getNumWorkgroups() {
+  return getGlobalSection()->getNumWorkgroups();
+}
+
+Module *Module::addStructType(TypeStructInst *structType) {
+  getGlobalSection()->addStructType(structType);
+  return this;
+}
+
+Module *Module::addVariable(VariableInst *var) {
+  getGlobalSection()->addVariable(var);
+  return this;
+}
+
+void Module::consolidateAnnotations() {
+  std::vector<Instruction *> annotations(mAnnotations->begin(),
+                                      mAnnotations->end());
+  std::unique_ptr<IVisitor> v(
+      CreateInstructionVisitor([&annotations](Instruction *inst) -> void {
+        const auto &ann = inst->getAnnotations();
+        annotations.insert(annotations.end(), ann.begin(), ann.end());
+      }));
+  v->visit(this);
+  mAnnotations->clear();
+  mAnnotations->addAnnotations(annotations.begin(), annotations.end());
+}
+
+EntryPointDefinition::EntryPointDefinition(Builder *builder,
+                                           ExecutionModel execModel,
+                                           FunctionDefinition *func,
+                                           const char *name)
+    : Entity(builder), mFunction(func->getInstruction()),
+      mExecutionModel(execModel) {
+  mName = strndup(name, strlen(name));
+  mEntryPointInst = mBuilder->MakeEntryPoint(execModel, mFunction, mName);
+  (void)mExecutionModel; // suppress unused private field warning
+}
+
+bool EntryPointDefinition::DeserializeInternal(InputWordStream &IS) {
+  if (IS.empty()) {
+    return false;
+  }
+
+  if ((mEntryPointInst = Deserialize<EntryPointInst>(IS))) {
+    return true;
+  }
+
+  return false;
+}
+
+EntryPointDefinition *
+EntryPointDefinition::applyExecutionMode(ExecutionModeInst *mode) {
+  if (mode->mOperand1.mInstruction == mFunction) {
+    addExecutionMode(mode);
+  }
+  return this;
+}
+
+EntryPointDefinition *EntryPointDefinition::addToInterface(VariableInst *var) {
+  mInterface.push_back(var);
+  mEntryPointInst->mOperand4.push_back(var);
+  return this;
+}
+
+EntryPointDefinition *EntryPointDefinition::setLocalSize(uint32_t width,
+                                                         uint32_t height,
+                                                         uint32_t depth) {
+  mLocalSize.mWidth = width;
+  mLocalSize.mHeight = height;
+  mLocalSize.mDepth = depth;
+
+  auto mode = mBuilder->MakeExecutionMode(mFunction, ExecutionMode::LocalSize);
+  mode->addExtraOperand(width)->addExtraOperand(height)->addExtraOperand(depth);
+
+  addExecutionMode(mode);
+
+  return this;
+}
+
+bool DebugInfoSection::DeserializeInternal(InputWordStream &IS) {
+  while (true) {
+    if (auto str = Deserialize<StringInst>(IS)) {
+      mSources.push_back(str);
+    } else if (auto src = Deserialize<SourceInst>(IS)) {
+      mSources.push_back(src);
+    } else if (auto srcExt = Deserialize<SourceExtensionInst>(IS)) {
+      mSources.push_back(srcExt);
+    } else if (auto srcCont = Deserialize<SourceContinuedInst>(IS)) {
+      mSources.push_back(srcCont);
+    } else {
+      break;
+    }
+  }
+
+  while (true) {
+    if (auto name = Deserialize<NameInst>(IS)) {
+      mNames.push_back(name);
+    } else if (auto memName = Deserialize<MemberNameInst>(IS)) {
+      mNames.push_back(memName);
+    } else {
+      break;
+    }
+  }
+
+  return true;
+}
+
+DebugInfoSection *DebugInfoSection::addSource(SourceLanguage lang,
+                                              int version) {
+  SourceInst *source = mBuilder->MakeSource(lang, version);
+  mSources.push_back(source);
+  return this;
+}
+
+DebugInfoSection *DebugInfoSection::addSourceExtension(const char *ext) {
+  SourceExtensionInst *inst = mBuilder->MakeSourceExtension(ext);
+  mSources.push_back(inst);
+  return this;
+}
+
+DebugInfoSection *DebugInfoSection::addString(const char *str) {
+  StringInst *source = mBuilder->MakeString(str);
+  mSources.push_back(source);
+  return this;
+}
+
+std::string DebugInfoSection::findStringOfPrefix(const char *prefix) {
+  auto it = std::find_if(
+      mSources.begin(), mSources.end(), [prefix](Instruction *inst) -> bool {
+        if (inst->getOpCode() != OpString) {
+          return false;
+        }
+        const StringInst *strInst = static_cast<const StringInst *>(inst);
+        const std::string &str = strInst->mOperand1;
+        return str.find(prefix) == 0;
+      });
+  if (it == mSources.end()) {
+    return "";
+  }
+  StringInst *strInst = static_cast<StringInst *>(*it);
+  return strInst->mOperand1;
+}
+
+Instruction *DebugInfoSection::lookupByName(const char *name) const {
+  for (auto inst : mNames) {
+    if (inst->getOpCode() == OpName) {
+      NameInst *nameInst = static_cast<NameInst *>(inst);
+      if (nameInst->mOperand2.compare(name) == 0) {
+        return nameInst->mOperand1.mInstruction;
+      }
+    }
+    // Ignore member names
+  }
+  return nullptr;
+}
+
+const char *
+DebugInfoSection::lookupNameByInstruction(const Instruction *target) const {
+  for (auto inst : mNames) {
+    if (inst->getOpCode() == OpName) {
+      NameInst *nameInst = static_cast<NameInst *>(inst);
+      if (nameInst->mOperand1.mInstruction == target) {
+        return nameInst->mOperand2.c_str();
+      }
+    }
+    // Ignore member names
+  }
+  return nullptr;
+}
+
+AnnotationSection::AnnotationSection() : mAnnotationsDeleter(mAnnotations) {}
+
+AnnotationSection::AnnotationSection(Builder *b)
+    : Entity(b), mAnnotationsDeleter(mAnnotations) {}
+
+bool AnnotationSection::DeserializeInternal(InputWordStream &IS) {
+  while (true) {
+    if (auto decor = Deserialize<DecorateInst>(IS)) {
+      mAnnotations.push_back(decor);
+    } else if (auto decor = Deserialize<MemberDecorateInst>(IS)) {
+      mAnnotations.push_back(decor);
+    } else if (auto decor = Deserialize<GroupDecorateInst>(IS)) {
+      mAnnotations.push_back(decor);
+    } else if (auto decor = Deserialize<GroupMemberDecorateInst>(IS)) {
+      mAnnotations.push_back(decor);
+    } else if (auto decor = Deserialize<DecorationGroupInst>(IS)) {
+      mAnnotations.push_back(decor);
+    } else {
+      break;
+    }
+  }
+  return true;
+}
+
+GlobalSection::GlobalSection() : mGlobalDefsDeleter(mGlobalDefs) {}
+
+GlobalSection::GlobalSection(Builder *builder)
+    : Entity(builder), mGlobalDefsDeleter(mGlobalDefs) {}
+
+namespace {
+
+template <typename T>
+T *findOrCreate(std::function<bool(T *)> criteria, std::function<T *()> factory,
+                std::vector<Instruction *> *globals) {
+  T *derived;
+  for (auto inst : *globals) {
+    if (inst->getOpCode() == T::mOpCode) {
+      T *derived = static_cast<T *>(inst);
+      if (criteria(derived)) {
+        return derived;
+      }
+    }
+  }
+  derived = factory();
+  globals->push_back(derived);
+  return derived;
+}
+
+} // anonymous namespace
+
+bool GlobalSection::DeserializeInternal(InputWordStream &IS) {
+  while (true) {
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS)                                 \
+  if (auto typeInst = Deserialize<INST_CLASS>(IS)) {                           \
+    mGlobalDefs.push_back(typeInst);                                           \
+    continue;                                                                  \
+  }
+#include "const_inst_dispatches_generated.h"
+#include "type_inst_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+
+    if (auto globalInst = Deserialize<VariableInst>(IS)) {
+      // Check if this is function scoped
+      if (globalInst->mOperand1 == StorageClass::Function) {
+        Module::errs() << "warning: Variable (id = " << globalInst->mResult;
+        Module::errs() << ") has function scope in global section.\n";
+        // Khronos LLVM-SPIRV convertor emits "Function" storage-class globals.
+        // As a workaround, accept such SPIR-V code here, and fix it up later
+        // in the rs2spirv compiler by correcting the storage class.
+        // In a stricter deserializer, such code should be rejected, and we
+        // should return false here.
+      }
+      mGlobalDefs.push_back(globalInst);
+      continue;
+    }
+
+    if (auto globalInst = Deserialize<UndefInst>(IS)) {
+      mGlobalDefs.push_back(globalInst);
+      continue;
+    }
+    break;
+  }
+  return true;
+}
+
+ConstantInst *GlobalSection::getConstant(TypeIntInst *type, int32_t value) {
+  return findOrCreate<ConstantInst>(
+      [=](ConstantInst *c) { return c->mOperand1.intValue == value; },
+      [=]() -> ConstantInst * {
+        LiteralContextDependentNumber cdn = {.intValue = value};
+        return mBuilder->MakeConstant(type, cdn);
+      },
+      &mGlobalDefs);
+}
+
+ConstantInst *GlobalSection::getConstant(TypeIntInst *type, uint32_t value) {
+  return findOrCreate<ConstantInst>(
+      [=](ConstantInst *c) { return c->mOperand1.intValue == (int)value; },
+      [=]() -> ConstantInst * {
+        LiteralContextDependentNumber cdn = {.intValue = (int)value};
+        return mBuilder->MakeConstant(type, cdn);
+      },
+      &mGlobalDefs);
+}
+
+ConstantInst *GlobalSection::getConstant(TypeFloatInst *type, float value) {
+  return findOrCreate<ConstantInst>(
+      [=](ConstantInst *c) { return c->mOperand1.floatValue == value; },
+      [=]() -> ConstantInst * {
+        LiteralContextDependentNumber cdn = {.floatValue = value};
+        return mBuilder->MakeConstant(type, cdn);
+      },
+      &mGlobalDefs);
+}
+
+ConstantCompositeInst *
+GlobalSection::getConstantComposite(TypeVectorInst *type,
+                                    ConstantInst *components[], size_t width) {
+  return findOrCreate<ConstantCompositeInst>(
+      [=](ConstantCompositeInst *c) {
+        if (c->mOperand1.size() != width) {
+          return false;
+        }
+        for (size_t i = 0; i < width; i++) {
+          if (c->mOperand1[i].mInstruction != components[i]) {
+            return false;
+          }
+        }
+        return true;
+      },
+      [=]() -> ConstantCompositeInst * {
+        ConstantCompositeInst *c = mBuilder->MakeConstantComposite(type);
+        for (size_t i = 0; i < width; i++) {
+          c->mOperand1.push_back(components[i]);
+        }
+        return c;
+      },
+      &mGlobalDefs);
+}
+
+TypeVoidInst *GlobalSection::getVoidType() {
+  return findOrCreate<TypeVoidInst>(
+      [=](TypeVoidInst *) -> bool { return true; },
+      [=]() -> TypeVoidInst * { return mBuilder->MakeTypeVoid(); },
+      &mGlobalDefs);
+}
+
+TypeIntInst *GlobalSection::getIntType(int bits, bool isSigned) {
+  if (isSigned) {
+    switch (bits) {
+#define HANDLE_INT_SIZE(INT_TYPE, BITS, SIGNED)                                \
+  case BITS: {                                                                 \
+    return findOrCreate<TypeIntInst>(                                          \
+        [=](TypeIntInst *intTy) -> bool {                                      \
+          return intTy->mOperand1 == BITS && intTy->mOperand2 == SIGNED;       \
+        },                                                                     \
+        [=]() -> TypeIntInst * {                                               \
+          return mBuilder->MakeTypeInt(BITS, SIGNED);                          \
+        },                                                                     \
+        &mGlobalDefs);                                                         \
+  }
+      HANDLE_INT_SIZE(Int, 8, 1);
+      HANDLE_INT_SIZE(Int, 16, 1);
+      HANDLE_INT_SIZE(Int, 32, 1);
+      HANDLE_INT_SIZE(Int, 64, 1);
+    default:
+      Module::errs() << "unexpected int type";
+    }
+  } else {
+    switch (bits) {
+      HANDLE_INT_SIZE(UInt, 8, 0);
+      HANDLE_INT_SIZE(UInt, 16, 0);
+      HANDLE_INT_SIZE(UInt, 32, 0);
+      HANDLE_INT_SIZE(UInt, 64, 0);
+    default:
+      Module::errs() << "unexpected int type";
+    }
+  }
+#undef HANDLE_INT_SIZE
+  return nullptr;
+}
+
+TypeFloatInst *GlobalSection::getFloatType(int bits) {
+  switch (bits) {
+#define HANDLE_FLOAT_SIZE(BITS)                                                \
+  case BITS: {                                                                 \
+    return findOrCreate<TypeFloatInst>(                                        \
+        [=](TypeFloatInst *floatTy) -> bool {                                  \
+          return floatTy->mOperand1 == BITS;                                   \
+        },                                                                     \
+        [=]() -> TypeFloatInst * { return mBuilder->MakeTypeFloat(BITS); },    \
+        &mGlobalDefs);                                                         \
+  }
+    HANDLE_FLOAT_SIZE(16);
+    HANDLE_FLOAT_SIZE(32);
+    HANDLE_FLOAT_SIZE(64);
+  default:
+    Module::errs() << "unexpeced floating point type";
+  }
+#undef HANDLE_FLOAT_SIZE
+  return nullptr;
+}
+
+TypeVectorInst *GlobalSection::getVectorType(Instruction *componentType,
+                                             int width) {
+  // TODO: verify that componentType is basic numeric types
+
+  return findOrCreate<TypeVectorInst>(
+      [=](TypeVectorInst *vecTy) -> bool {
+        return vecTy->mOperand1.mInstruction == componentType &&
+               vecTy->mOperand2 == width;
+      },
+      [=]() -> TypeVectorInst * {
+        return mBuilder->MakeTypeVector(componentType, width);
+      },
+      &mGlobalDefs);
+}
+
+TypePointerInst *GlobalSection::getPointerType(StorageClass storage,
+                                               Instruction *pointeeType) {
+  return findOrCreate<TypePointerInst>(
+      [=](TypePointerInst *type) -> bool {
+        return type->mOperand1 == storage &&
+               type->mOperand2.mInstruction == pointeeType;
+      },
+      [=]() -> TypePointerInst * {
+        return mBuilder->MakeTypePointer(storage, pointeeType);
+      },
+      &mGlobalDefs);
+}
+
+TypeRuntimeArrayInst *
+GlobalSection::getRuntimeArrayType(Instruction *elemType) {
+  return findOrCreate<TypeRuntimeArrayInst>(
+      [=](TypeRuntimeArrayInst * /*type*/) -> bool {
+        // return type->mOperand1.mInstruction == elemType;
+        return false;
+      },
+      [=]() -> TypeRuntimeArrayInst * {
+        return mBuilder->MakeTypeRuntimeArray(elemType);
+      },
+      &mGlobalDefs);
+}
+
+TypeStructInst *GlobalSection::getStructType(Instruction *fieldType[],
+                                             int numField) {
+  TypeStructInst *structTy = mBuilder->MakeTypeStruct();
+  for (int i = 0; i < numField; i++) {
+    structTy->mOperand1.push_back(fieldType[i]);
+  }
+  mGlobalDefs.push_back(structTy);
+  return structTy;
+}
+
+TypeFunctionInst *GlobalSection::getFunctionType(Instruction *retType,
+                                                 Instruction *const argType[],
+                                                 size_t numArg) {
+  return findOrCreate<TypeFunctionInst>(
+      [=](TypeFunctionInst *type) -> bool {
+        if (type->mOperand1.mInstruction != retType ||
+            type->mOperand2.size() != numArg) {
+          return false;
+        }
+        for (size_t i = 0; i < numArg; i++) {
+          if (type->mOperand2[i].mInstruction != argType[i]) {
+            return false;
+          }
+        }
+        return true;
+      },
+      [=]() -> TypeFunctionInst * {
+        TypeFunctionInst *funcTy = mBuilder->MakeTypeFunction(retType);
+        for (size_t i = 0; i < numArg; i++) {
+          funcTy->mOperand2.push_back(argType[i]);
+        }
+        return funcTy;
+      },
+      &mGlobalDefs);
+}
+
+GlobalSection *GlobalSection::addStructType(TypeStructInst *structType) {
+  mGlobalDefs.push_back(structType);
+  return this;
+}
+
+GlobalSection *GlobalSection::addVariable(VariableInst *var) {
+  mGlobalDefs.push_back(var);
+  return this;
+}
+
+VariableInst *GlobalSection::getInvocationId() {
+  if (mInvocationId) {
+    return mInvocationId.get();
+  }
+
+  TypeIntInst *UIntTy = getIntType(32, false);
+  TypeVectorInst *V3UIntTy = getVectorType(UIntTy, 3);
+  TypePointerInst *V3UIntPtrTy = getPointerType(StorageClass::Input, V3UIntTy);
+
+  VariableInst *InvocationId =
+      mBuilder->MakeVariable(V3UIntPtrTy, StorageClass::Input);
+  InvocationId->decorate(Decoration::BuiltIn)
+      ->addExtraOperand(static_cast<uint32_t>(BuiltIn::GlobalInvocationId));
+
+  mInvocationId.reset(InvocationId);
+
+  return InvocationId;
+}
+
+VariableInst *GlobalSection::getNumWorkgroups() {
+  if (mNumWorkgroups) {
+    return mNumWorkgroups.get();
+  }
+
+  TypeIntInst *UIntTy = getIntType(32, false);
+  TypeVectorInst *V3UIntTy = getVectorType(UIntTy, 3);
+  TypePointerInst *V3UIntPtrTy = getPointerType(StorageClass::Input, V3UIntTy);
+
+  VariableInst *GNum = mBuilder->MakeVariable(V3UIntPtrTy, StorageClass::Input);
+  GNum->decorate(Decoration::BuiltIn)
+      ->addExtraOperand(static_cast<uint32_t>(BuiltIn::NumWorkgroups));
+
+  mNumWorkgroups.reset(GNum);
+
+  return GNum;
+}
+
+bool FunctionDeclaration::DeserializeInternal(InputWordStream &IS) {
+  if (!(mFunc = Deserialize<FunctionInst>(IS))) {
+    return false;
+  }
+
+  DeserializeZeroOrMore<FunctionParameterInst>(IS, mParams);
+
+  if (!(mFuncEnd = Deserialize<FunctionEndInst>(IS))) {
+    return false;
+  }
+
+  return true;
+}
+
+template <> Instruction *Deserialize(InputWordStream &IS) {
+  Instruction *inst;
+
+  switch ((*IS) & 0xFFFF) {
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS)                                 \
+  case OPCODE:                                                                 \
+    inst = Deserialize<INST_CLASS>(IS);                                        \
+    break;
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+  default:
+    Module::errs() << "unrecognized instruction";
+    inst = nullptr;
+  }
+
+  return inst;
+}
+
+bool Block::DeserializeInternal(InputWordStream &IS) {
+  Instruction *inst;
+  while (((*IS) & 0xFFFF) != OpFunctionEnd &&
+         (inst = Deserialize<Instruction>(IS))) {
+    mInsts.push_back(inst);
+    if (inst->getOpCode() == OpBranch ||
+        inst->getOpCode() == OpBranchConditional ||
+        inst->getOpCode() == OpSwitch || inst->getOpCode() == OpKill ||
+        inst->getOpCode() == OpReturn || inst->getOpCode() == OpReturnValue ||
+        inst->getOpCode() == OpUnreachable) {
+      break;
+    }
+  }
+  return !mInsts.empty();
+}
+
+FunctionDefinition::FunctionDefinition()
+    : mParamsDeleter(mParams), mBlocksDeleter(mBlocks) {}
+
+FunctionDefinition::FunctionDefinition(Builder *builder, FunctionInst *func,
+                                       FunctionEndInst *end)
+    : Entity(builder), mFunc(func), mFuncEnd(end), mParamsDeleter(mParams),
+      mBlocksDeleter(mBlocks) {}
+
+bool FunctionDefinition::DeserializeInternal(InputWordStream &IS) {
+  mFunc.reset(Deserialize<FunctionInst>(IS));
+  if (!mFunc) {
+    return false;
+  }
+
+  DeserializeZeroOrMore<FunctionParameterInst>(IS, mParams);
+  DeserializeZeroOrMore<Block>(IS, mBlocks);
+
+  mFuncEnd.reset(Deserialize<FunctionEndInst>(IS));
+  if (!mFuncEnd) {
+    return false;
+  }
+
+  return true;
+}
+
+Instruction *FunctionDefinition::getReturnType() const {
+  return mFunc->mResultType.mInstruction;
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/module.h b/rsov/compiler/spirit/module.h
new file mode 100644
index 0000000..cf0b1e0
--- /dev/null
+++ b/rsov/compiler/spirit/module.h
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MODULE_H
+#define MODULE_H
+
+#include <iostream>
+#include <map>
+#include <vector>
+
+#include "core_defs.h"
+#include "entity.h"
+#include "instructions.h"
+#include "stl_util.h"
+#include "types_generated.h"
+#include "visitor.h"
+
+namespace android {
+namespace spirit {
+
+class Builder;
+class AnnotationSection;
+class CapabilityInst;
+class DebugInfoSection;
+class ExtensionInst;
+class ExtInstImportInst;
+class EntryPointInst;
+class ExecutionModeInst;
+class EntryPointDefinition;
+class FunctionDeclaration;
+class FunctionDefinition;
+class GlobalSection;
+class InputWordStream;
+class Instruction;
+class MemoryModelInst;
+
+union VersionNumber {
+  struct {
+    uint8_t mLowZero;
+    uint8_t mMinorNumber;
+    uint8_t mMajorNumber;
+    uint8_t mHighZero;
+  } mMajorMinor;
+  uint8_t mBytes[4];
+  uint32_t mWord;
+};
+
+class Module : public Entity {
+public:
+  static Module *getCurrentModule();
+  uint32_t nextId() { return mNextId++; }
+
+  Module();
+
+  Module(Builder *b);
+
+  virtual ~Module() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  void Serialize(OutputWordStream &OS) const override;
+
+  void SerializeHeader(OutputWordStream &OS) const;
+
+  void registerId(uint32_t id, Instruction *inst) {
+    mIdTable.insert(std::make_pair(id, inst));
+  }
+
+  void initialize();
+
+  bool resolveIds();
+
+  void accept(IVisitor *v) override {
+    for (auto cap : mCapabilities) {
+      v->visit(cap);
+    }
+    for (auto ext : mExtensions) {
+      v->visit(ext);
+    }
+    for (auto imp : mExtInstImports) {
+      v->visit(imp);
+    }
+
+    v->visit(mMemoryModel.get());
+
+    for (auto entry : mEntryPoints) {
+      v->visit(entry);
+    }
+
+    for (auto mode : mExecutionModes) {
+      v->visit(mode);
+    }
+
+    v->visit(mDebugInfo.get());
+    if (mAnnotations) {
+      v->visit(mAnnotations.get());
+    }
+    if (mGlobals) {
+      v->visit(mGlobals.get());
+    }
+
+    for (auto def : mFunctionDefinitions) {
+      v->visit(def);
+    }
+  }
+
+  static std::ostream &errs() { return std::cerr; }
+
+  Module *addCapability(Capability cap);
+  Module *setMemoryModel(AddressingModel am, MemoryModel mm);
+  Module *addExtInstImport(const char *extName);
+  Module *addSource(SourceLanguage lang, int version);
+  Module *addSourceExtension(const char *ext);
+  Module *addString(const char *ext);
+  Module *addEntryPoint(EntryPointDefinition *entry);
+
+  ExtInstImportInst *getGLExt() const { return mGLExt; }
+
+  const std::string findStringOfPrefix(const char *prefix) const;
+
+  GlobalSection *getGlobalSection();
+
+  Instruction *lookupByName(const char *) const;
+  FunctionDefinition *
+  getFunctionDefinitionFromInstruction(FunctionInst *) const;
+  FunctionDefinition *lookupFunctionDefinitionByName(const char *name) const;
+
+  // Find the name of the instruction, e.g., the name of a function (OpFunction
+  // instruction).
+  // The returned string is owned by the OpName instruction, whose first operand
+  // is the instruction being queried on.
+  const char *lookupNameByInstruction(const Instruction *) const;
+
+  VariableInst *getInvocationId();
+  VariableInst *getNumWorkgroups();
+
+  // Adds a struct type built somewhere else.
+  Module *addStructType(TypeStructInst *structType);
+  Module *addVariable(VariableInst *var);
+
+  // Methods to look up types. Create them if not found.
+  TypeVoidInst *getVoidType();
+  TypeIntInst *getIntType(int bits, bool isSigned = true);
+  TypeIntInst *getUnsignedIntType(int bits);
+  TypeFloatInst *getFloatType(int bits);
+  TypeVectorInst *getVectorType(Instruction *componentType, int width);
+  TypePointerInst *getPointerType(StorageClass storage,
+                                  Instruction *pointeeType);
+  TypeRuntimeArrayInst *getRuntimeArrayType(Instruction *elementType);
+
+  // This implies that struct types are strictly structural equivalent, i.e.,
+  // two structs are equivalent i.f.f. their fields are equivalent, recursively.
+  TypeStructInst *getStructType(Instruction *fieldType[], int numField);
+  TypeStructInst *getStructType(const std::vector<Instruction *> &fieldType);
+  TypeStructInst *getStructType(Instruction *field0Type);
+  TypeStructInst *getStructType(Instruction *field0Type,
+                                Instruction *field1Type);
+  TypeStructInst *getStructType(Instruction *field0Type,
+                                Instruction *field1Type,
+                                Instruction *field2Type);
+
+  // TODO: Can function types of different decorations be considered the same?
+  TypeFunctionInst *getFunctionType(Instruction *retType,
+                                    Instruction *const argType[],
+                                    size_t numArg);
+  TypeFunctionInst *getFunctionType(Instruction *retType,
+                                    const std::vector<Instruction *> &argTypes);
+
+  size_t getSize(TypeVoidInst *voidTy);
+  size_t getSize(TypeIntInst *intTy);
+  size_t getSize(TypeFloatInst *fpTy);
+  size_t getSize(TypeVectorInst *vTy);
+  size_t getSize(TypePointerInst *ptrTy);
+  size_t getSize(TypeStructInst *structTy);
+  size_t getSize(TypeFunctionInst *funcTy);
+  size_t getSize(Instruction *inst);
+
+  ConstantInst *getConstant(TypeIntInst *type, int32_t value);
+  ConstantInst *getConstant(TypeIntInst *type, uint32_t value);
+  ConstantInst *getConstant(TypeFloatInst *type, float value);
+
+  ConstantCompositeInst *getConstantComposite(TypeVectorInst *type,
+                                              ConstantInst *components[],
+                                              size_t width);
+  ConstantCompositeInst *
+  getConstantComposite(Instruction *type,
+                       const std::vector<ConstantInst *> &components);
+  ConstantCompositeInst *getConstantComposite(Instruction *type,
+                                              ConstantInst *comp0,
+                                              ConstantInst *comp1);
+  ConstantCompositeInst *getConstantComposite(TypeVectorInst *type,
+                                              ConstantInst *comp0,
+                                              ConstantInst *comp1,
+                                              ConstantInst *comp2);
+  ConstantCompositeInst *getConstantComposite(TypeVectorInst *type,
+                                              ConstantInst *comp0,
+                                              ConstantInst *comp1,
+                                              ConstantInst *comp2,
+                                              ConstantInst *comp3);
+
+  Module *addFunctionDefinition(FunctionDefinition *func);
+
+  void consolidateAnnotations();
+
+private:
+  static Module *mInstance;
+  uint32_t mNextId;
+  std::map<uint32_t, Instruction *> mIdTable;
+
+  uint32_t mMagicNumber;
+  VersionNumber mVersion;
+  uint32_t mGeneratorMagicNumber;
+  uint32_t mBound;
+  uint32_t mReserved;
+
+  std::vector<CapabilityInst *> mCapabilities;
+  std::vector<ExtensionInst *> mExtensions;
+  std::vector<ExtInstImportInst *> mExtInstImports;
+  std::unique_ptr<MemoryModelInst> mMemoryModel;
+  std::vector<EntryPointInst *> mEntryPointInsts;
+  std::vector<ExecutionModeInst *> mExecutionModes;
+  std::vector<EntryPointDefinition *> mEntryPoints;
+  std::unique_ptr<DebugInfoSection> mDebugInfo;
+  std::unique_ptr<AnnotationSection> mAnnotations;
+  std::unique_ptr<GlobalSection> mGlobals;
+  std::vector<FunctionDefinition *> mFunctionDefinitions;
+
+  ExtInstImportInst *mGLExt;
+
+  ContainerDeleter<std::vector<CapabilityInst *>> mCapabilitiesDeleter;
+  ContainerDeleter<std::vector<ExtensionInst *>> mExtensionsDeleter;
+  ContainerDeleter<std::vector<ExtInstImportInst *>> mExtInstImportsDeleter;
+  ContainerDeleter<std::vector<EntryPointInst *>> mEntryPointInstsDeleter;
+  ContainerDeleter<std::vector<ExecutionModeInst *>> mExecutionModesDeleter;
+  ContainerDeleter<std::vector<EntryPointDefinition *>> mEntryPointsDeleter;
+  ContainerDeleter<std::vector<FunctionDefinition *>>
+      mFunctionDefinitionsDeleter;
+};
+
+struct Extent3D {
+  uint32_t mWidth;
+  uint32_t mHeight;
+  uint32_t mDepth;
+};
+
+class EntryPointDefinition : public Entity {
+public:
+  EntryPointDefinition() {}
+  EntryPointDefinition(Builder *builder, ExecutionModel execModel,
+                       FunctionDefinition *func, const char *name);
+
+  virtual ~EntryPointDefinition() {
+    // Nothing to do here since ~Module() will delete entities referenced here
+  }
+
+  void accept(IVisitor *visitor) override {
+    visitor->visit(mEntryPointInst);
+    // Do not visit the ExecutionMode instructions here. They are linked here
+    // for convinience, and for convinience only. They are all grouped, stored,
+    // and serialized directly in the module in a section right after all
+    // EntryPoint instructions. Visit them from there.
+  }
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  EntryPointDefinition *addToInterface(VariableInst *var);
+  EntryPointDefinition *addExecutionMode(ExecutionModeInst *mode) {
+    mExecutionModeInsts.push_back(mode);
+    return this;
+  }
+  const std::vector<ExecutionModeInst *> &getExecutionModes() const {
+    return mExecutionModeInsts;
+  }
+
+  EntryPointDefinition *setLocalSize(uint32_t width, uint32_t height,
+                                     uint32_t depth);
+
+  EntryPointDefinition *applyExecutionMode(ExecutionModeInst *mode);
+
+  EntryPointInst *getInstruction() const { return mEntryPointInst; }
+
+private:
+  const char *mName;
+  FunctionInst *mFunction;
+  ExecutionModel mExecutionModel;
+  std::vector<VariableInst *> mInterface;
+  Extent3D mLocalSize;
+
+  EntryPointInst *mEntryPointInst;
+  std::vector<ExecutionModeInst *> mExecutionModeInsts;
+};
+
+class DebugInfoSection : public Entity {
+public:
+  DebugInfoSection() : mSourcesDeleter(mSources), mNamesDeleter(mNames) {}
+  DebugInfoSection(Builder *b)
+      : Entity(b), mSourcesDeleter(mSources), mNamesDeleter(mNames) {}
+
+  virtual ~DebugInfoSection() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  DebugInfoSection *addSource(SourceLanguage lang, int version);
+  DebugInfoSection *addSourceExtension(const char *ext);
+  DebugInfoSection *addString(const char *str);
+
+  std::string findStringOfPrefix(const char *prefix);
+
+  Instruction *lookupByName(const char *name) const;
+  const char *lookupNameByInstruction(const Instruction *) const;
+
+  void accept(IVisitor *v) override {
+    for (auto source : mSources) {
+      v->visit(source);
+    }
+    for (auto name : mNames) {
+      v->visit(name);
+    }
+  }
+
+private:
+  // (OpString|OpSource|OpSourceExtension|OpSourceContinued)*
+  std::vector<Instruction *> mSources;
+  // (OpName|OpMemberName)*
+  std::vector<Instruction *> mNames;
+
+  ContainerDeleter<std::vector<Instruction *>> mSourcesDeleter;
+  ContainerDeleter<std::vector<Instruction *>> mNamesDeleter;
+};
+
+class AnnotationSection : public Entity {
+public:
+  AnnotationSection();
+  AnnotationSection(Builder *b);
+
+  virtual ~AnnotationSection() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  void accept(IVisitor *v) override {
+    for (auto inst : mAnnotations) {
+      v->visit(inst);
+    }
+  }
+
+  template <typename T> void addAnnotations(T begin, T end) {
+    mAnnotations.insert<T>(std::end(mAnnotations), begin, end);
+  }
+
+  std::vector<Instruction *>::const_iterator begin() const {
+    return mAnnotations.begin();
+  }
+
+  std::vector<Instruction *>::const_iterator end() const {
+    return mAnnotations.end();
+  }
+
+  void clear() { mAnnotations.clear(); }
+
+private:
+  std::vector<Instruction *> mAnnotations; // OpDecorate, etc.
+
+  ContainerDeleter<std::vector<Instruction *>> mAnnotationsDeleter;
+};
+
+// Types, constants, and globals
+class GlobalSection : public Entity {
+public:
+  GlobalSection();
+  GlobalSection(Builder *builder);
+
+  virtual ~GlobalSection() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  void accept(IVisitor *v) override {
+    for (auto inst : mGlobalDefs) {
+      v->visit(inst);
+    }
+
+    if (mInvocationId) {
+      v->visit(mInvocationId.get());
+    }
+
+    if (mNumWorkgroups) {
+      v->visit(mNumWorkgroups.get());
+    }
+  }
+
+  ConstantInst *getConstant(TypeIntInst *type, int32_t value);
+  ConstantInst *getConstant(TypeIntInst *type, uint32_t value);
+  ConstantInst *getConstant(TypeFloatInst *type, float value);
+  ConstantCompositeInst *getConstantComposite(TypeVectorInst *type,
+                                              ConstantInst *components[],
+                                              size_t width);
+
+  // Methods to look up types. Create them if not found.
+  TypeVoidInst *getVoidType();
+  TypeIntInst *getIntType(int bits, bool isSigned = true);
+  TypeFloatInst *getFloatType(int bits);
+  TypeVectorInst *getVectorType(Instruction *componentType, int width);
+  TypePointerInst *getPointerType(StorageClass storage,
+                                  Instruction *pointeeType);
+  TypeRuntimeArrayInst *getRuntimeArrayType(Instruction *elementType);
+
+  // This implies that struct types are strictly structural equivalent, i.e.,
+  // two structs are equivalent i.f.f. their fields are equivalent, recursively.
+  TypeStructInst *getStructType(Instruction *fieldType[], int numField);
+  // TypeStructInst *getStructType(const std::vector<Instruction *>
+  // &fieldTypes);
+
+  // TODO: Can function types of different decorations be considered the same?
+  TypeFunctionInst *getFunctionType(Instruction *retType,
+                                    Instruction *const argType[],
+                                    size_t numArg);
+  // TypeStructInst *addStructType(Instruction *fieldType[], int numField);
+  GlobalSection *addStructType(TypeStructInst *structType);
+  GlobalSection *addVariable(VariableInst *var);
+
+  VariableInst *getInvocationId();
+  VariableInst *getNumWorkgroups();
+
+private:
+  // TODO: Add structure to this.
+  // Separate types, constants, variables, etc.
+  std::vector<Instruction *> mGlobalDefs;
+  std::unique_ptr<VariableInst> mInvocationId;
+  std::unique_ptr<VariableInst> mNumWorkgroups;
+
+  ContainerDeleter<std::vector<Instruction *>> mGlobalDefsDeleter;
+};
+
+class FunctionDeclaration : public Entity {
+public:
+  virtual ~FunctionDeclaration() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  void accept(IVisitor *v) override {
+    v->visit(mFunc);
+    for (auto param : mParams) {
+      v->visit(param);
+    }
+    v->visit(mFuncEnd);
+  }
+
+private:
+  FunctionInst *mFunc;
+  std::vector<FunctionParameterInst *> mParams;
+  FunctionEndInst *mFuncEnd;
+};
+
+class Block : public Entity {
+public:
+  Block() {}
+  Block(Builder *b) : Entity(b) {}
+
+  virtual ~Block() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  void accept(IVisitor *v) override {
+    for (auto inst : mInsts) {
+      v->visit(inst);
+    }
+  }
+
+  Block *addInstruction(Instruction *inst) {
+    mInsts.push_back(inst);
+    return this;
+  }
+
+private:
+  std::vector<Instruction *> mInsts;
+};
+
+class FunctionDefinition : public Entity {
+public:
+  FunctionDefinition();
+  FunctionDefinition(Builder *builder, FunctionInst *func,
+                     FunctionEndInst *end);
+
+  virtual ~FunctionDefinition() {}
+
+  bool DeserializeInternal(InputWordStream &IS) override;
+
+  void accept(IVisitor *v) override {
+    v->visit(mFunc.get());
+    for (auto param : mParams) {
+      v->visit(param);
+    }
+    for (auto block : mBlocks) {
+      v->visit(block);
+    }
+    v->visit(mFuncEnd.get());
+  }
+
+  FunctionDefinition *addBlock(Block *b) {
+    mBlocks.push_back(b);
+    return this;
+  }
+
+  FunctionInst *getInstruction() const { return mFunc.get(); }
+  FunctionParameterInst *getParameter(uint32_t i) const { return mParams[i]; }
+
+  Instruction *getReturnType() const;
+
+private:
+  std::unique_ptr<FunctionInst> mFunc;
+  std::vector<FunctionParameterInst *> mParams;
+  std::vector<Block *> mBlocks;
+  std::unique_ptr<FunctionEndInst> mFuncEnd;
+
+  ContainerDeleter<std::vector<FunctionParameterInst *>> mParamsDeleter;
+  ContainerDeleter<std::vector<Block *>> mBlocksDeleter;
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // MODULE_H
diff --git a/rsov/compiler/spirit/module_test.cpp b/rsov/compiler/spirit/module_test.cpp
new file mode 100644
index 0000000..17d3134
--- /dev/null
+++ b/rsov/compiler/spirit/module_test.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "module.h"
+
+#include "file_utils.h"
+#include "instructions.h"
+#include "test_utils.h"
+#include "gtest/gtest.h"
+
+#include <fstream>
+#include <memory>
+
+namespace android {
+namespace spirit {
+
+class ModuleTest : public ::testing::Test {
+protected:
+  virtual void SetUp() {
+    mWordsGlobal = readWords("global.spv");
+    mWordsGreyscale = readWords("greyscale.spv");
+    mWordsGreyscale2 = readWords("greyscale2.spv");
+    mWordsInvert = readWords("invert.spv");
+  }
+
+  std::vector<uint32_t> mWordsGlobal;
+  std::vector<uint32_t> mWordsGreyscale;
+  std::vector<uint32_t> mWordsGreyscale2;
+  std::vector<uint32_t> mWordsInvert;
+
+private:
+  std::vector<uint32_t> readWords(const char *testFile) {
+    static const std::string testDataPath(
+        "frameworks/rs/rsov/compiler/spirit/test_data/");
+    const std::string &fullPath = getAbsolutePath(testDataPath + testFile);
+    return readFile<uint32_t>(fullPath);
+  }
+};
+
+TEST_F(ModuleTest, testDeserialization1) {
+  auto m = Deserialize<Module>(mWordsGreyscale);
+
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+
+  int count = 0;
+  std::unique_ptr<IVisitor> v(
+      CreateInstructionVisitor([&count](Instruction *) -> void { count++; }));
+  v->visit(m);
+
+  ASSERT_EQ(count, 123);
+
+  // TODO:: checkCountEntity<Instruction>() does not work correctly
+  //  EXPECT_TRUE(checkCountEntity<Instruction>(m, 123));
+  EXPECT_EQ(5, countEntity<AccessChainInst>(m));
+  EXPECT_EQ(2, countEntity<BitcastInst>(m));
+  EXPECT_EQ(1, countEntity<CapabilityInst>(m));
+  EXPECT_EQ(1, countEntity<CompositeConstructInst>(m));
+  EXPECT_EQ(5, countEntity<ConstantInst>(m));
+  EXPECT_EQ(1, countEntity<ConstantCompositeInst>(m));
+  EXPECT_EQ(11, countEntity<DecorateInst>(m));
+  EXPECT_EQ(1, countEntity<DotInst>(m));
+  EXPECT_EQ(1, countEntity<EntryPointInst>(m));
+  EXPECT_EQ(1, countEntity<ExecutionModeInst>(m));
+  EXPECT_EQ(1, countEntity<ExtInstImportInst>(m));
+  EXPECT_EQ(2, countEntity<FunctionInst>(m));
+  EXPECT_EQ(1, countEntity<FunctionCallInst>(m));
+  EXPECT_EQ(2, countEntity<FunctionEndInst>(m));
+  EXPECT_EQ(1, countEntity<FunctionParameterInst>(m));
+  EXPECT_EQ(1, countEntity<IAddInst>(m));
+  EXPECT_EQ(1, countEntity<IMulInst>(m));
+  EXPECT_EQ(1, countEntity<ImageInst>(m));
+  EXPECT_EQ(1, countEntity<ImageFetchInst>(m));
+  EXPECT_EQ(2, countEntity<LabelInst>(m));
+  EXPECT_EQ(11, countEntity<LoadInst>(m));
+  EXPECT_EQ(4, countEntity<MemberDecorateInst>(m));
+  EXPECT_EQ(4, countEntity<MemberNameInst>(m));
+  EXPECT_EQ(1, countEntity<MemoryModelInst>(m));
+  EXPECT_EQ(14, countEntity<NameInst>(m));
+  EXPECT_EQ(1, countEntity<ReturnInst>(m));
+  EXPECT_EQ(1, countEntity<ReturnValueInst>(m));
+  EXPECT_EQ(1, countEntity<SourceInst>(m));
+  EXPECT_EQ(3, countEntity<SourceExtensionInst>(m));
+  EXPECT_EQ(6, countEntity<StoreInst>(m));
+  EXPECT_EQ(1, countEntity<TypeFloatInst>(m));
+  EXPECT_EQ(2, countEntity<TypeFunctionInst>(m));
+  EXPECT_EQ(1, countEntity<TypeImageInst>(m));
+  EXPECT_EQ(2, countEntity<TypeIntInst>(m));
+  EXPECT_EQ(10, countEntity<TypePointerInst>(m));
+  EXPECT_EQ(1, countEntity<TypeRuntimeArrayInst>(m));
+  EXPECT_EQ(1, countEntity<TypeSampledImageInst>(m));
+  EXPECT_EQ(2, countEntity<TypeStructInst>(m));
+  EXPECT_EQ(4, countEntity<TypeVectorInst>(m));
+  EXPECT_EQ(1, countEntity<TypeVoidInst>(m));
+  EXPECT_EQ(9, countEntity<VariableInst>(m));
+  EXPECT_EQ(1, countEntity<VectorShuffleInst>(m));
+  EXPECT_EQ(1, countEntity<EntryPointDefinition>(m));
+  EXPECT_EQ(1, countEntity<DebugInfoSection>(m));
+  EXPECT_EQ(1, countEntity<GlobalSection>(m));
+  EXPECT_EQ(2, countEntity<FunctionDefinition>(m));
+}
+
+TEST_F(ModuleTest, testDeserialization2) {
+  Module *m = Deserialize<Module>(mWordsInvert);
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+
+  auto outwords = Serialize<Module>(m);
+
+  EXPECT_TRUE(mWordsInvert == outwords);
+}
+
+TEST_F(ModuleTest, testSerialization1) {
+  Module *m = Deserialize<Module>(mWordsGreyscale);
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+
+  EXPECT_EQ(2, countEntity<FunctionDefinition>(m));
+
+  auto outwords = Serialize<Module>(m);
+
+  EXPECT_TRUE(mWordsGreyscale == outwords);
+}
+
+TEST_F(ModuleTest, testSerialization2) {
+  Module *m = Deserialize<Module>(mWordsGreyscale2);
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+
+  EXPECT_EQ(1, countEntity<FunctionDefinition>(m));
+
+  auto outwords = Serialize<Module>(m);
+
+  EXPECT_TRUE(mWordsGreyscale2 == outwords);
+}
+
+TEST_F(ModuleTest, testLookupByName) {
+  Module *m = Deserialize<Module>(mWordsGreyscale);
+
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+
+  m->resolveIds();
+
+  Instruction *mainFunc = m->lookupByName("main");
+
+  EXPECT_NE(nullptr, mainFunc);
+  EXPECT_STREQ("main", m->lookupNameByInstruction(mainFunc));
+
+  auto i = static_cast<FunctionInst *>(m->lookupByName("greyscale(vf4;"));
+  ASSERT_NE(nullptr, i);
+
+  auto kernel = m->getFunctionDefinitionFromInstruction(i);
+  ASSERT_NE(nullptr, kernel);
+
+  EXPECT_NE(nullptr, kernel->getParameter(0));
+  EXPECT_NE(nullptr, kernel->getReturnType());
+
+  EXPECT_NE(nullptr, m->lookupFunctionDefinitionByName("greyscale(vf4;"));
+}
+
+TEST_F(ModuleTest, testGetSize) {
+  std::unique_ptr<Module> m(new Module());
+  EXPECT_EQ(4UL, m->getSize(m->getIntType(32)));
+  EXPECT_EQ(4UL, m->getSize(m->getIntType(32, 0)));
+  EXPECT_EQ(4UL, m->getSize(m->getFloatType(32)));
+  EXPECT_EQ(16UL, m->getSize(m->getVectorType(m->getFloatType(32), 4)));
+}
+
+TEST_F(ModuleTest, testFindStringOfPrefix) {
+  Module *m = Deserialize<Module>(mWordsGlobal);
+
+  ASSERT_NE(nullptr, m);
+
+  std::unique_ptr<Module> mDeleter(m);
+  ASSERT_STREQ(".rsov.ExportedVars:0;",
+               m->findStringOfPrefix(".rsov.ExportedVars:").c_str());
+
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/pass.cpp b/rsov/compiler/spirit/pass.cpp
new file mode 100644
index 0000000..d8c3afe
--- /dev/null
+++ b/rsov/compiler/spirit/pass.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pass.h"
+
+#include "module.h"
+
+namespace android {
+namespace spirit {
+
+Module *Pass::run(Module *module, int *error) {
+  int intermediateError;
+  auto words = runAndSerialize(module, &intermediateError);
+  if (intermediateError) {
+    if (error) {
+      *error = intermediateError;
+    }
+    return nullptr;
+  }
+  return Deserialize<Module>(words);
+}
+
+std::vector<uint32_t> Pass::runAndSerialize(Module *module, int *error) {
+  int intermediateError;
+  auto m1 = run(module, &intermediateError);
+  if (intermediateError) {
+    if (error) {
+      *error = intermediateError;
+    }
+    return std::vector<uint32_t>();
+  }
+  return Serialize<Module>(m1);
+}
+
+} // namespace spirit
+} // namespace android
+
diff --git a/rsov/compiler/spirit/pass.h b/rsov/compiler/spirit/pass.h
new file mode 100644
index 0000000..1d493a1
--- /dev/null
+++ b/rsov/compiler/spirit/pass.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_COMPILER_SPIRIT_PASS_H
+#define RSOV_COMPILER_SPIRIT_PASS_H
+
+#include <stdint.h>
+
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+class Module;
+
+// The base class for a pass, either an analysis or a transformation of a
+// Module. An instanace of a derived class can be added to a PassQueue and
+// applied to a Module, and produce a result Module with other passes.
+class Pass {
+public:
+  virtual ~Pass() {}
+
+  // Runs the pass  on the input module and returns the result module.
+  // If argument error is not null, set the error code. On a successful run,
+  // error code is set to zero.
+  virtual Module *run(Module *module, int *error);
+
+  // Runs the pass  on the input module, serializes the result module, and
+  // returns the words as a vector.
+  // If argument error is not null, set the error code. On a successful run,
+  // error code is set to zero.
+  virtual std::vector<uint32_t> runAndSerialize(Module *module, int *error);
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // RSOV_COMPILER_SPIRIT_PASS_H
diff --git a/rsov/compiler/spirit/pass_queue.cpp b/rsov/compiler/spirit/pass_queue.cpp
new file mode 100644
index 0000000..1bbdd2c
--- /dev/null
+++ b/rsov/compiler/spirit/pass_queue.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pass_queue.h"
+
+#include "module.h"
+
+namespace android {
+namespace spirit {
+
+bool PassQueue::append(Pass *pass) {
+  mPasses.push_back(pass);
+  mPassSet.insert(pass);
+  return true;
+}
+
+Module *PassQueue::run(Module *module, int *error) {
+  if (mPasses.empty()) {
+    return module;
+  }
+
+  // A unique ptr to keep intermediate modules from leaking
+  std::unique_ptr<Module> tempModule;
+
+  for (auto pass : mPasses) {
+    int intermediateError = 0;
+    Module* newModule = pass->run(module, &intermediateError);
+    // Some passes modify the input module in place, while others create a new
+    // module. Release memory only when it is necessary.
+    if (newModule != module) {
+      tempModule.reset(newModule);
+    }
+    module = newModule;
+    if (intermediateError) {
+      if (error) {
+        *error = intermediateError;
+      }
+      return nullptr;
+    }
+    if (!module || !module->resolveIds()) {
+      if (error) {
+        *error = -1;
+      }
+      return nullptr;
+    }
+  }
+
+  if (tempModule == nullptr) {
+    return module;
+  }
+
+  return tempModule.release();
+}
+
+std::vector<uint32_t> PassQueue::run(const std::vector<uint32_t> &spirvWords,
+                                     int *error) {
+  if (mPasses.empty()) {
+    return spirvWords;
+  }
+
+  Module *module = Deserialize<Module>(spirvWords);
+  if (!module || !module->resolveIds()) {
+    return std::vector<uint32_t>();
+  }
+
+  return runAndSerialize(module, error);
+}
+
+std::vector<uint32_t> PassQueue::runAndSerialize(Module *module, int *error) {
+  const int n = mPasses.size();
+  if (n < 1) {
+    return Serialize<Module>(module);
+  }
+
+  // A unique ptr to keep intermediate modules from leaking
+  std::unique_ptr<Module> tempModule;
+
+  for (int i = 0; i < n - 1; i++) {
+    int intermediateError = 0;
+    Module *newModule = mPasses[i]->run(module, &intermediateError);
+    // Some passes modify the input module in place, while others create a new
+    // module. Release memory only when it is necessary.
+    if (newModule != module) {
+      tempModule.reset(newModule);
+    }
+    module = newModule;
+    if (intermediateError) {
+      if (error) {
+        *error = intermediateError;
+      }
+      return std::vector<uint32_t>();
+    }
+    if (!module || !module->resolveIds()) {
+      if (error) {
+        *error = -1;
+      }
+      return std::vector<uint32_t>();
+    }
+  }
+  return mPasses[n - 1]->runAndSerialize(module, error);
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/pass_queue.h b/rsov/compiler/spirit/pass_queue.h
new file mode 100644
index 0000000..f00dcf7
--- /dev/null
+++ b/rsov/compiler/spirit/pass_queue.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_COMPILER_SPIRIT_PASS_QUEUE_H
+#define RSOV_COMPILER_SPIRIT_PASS_QUEUE_H
+
+#include "module.h"
+#include "pass.h"
+#include "stl_util.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <set>
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+// A FIFO of passes. Passes are appended to the end of the FIFO and run in the
+// first-in first-out order. Once appended to a pass queue, Passes are owned by
+// the queue.
+class PassQueue {
+public:
+  PassQueue() : mPassesDeleter(mPassSet) {}
+
+  // Appends a pass to the end of the queue
+  bool append(Pass *pass);
+
+  // Runs all passes in the queue in the first-in first-out order on a Module.
+  // Returns the result Module after all passes have run.
+  // If argument error is not null, sets the error code. On a successful run,
+  // error code is set to zero.
+  Module *run(Module *module, int *error = nullptr);
+
+  // Deserialize the input vector of words into a Module, and runs all passes in
+  // the queue in the first-in first-out order on the Module.
+  // for a serialized Module.
+  // After all the passes have run, returns the words from the serialized result
+  // Module.
+  // If argument error is not null, sets the error code. On a successful run,
+  // error code is set to zero.
+  std::vector<uint32_t> run(const std::vector<uint32_t> &spirvWords,
+                            int *error = nullptr);
+
+  // Runs all passes in the queue in the first-in first-out order on a Module.
+  // After all the passes have run, serializes the result Module, and returns
+  // the words as a vector.
+  // If argument error is not null, sets the error code. On a successful run,
+  // error code is set to zero.
+  std::vector<uint32_t> runAndSerialize(Module *module, int *error = nullptr);
+
+private:
+  std::vector<Pass *> mPasses;
+  // Keep all passes in a set so that we can delete them on destruction without
+  // worrying about duplicates
+  std::set<Pass *> mPassSet;
+  ContainerDeleter<std::set<Pass *>> mPassesDeleter;
+};
+
+} // spirit
+} // android
+
+#endif // RSOV_COMPILER_SPIRIT_PASS_QUEUE_H
diff --git a/rsov/compiler/spirit/pass_queue_test.cpp b/rsov/compiler/spirit/pass_queue_test.cpp
new file mode 100644
index 0000000..23e18e2
--- /dev/null
+++ b/rsov/compiler/spirit/pass_queue_test.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pass_queue.h"
+
+#include "file_utils.h"
+#include "spirit.h"
+#include "test_utils.h"
+#include "transformer.h"
+#include "gtest/gtest.h"
+
+#include <stdint.h>
+
+namespace android {
+namespace spirit {
+
+namespace {
+
+class MulToAddTransformer : public Transformer {
+public:
+  Instruction *transform(IMulInst *mul) override {
+    auto ret = new IAddInst(mul->mResultType, mul->mOperand1, mul->mOperand2);
+    ret->setId(mul->getId());
+    return ret;
+  }
+};
+
+class AddToDivTransformer : public Transformer {
+public:
+  Instruction *transform(IAddInst *add) override {
+    auto ret = new SDivInst(add->mResultType, add->mOperand1, add->mOperand2);
+    ret->setId(add->getId());
+    return ret;
+  }
+};
+
+class AddMulAfterAddTransformer : public Transformer {
+public:
+  Instruction *transform(IAddInst *add) override {
+    insert(add);
+    auto ret = new IMulInst(add->mResultType, add, add);
+    ret->setId(add->getId());
+    return ret;
+  }
+};
+
+class Deleter : public Transformer {
+public:
+  Instruction *transform(IMulInst *) override { return nullptr; }
+};
+
+class InPlaceModifyingPass : public Pass {
+public:
+  Module *run(Module *m, int *error) override {
+    m->getFloatType(64);
+    if (error) {
+      *error = 0;
+    }
+    return m;
+  }
+};
+
+} // annonymous namespace
+
+class PassQueueTest : public ::testing::Test {
+protected:
+  virtual void SetUp() { mWordsGreyscale = readWords("greyscale.spv"); }
+
+  std::vector<uint32_t> mWordsGreyscale;
+
+private:
+  std::vector<uint32_t> readWords(const char *testFile) {
+    static const std::string testDataPath(
+        "frameworks/rs/rsov/compiler/spirit/test_data/");
+    const std::string &fullPath = getAbsolutePath(testDataPath + testFile);
+    return readFile<uint32_t>(fullPath);
+  }
+};
+
+TEST_F(PassQueueTest, testMulToAdd) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new MulToAddTransformer());
+  auto m1 = passes.run(m.get());
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(2, countEntity<IAddInst>(m1));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1));
+}
+
+TEST_F(PassQueueTest, testInPlaceModifying) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+  EXPECT_EQ(1, countEntity<TypeFloatInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new InPlaceModifyingPass());
+  auto m1 = passes.run(m.get());
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m1));
+  EXPECT_EQ(1, countEntity<IMulInst>(m1));
+  EXPECT_EQ(2, countEntity<TypeFloatInst>(m1));
+}
+
+TEST_F(PassQueueTest, testDeletion) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m.get());
+
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new Deleter());
+  auto m1 = passes.run(m.get());
+
+  // One of the ids from the input module is missing now.
+  ASSERT_EQ(nullptr, m1);
+}
+
+TEST_F(PassQueueTest, testMulToAddToDiv) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new MulToAddTransformer());
+  passes.append(new AddToDivTransformer());
+  auto m1 = passes.run(m.get());
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(0, countEntity<IAddInst>(m1));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1));
+  EXPECT_EQ(2, countEntity<SDivInst>(m1));
+}
+
+TEST_F(PassQueueTest, testAMix) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+  EXPECT_EQ(0, countEntity<SDivInst>(m.get()));
+  EXPECT_EQ(1, countEntity<TypeFloatInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new MulToAddTransformer());
+  passes.append(new AddToDivTransformer());
+  passes.append(new InPlaceModifyingPass());
+
+  std::unique_ptr<Module> m1(passes.run(m.get()));
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(0, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<SDivInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<TypeFloatInst>(m1.get()));
+}
+
+TEST_F(PassQueueTest, testAnotherMix) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+  EXPECT_EQ(0, countEntity<SDivInst>(m.get()));
+  EXPECT_EQ(1, countEntity<TypeFloatInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new InPlaceModifyingPass());
+  passes.append(new MulToAddTransformer());
+  passes.append(new AddToDivTransformer());
+  auto outputWords = passes.runAndSerialize(m.get());
+
+  std::unique_ptr<Module> m1(Deserialize<Module>(outputWords));
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(0, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<SDivInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<TypeFloatInst>(m1.get()));
+}
+
+TEST_F(PassQueueTest, testMulToAddToDivFromWords) {
+  PassQueue passes;
+  passes.append(new MulToAddTransformer());
+  passes.append(new AddToDivTransformer());
+  auto outputWords = passes.run(std::move(mWordsGreyscale));
+
+  std::unique_ptr<Module> m1(Deserialize<Module>(outputWords));
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(0, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<SDivInst>(m1.get()));
+}
+
+TEST_F(PassQueueTest, testMulToAddToDivToWords) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  PassQueue passes;
+  passes.append(new MulToAddTransformer());
+  passes.append(new AddToDivTransformer());
+  auto outputWords = passes.runAndSerialize(m.get());
+
+  std::unique_ptr<Module> m1(Deserialize<Module>(outputWords));
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(0, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<SDivInst>(m1.get()));
+}
+
+TEST_F(PassQueueTest, testAddMulAfterAdd) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  constexpr int kNumMulToAdd = 100;
+
+  PassQueue passes;
+  for (int i = 0; i < kNumMulToAdd; i++) {
+    passes.append(new AddMulAfterAddTransformer());
+  }
+  auto outputWords = passes.runAndSerialize(m.get());
+
+  std::unique_ptr<Module> m1(Deserialize<Module>(outputWords));
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(1 + kNumMulToAdd, countEntity<IMulInst>(m1.get()));
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/compiler/spirit/spirit.h
similarity index 66%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/compiler/spirit/spirit.h
index b828ae0..7f631b1 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/compiler/spirit/spirit.h
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 2017, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,5 +14,12 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#ifndef SPIRIT_H
+#define SPIRIT_H
+
+#include "builder.h"
+#include "instructions.h"
+#include "module.h"
+#include "word_stream.h"
+
+#endif // SPIRIT_H
diff --git a/rsov/compiler/spirit/stl_util.h b/rsov/compiler/spirit/stl_util.h
new file mode 100644
index 0000000..0e59d05
--- /dev/null
+++ b/rsov/compiler/spirit/stl_util.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STL_UTIL_H
+#define STL_UTIL_H
+
+namespace android {
+namespace spirit {
+
+template <class T> class ContainerDeleter {
+public:
+  ContainerDeleter(T &container) : mContainer(container) {}
+  ~ContainerDeleter() {
+    for (auto *ptr : mContainer) {
+      delete ptr;
+    }
+  }
+
+private:
+  T &mContainer;
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // STL_UTIL_H
diff --git a/rsov/compiler/spirit/test_data/greyscale.spt b/rsov/compiler/spirit/test_data/greyscale.spt
new file mode 100644
index 0000000..3cfde69
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/greyscale.spt
@@ -0,0 +1,128 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 1
+; Bound: 75
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
+               OpExecutionMode %main LocalSize 4 1 1
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_shading_language_420pack"
+               OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+               OpSourceExtension "GL_GOOGLE_include_directive"
+               OpName %main "main"
+               OpName %greyscale_vf4_ "greyscale(vf4;"
+               OpName %p "p"
+               OpName %globalBuffer "globalBuffer"
+               OpMemberName %globalBuffer 0 "coeff"
+               OpMemberName %globalBuffer 1 "width"
+               OpMemberName %globalBuffer 2 "height"
+               OpName %globalBlock "globalBlock"
+               OpName %xy "xy"
+               OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+               OpName %inputPixel "inputPixel"
+               OpName %inputTexture "inputTexture"
+               OpName %res "res"
+               OpName %x "x"
+               OpName %y "y"
+               OpName %outputBufferS "outputBufferS"
+               OpMemberName %outputBufferS 0 "buf"
+               OpName %outputBuffer "outputBuffer"
+               OpMemberDecorate %globalBuffer 0 Offset 0
+               OpMemberDecorate %globalBuffer 1 Offset 16
+               OpMemberDecorate %globalBuffer 2 Offset 20
+               OpDecorate %globalBuffer BufferBlock
+               OpDecorate %globalBlock DescriptorSet 0
+               OpDecorate %globalBlock Binding 2
+               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+               OpDecorate %inputTexture DescriptorSet 0
+               OpDecorate %inputTexture Binding 0
+               OpDecorate %_runtimearr_v4float ArrayStride 16
+               OpMemberDecorate %outputBufferS 0 Offset 0
+               OpDecorate %outputBufferS BufferBlock
+               OpDecorate %outputBuffer DescriptorSet 0
+               OpDecorate %outputBuffer Binding 1
+               OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+          %8 = OpTypeFunction %v4float %v4float
+        %int = OpTypeInt 32 1
+%globalBuffer = OpTypeStruct %v4float %int %int
+%_ptr_Uniform_globalBuffer = OpTypePointer Uniform %globalBuffer
+%globalBlock = OpVariable %_ptr_Uniform_globalBuffer Uniform
+         %16 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+      %v2int = OpTypeVector %int 2
+%_ptr_Function_v2int = OpTypePointer Function %v2int
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+     %v2uint = OpTypeVector %uint 2
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+         %37 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %38 = OpTypeSampledImage %37
+%_ptr_UniformConstant_38 = OpTypePointer UniformConstant %38
+%inputTexture = OpVariable %_ptr_UniformConstant_38 UniformConstant
+%_ptr_Function_uint = OpTypePointer Function %uint
+         %50 = OpConstant %uint 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+         %55 = OpConstant %uint 1
+%_runtimearr_v4float = OpTypeRuntimeArray %v4float
+%outputBufferS = OpTypeStruct %_runtimearr_v4float
+%_ptr_Uniform_outputBufferS = OpTypePointer Uniform %outputBufferS
+%outputBuffer = OpVariable %_ptr_Uniform_outputBufferS Uniform
+         %63 = OpConstant %int 1
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+         %73 = OpConstant %uint 4
+%gl_WorkGroupSize = OpConstantComposite %v3uint %73 %55 %55
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %xy = OpVariable %_ptr_Function_v2int Function
+ %inputPixel = OpVariable %_ptr_Function_v4float Function
+        %res = OpVariable %_ptr_Function_v4float Function
+          %x = OpVariable %_ptr_Function_uint Function
+          %y = OpVariable %_ptr_Function_uint Function
+         %32 = OpLoad %v3uint %gl_GlobalInvocationID
+         %33 = OpVectorShuffle %v2uint %32 %32 0 1
+         %34 = OpBitcast %v2int %33
+               OpStore %xy %34
+         %41 = OpLoad %38 %inputTexture
+         %42 = OpLoad %v2int %xy
+         %43 = OpImage %37 %41
+         %44 = OpImageFetch %v4float %43 %42 Lod %16
+               OpStore %inputPixel %44
+         %46 = OpLoad %v4float %inputPixel
+         %47 = OpFunctionCall %v4float %greyscale_vf4_ %46
+               OpStore %res %47
+         %52 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %50
+         %53 = OpLoad %uint %52
+               OpStore %x %53
+         %56 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %55
+         %57 = OpLoad %uint %56
+               OpStore %y %57
+         %62 = OpLoad %uint %y
+         %65 = OpAccessChain %_ptr_Uniform_int %globalBlock %63
+         %66 = OpLoad %int %65
+         %67 = OpBitcast %uint %66
+         %68 = OpIMul %uint %62 %67
+         %69 = OpLoad %uint %x
+         %70 = OpIAdd %uint %68 %69
+         %71 = OpLoad %v4float %res
+         %72 = OpAccessChain %_ptr_Uniform_v4float %outputBuffer %16 %70
+               OpStore %72 %71
+               OpReturn
+               OpFunctionEnd
+%greyscale_vf4_ = OpFunction %v4float None %8
+          %p = OpFunctionParameter %v4float
+         %11 = OpLabel
+         %18 = OpAccessChain %_ptr_Uniform_v4float %globalBlock %16
+         %19 = OpLoad %v4float %18
+         %20 = OpDot %float %p %19
+         %21 = OpCompositeConstruct %v4float %20 %20 %20 %20
+               OpReturnValue %21
+               OpFunctionEnd
diff --git a/rsov/compiler/spirit/test_data/greyscale.spv b/rsov/compiler/spirit/test_data/greyscale.spv
new file mode 100644
index 0000000..97e39c1
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/greyscale.spv
Binary files differ
diff --git a/rsov/compiler/spirit/test_data/greyscale2.spt b/rsov/compiler/spirit/test_data/greyscale2.spt
new file mode 100644
index 0000000..51dc530
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/greyscale2.spt
@@ -0,0 +1,118 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 1
+; Bound: 67
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
+               OpExecutionMode %main LocalSize 2 1 1
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_shading_language_420pack"
+               OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+               OpSourceExtension "GL_GOOGLE_include_directive"
+               OpName %main "main"
+               OpName %xy "xy"
+               OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+               OpName %inputPixel "inputPixel"
+               OpName %inputTexture "inputTexture"
+               OpName %res "res"
+               OpName %globalBuffer "globalBuffer"
+               OpMemberName %globalBuffer 0 "coeff"
+               OpMemberName %globalBuffer 1 "width"
+               OpMemberName %globalBuffer 2 "height"
+               OpName %globalBlock "globalBlock"
+               OpName %x "x"
+               OpName %y "y"
+               OpName %outputBufferS "outputBufferS"
+               OpMemberName %outputBufferS 0 "buf"
+               OpName %outputBuffer "outputBuffer"
+               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+               OpDecorate %inputTexture DescriptorSet 0
+               OpDecorate %inputTexture Binding 0
+               OpMemberDecorate %globalBuffer 0 Offset 0
+               OpMemberDecorate %globalBuffer 1 Offset 16
+               OpMemberDecorate %globalBuffer 2 Offset 20
+               OpDecorate %globalBuffer BufferBlock
+               OpDecorate %globalBlock DescriptorSet 0
+               OpDecorate %globalBlock Binding 2
+               OpDecorate %_runtimearr_v4float ArrayStride 16
+               OpMemberDecorate %outputBufferS 0 Offset 0
+               OpDecorate %outputBufferS BufferBlock
+               OpDecorate %outputBuffer DescriptorSet 0
+               OpDecorate %outputBuffer Binding 1
+               OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%_ptr_Function_v2int = OpTypePointer Function %v2int
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+     %v2uint = OpTypeVector %uint 2
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+         %22 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %23 = OpTypeSampledImage %22
+%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
+%inputTexture = OpVariable %_ptr_UniformConstant_23 UniformConstant
+         %28 = OpConstant %int 0
+%globalBuffer = OpTypeStruct %v4float %int %int
+%_ptr_Uniform_globalBuffer = OpTypePointer Uniform %globalBuffer
+%globalBlock = OpVariable %_ptr_Uniform_globalBuffer Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%_ptr_Function_uint = OpTypePointer Function %uint
+         %42 = OpConstant %uint 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+         %47 = OpConstant %uint 1
+%_runtimearr_v4float = OpTypeRuntimeArray %v4float
+%outputBufferS = OpTypeStruct %_runtimearr_v4float
+%_ptr_Uniform_outputBufferS = OpTypePointer Uniform %outputBufferS
+%outputBuffer = OpVariable %_ptr_Uniform_outputBufferS Uniform
+         %55 = OpConstant %int 1
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+         %65 = OpConstant %uint 2
+%gl_WorkGroupSize = OpConstantComposite %v3uint %65 %47 %47
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %xy = OpVariable %_ptr_Function_v2int Function
+ %inputPixel = OpVariable %_ptr_Function_v4float Function
+        %res = OpVariable %_ptr_Function_v4float Function
+          %x = OpVariable %_ptr_Function_uint Function
+          %y = OpVariable %_ptr_Function_uint Function
+         %15 = OpLoad %v3uint %gl_GlobalInvocationID
+         %16 = OpVectorShuffle %v2uint %15 %15 0 1
+         %17 = OpBitcast %v2int %16
+               OpStore %xy %17
+         %26 = OpLoad %23 %inputTexture
+         %27 = OpLoad %v2int %xy
+         %29 = OpImageFetch %v4float %26 %27 Lod %28
+               OpStore %inputPixel %29
+         %31 = OpLoad %v4float %inputPixel
+         %36 = OpAccessChain %_ptr_Uniform_v4float %globalBlock %28
+         %37 = OpLoad %v4float %36
+         %38 = OpDot %float %31 %37
+         %39 = OpCompositeConstruct %v4float %38 %38 %38 %38
+               OpStore %res %39
+         %44 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %42
+         %45 = OpLoad %uint %44
+               OpStore %x %45
+         %48 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %47
+         %49 = OpLoad %uint %48
+               OpStore %y %49
+         %54 = OpLoad %uint %y
+         %57 = OpAccessChain %_ptr_Uniform_int %globalBlock %55
+         %58 = OpLoad %int %57
+         %59 = OpBitcast %uint %58
+         %60 = OpIMul %uint %54 %59
+         %61 = OpLoad %uint %x
+         %62 = OpIAdd %uint %60 %61
+         %63 = OpLoad %v4float %res
+         %64 = OpAccessChain %_ptr_Uniform_v4float %outputBuffer %28 %62
+               OpStore %64 %63
+               OpReturn
+               OpFunctionEnd
diff --git a/rsov/compiler/spirit/test_data/greyscale2.spv b/rsov/compiler/spirit/test_data/greyscale2.spv
new file mode 100644
index 0000000..088d96c
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/greyscale2.spv
Binary files differ
diff --git a/rsov/compiler/spirit/test_data/greyscale3.spt b/rsov/compiler/spirit/test_data/greyscale3.spt
new file mode 100644
index 0000000..ef60d11
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/greyscale3.spt
@@ -0,0 +1,115 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 1
+; Bound: 65
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
+               OpExecutionMode %main LocalSize 1 1 1
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_shading_language_420pack"
+               OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
+               OpSourceExtension "GL_GOOGLE_include_directive"
+               OpName %main "main"
+               OpName %xy "xy"
+               OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
+               OpName %inputPixel "inputPixel"
+               OpName %inputTexture "inputTexture"
+               OpName %res "res"
+               OpName %globalBuffer "globalBuffer"
+               OpMemberName %globalBuffer 0 "coeff"
+               OpMemberName %globalBuffer 1 "width"
+               OpMemberName %globalBuffer 2 "height"
+               OpName %globalBlock "globalBlock"
+               OpName %x "x"
+               OpName %y "y"
+               OpName %outputBufferS "outputBufferS"
+               OpMemberName %outputBufferS 0 "buf"
+               OpName %outputBuffer "outputBuffer"
+               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+               OpDecorate %inputTexture DescriptorSet 0
+               OpDecorate %inputTexture Binding 0
+               OpMemberDecorate %globalBuffer 0 Offset 0
+               OpMemberDecorate %globalBuffer 1 Offset 16
+               OpMemberDecorate %globalBuffer 2 Offset 20
+               OpDecorate %globalBuffer BufferBlock
+               OpDecorate %globalBlock DescriptorSet 0
+               OpDecorate %globalBlock Binding 2
+               OpDecorate %_runtimearr_v4float ArrayStride 16
+               OpMemberDecorate %outputBufferS 0 Offset 0
+               OpDecorate %outputBufferS BufferBlock
+               OpDecorate %outputBuffer DescriptorSet 0
+               OpDecorate %outputBuffer Binding 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %v2int = OpTypeVector %int 2
+%_ptr_Function_v2int = OpTypePointer Function %v2int
+       %uint = OpTypeInt 32 0
+     %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+     %v2uint = OpTypeVector %uint 2
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+         %22 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %23 = OpTypeSampledImage %22
+%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
+%inputTexture = OpVariable %_ptr_UniformConstant_23 UniformConstant
+         %28 = OpConstant %int 0
+%globalBuffer = OpTypeStruct %v4float %int %int
+%_ptr_Uniform_globalBuffer = OpTypePointer Uniform %globalBuffer
+%globalBlock = OpVariable %_ptr_Uniform_globalBuffer Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%_ptr_Function_uint = OpTypePointer Function %uint
+         %42 = OpConstant %uint 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+         %47 = OpConstant %uint 1
+%_runtimearr_v4float = OpTypeRuntimeArray %v4float
+%outputBufferS = OpTypeStruct %_runtimearr_v4float
+%_ptr_Uniform_outputBufferS = OpTypePointer Uniform %outputBufferS
+%outputBuffer = OpVariable %_ptr_Uniform_outputBufferS Uniform
+         %55 = OpConstant %int 1
+%_ptr_Uniform_int = OpTypePointer Uniform %int
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %xy = OpVariable %_ptr_Function_v2int Function
+ %inputPixel = OpVariable %_ptr_Function_v4float Function
+        %res = OpVariable %_ptr_Function_v4float Function
+          %x = OpVariable %_ptr_Function_uint Function
+          %y = OpVariable %_ptr_Function_uint Function
+         %15 = OpLoad %v3uint %gl_GlobalInvocationID
+         %16 = OpVectorShuffle %v2uint %15 %15 0 1
+         %17 = OpBitcast %v2int %16
+               OpStore %xy %17
+         %26 = OpLoad %23 %inputTexture
+         %27 = OpLoad %v2int %xy
+         %29 = OpImageFetch %v4float %26 %27 Lod %28
+               OpStore %inputPixel %29
+         %31 = OpLoad %v4float %inputPixel
+         %36 = OpAccessChain %_ptr_Uniform_v4float %globalBlock %28
+         %37 = OpLoad %v4float %36
+         %38 = OpDot %float %31 %37
+         %39 = OpCompositeConstruct %v4float %38 %38 %38 %38
+               OpStore %res %39
+         %44 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %42
+         %45 = OpLoad %uint %44
+               OpStore %x %45
+         %48 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %47
+         %49 = OpLoad %uint %48
+               OpStore %y %49
+         %54 = OpLoad %uint %y
+         %57 = OpAccessChain %_ptr_Uniform_int %globalBlock %55
+         %58 = OpLoad %int %57
+         %59 = OpBitcast %uint %58
+         %60 = OpIMul %uint %54 %59
+         %61 = OpLoad %uint %x
+         %62 = OpIAdd %uint %60 %61
+         %63 = OpLoad %v4float %res
+         %64 = OpAccessChain %_ptr_Uniform_v4float %outputBuffer %28 %62
+               OpStore %64 %63
+               OpReturn
+               OpFunctionEnd
diff --git a/rsov/compiler/spirit/test_data/greyscale3.spv b/rsov/compiler/spirit/test_data/greyscale3.spv
new file mode 100644
index 0000000..5f5cc8b
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/greyscale3.spv
Binary files differ
diff --git a/rsov/compiler/spirit/test_data/invert.spv b/rsov/compiler/spirit/test_data/invert.spv
new file mode 100644
index 0000000..604c589
--- /dev/null
+++ b/rsov/compiler/spirit/test_data/invert.spv
Binary files differ
diff --git a/rsov/compiler/spirit/test_utils.h b/rsov/compiler/spirit/test_utils.h
new file mode 100644
index 0000000..c255e1b
--- /dev/null
+++ b/rsov/compiler/spirit/test_utils.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_UTILS_H
+#define TEST_UTILS_H
+
+#include "gtest/gtest.h"
+
+namespace android {
+namespace spirit {
+
+template <typename T> class EntityCounter : public DoNothingVisitor {
+public:
+  EntityCounter() : mCount(0) {}
+
+  void visit(T *) override { mCount++; }
+
+  int getCount() const { return mCount; }
+
+private:
+  int mCount;
+};
+
+template <typename T> int countEntity(Entity *e) {
+  EntityCounter<T> v;
+  e->accept(&v);
+  return v.getCount();
+}
+
+// Returns a caller owned string for the full path to the relative path inside
+// the Android source tree
+static inline std::string getAbsolutePath(const std::string &relativePath) {
+  std::string full(getenv("ANDROID_BUILD_TOP"));
+  return full.append("/").append(relativePath);
+}
+
+} // namespace spirit
+} // namespace android
+
+#endif // TEST_UTILS_H
diff --git a/rsov/compiler/spirit/transformer.cpp b/rsov/compiler/spirit/transformer.cpp
new file mode 100644
index 0000000..0eb9621
--- /dev/null
+++ b/rsov/compiler/spirit/transformer.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "transformer.h"
+
+#include "module.h"
+
+namespace android {
+namespace spirit {
+
+Module *Transformer::run(Module *module, int *error) {
+  auto words = runAndSerialize(module, error);
+  return Deserialize<Module>(words);
+}
+
+std::vector<uint32_t> Transformer::runAndSerialize(Module *m, int *error) {
+  mModule = m;
+
+  // Since contents in the decoration or global section may change, transform
+  // and serialize the function definitions first.
+  mVisit = 0;
+  mShouldRecord = false;
+  mStream = mStreamFunctions.get();
+  m->accept(this);
+
+  // Record in the annotation section any new annotations added
+  m->consolidateAnnotations();
+
+  // After the functions are transformed, serialize the other sections to
+  // capture any changes made during the function transformation, and append
+  // the new words from function serialization.
+
+  mVisit = 1;
+  mShouldRecord = true;
+  mStream = mStreamFinal.get();
+
+  // TODO fix Module::accept() to have the header serialization code there
+  m->SerializeHeader(*mStream);
+  m->accept(this);
+
+  auto output = mStream->getWords();
+  auto functions = mStreamFunctions->getWords();
+  output.insert(output.end(), functions.begin(), functions.end());
+
+  if (error) {
+    *error = 0;
+  }
+
+  return output;
+}
+
+void Transformer::insert(Instruction *inst) {
+  // TODO: warn on nullptr inst
+  inst->Serialize(*mStream);
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/transformer.h b/rsov/compiler/spirit/transformer.h
new file mode 100644
index 0000000..e2293f7
--- /dev/null
+++ b/rsov/compiler/spirit/transformer.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TRANSFORMER_H
+#define TRANSFORMER_H
+
+#include <vector>
+
+#include "instructions.h"
+#include "pass.h"
+#include "visitor.h"
+#include "word_stream.h"
+
+namespace android {
+namespace spirit {
+
+// Transformer is the base class for a transformation that transforms a Module.
+// An instance of a derived class can be added to a PassQueue and applied to a
+// Module.
+class Transformer : public Pass, public DoNothingVisitor {
+public:
+  Transformer()
+      : mStreamFunctions(WordStream::Create()),
+        mStreamFinal(WordStream::Create()) {}
+
+  virtual ~Transformer() {}
+
+  Module *run(Module *m, int *error = nullptr) override;
+
+  std::vector<uint32_t> runAndSerialize(Module *module,
+                                        int *error = nullptr) override;
+
+  // Returns the module being transformed
+  Module *getModule() const { return mModule; }
+
+  // Inserts a new instruction before the current instruction.
+  // Call this from a transform() method in a derived class.
+  void insert(Instruction *);
+
+  void visit(FunctionDefinition *fdef) override {
+    mShouldRecord = (mVisit == 0);
+    DoNothingVisitor::visit(fdef);
+  }
+
+  // Transforms the current instruction into a new instruction as specified by
+  // the return value. If returns nullptr, deletes the current instruction.
+  // Override this in a derived class for desired behavior.
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS)                                 \
+  virtual Instruction *transform(INST_CLASS *inst) {                           \
+    return static_cast<Instruction *>(inst);                                   \
+  }                                                                            \
+  virtual void visit(INST_CLASS *inst) {                                       \
+    if (!mShouldRecord) {                                                      \
+      return;                                                                  \
+    }                                                                          \
+    if (Instruction *transformed = transform(inst)) {                          \
+      transformed->Serialize(*mStream);                                        \
+    }                                                                          \
+  }
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+
+private:
+  Module *mModule;
+  int mVisit;
+  bool mShouldRecord;
+  std::unique_ptr<WordStream> mStreamFunctions;
+  std::unique_ptr<WordStream> mStreamFinal;
+  WordStream *mStream;
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // TRANSFORMER_H
diff --git a/rsov/compiler/spirit/transformer_test.cpp b/rsov/compiler/spirit/transformer_test.cpp
new file mode 100644
index 0000000..a78969f
--- /dev/null
+++ b/rsov/compiler/spirit/transformer_test.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "transformer.h"
+
+#include "file_utils.h"
+#include "spirit.h"
+#include "test_utils.h"
+#include "gtest/gtest.h"
+
+#include <stdint.h>
+
+namespace android {
+namespace spirit {
+
+namespace {
+
+class MulToAddTransformer : public Transformer {
+public:
+  Instruction *transform(IMulInst *mul) override {
+    auto ret = new IAddInst(mul->mResultType, mul->mOperand1, mul->mOperand2);
+    ret->setId(mul->getId());
+    return ret;
+  }
+};
+
+class Deleter : public Transformer {
+public:
+  Instruction *transform(IMulInst *) override { return nullptr; }
+};
+
+class NewDataTypeTransformer : public Transformer {
+public:
+  Instruction *transform(IMulInst *mul) override {
+    insert(mul);
+    auto *DoubleTy = getModule()->getFloatType(64);
+    ConstantInst *ConstDouble2 = getModule()->getConstant(DoubleTy, 2.0);
+    auto ret = new IAddInst(DoubleTy, mul, ConstDouble2);
+
+    IdResult id = ret->getId();
+    ret->setId(mul->getId());
+    mul->setId(id);
+
+    return ret;
+  }
+};
+
+} // annonymous namespace
+
+class TransformerTest : public ::testing::Test {
+protected:
+  virtual void SetUp() { mWordsGreyscale = readWords("greyscale.spv"); }
+
+  std::vector<uint32_t> mWordsGreyscale;
+
+private:
+  std::vector<uint32_t> readWords(const char *testFile) {
+    static const std::string testDataPath(
+        "frameworks/rs/rsov/compiler/spirit/test_data/");
+    const std::string &fullPath = getAbsolutePath(testDataPath + testFile);
+    return readFile<uint32_t>(fullPath);
+  }
+};
+
+TEST_F(TransformerTest, testMulToAdd) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m);
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  MulToAddTransformer trans;
+  std::unique_ptr<Module> m1(trans.run(m.get()));
+
+  ASSERT_NE(nullptr, m1);
+
+  ASSERT_TRUE(m1->resolveIds());
+
+  EXPECT_EQ(2, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
+}
+
+TEST_F(TransformerTest, testDeletion) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m.get());
+
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  Deleter trans;
+  std::unique_ptr<Module> m1(trans.run(m.get()));
+
+  ASSERT_NE(nullptr, m1.get());
+
+  EXPECT_EQ(1, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(0, countEntity<IMulInst>(m1.get()));
+}
+
+TEST_F(TransformerTest, testAddInstructionUsingNewDataType) {
+  std::unique_ptr<Module> m(Deserialize<Module>(mWordsGreyscale));
+
+  ASSERT_NE(nullptr, m.get());
+
+  EXPECT_EQ(5, countEntity<ConstantInst>(m.get()));
+  EXPECT_EQ(1, countEntity<TypeFloatInst>(m.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m.get()));
+
+  NewDataTypeTransformer trans;
+  std::unique_ptr<Module> m1(trans.run(m.get()));
+
+  ASSERT_NE(nullptr, m1.get());
+
+  EXPECT_EQ(6, countEntity<ConstantInst>(m.get()));
+  EXPECT_EQ(2, countEntity<TypeFloatInst>(m1.get()));
+  EXPECT_EQ(2, countEntity<IAddInst>(m1.get()));
+  EXPECT_EQ(1, countEntity<IMulInst>(m1.get()));
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/visitor.cpp b/rsov/compiler/spirit/visitor.cpp
new file mode 100644
index 0000000..dcc6322
--- /dev/null
+++ b/rsov/compiler/spirit/visitor.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "visitor.h"
+
+#include "instructions.h"
+#include "module.h"
+
+namespace android {
+namespace spirit {
+
+void DoNothingVisitor::visit(Entity *e) { e->accept(this); }
+
+void DoNothingVisitor::visit(Module *m) { m->accept(this); }
+
+void DoNothingVisitor::visit(EntryPointDefinition *entry) {
+  entry->accept(this);
+}
+
+void DoNothingVisitor::visit(DebugInfoSection *dinfo) { dinfo->accept(this); }
+
+void DoNothingVisitor::visit(AnnotationSection *a) { a->accept(this); }
+
+void DoNothingVisitor::visit(GlobalSection *g) { g->accept(this); }
+void DoNothingVisitor::visit(FunctionDeclaration *fdecl) {
+  fdecl->accept(this);
+}
+void DoNothingVisitor::visit(Block *b) { b->accept(this); }
+void DoNothingVisitor::visit(FunctionDefinition *fdef) { fdef->accept(this); }
+void DoNothingVisitor::visit(Instruction *inst) { inst->accept(this); }
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS)                                 \
+  void DoNothingVisitor::visit(INST_CLASS *) {}
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/visitor.h b/rsov/compiler/spirit/visitor.h
new file mode 100644
index 0000000..0e41537
--- /dev/null
+++ b/rsov/compiler/spirit/visitor.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VISITOR_H
+#define VISITOR_H
+
+#include <functional>
+
+namespace android {
+namespace spirit {
+
+class Entity;
+class Module;
+class EntryPointDefinition;
+class DebugInfoSection;
+class AnnotationSection;
+class GlobalSection;
+class FunctionDeclaration;
+class Block;
+class FunctionDefinition;
+class Instruction;
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS) class INST_CLASS;
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+
+class IVisitor {
+public:
+  virtual ~IVisitor() {}
+
+  virtual void visit(Entity *) = 0;
+  virtual void visit(Module *) = 0;
+  virtual void visit(EntryPointDefinition *) = 0;
+  virtual void visit(DebugInfoSection *) = 0;
+  virtual void visit(AnnotationSection *) = 0;
+  virtual void visit(GlobalSection *) = 0;
+  virtual void visit(FunctionDeclaration *) = 0;
+  virtual void visit(Block *) = 0;
+  virtual void visit(FunctionDefinition *) = 0;
+  virtual void visit(Instruction *) = 0;
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS)                                 \
+  virtual void visit(INST_CLASS *) = 0;
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+};
+
+class DoNothingVisitor : public IVisitor {
+public:
+  virtual ~DoNothingVisitor() {}
+
+  virtual void visit(Entity *e);
+  virtual void visit(Module *m);
+  virtual void visit(EntryPointDefinition *);
+  virtual void visit(DebugInfoSection *dinfo);
+  virtual void visit(AnnotationSection *a);
+  virtual void visit(GlobalSection *g);
+  virtual void visit(FunctionDeclaration *fdecl);
+  virtual void visit(Block *b);
+  virtual void visit(FunctionDefinition *fdef);
+  // This visit(Instruction *) necessary?
+  virtual void visit(Instruction *inst);
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS) virtual void visit(INST_CLASS *);
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+};
+
+template <typename T> class InstructionVisitor : public DoNothingVisitor {
+public:
+  InstructionVisitor(T action) : mAction(action) {}
+
+  virtual ~InstructionVisitor() {}
+
+#define HANDLE_INSTRUCTION(OPCODE, INST_CLASS)                                 \
+  void visit(INST_CLASS *inst) override { mAction((Instruction *)inst); }
+#include "instruction_dispatches_generated.h"
+#undef HANDLE_INSTRUCTION
+
+private:
+  T mAction;
+};
+
+template <typename T> static IVisitor *CreateInstructionVisitor(T action) {
+  return new InstructionVisitor<decltype(action)>(action);
+}
+
+} // namespace spirit
+} // namespace android
+
+#endif // VISITOR_H
diff --git a/rsov/compiler/spirit/word_stream.cpp b/rsov/compiler/spirit/word_stream.cpp
new file mode 100644
index 0000000..7061577
--- /dev/null
+++ b/rsov/compiler/spirit/word_stream.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "word_stream.h"
+
+#include "file_utils.h"
+#include "word_stream_impl.h"
+
+namespace android {
+namespace spirit {
+
+InputWordStream *InputWordStream::Create() { return new WordStreamImpl(); }
+
+InputWordStream *InputWordStream::Create(std::vector<uint32_t> &&words) {
+  return new WordStreamImpl(words);
+}
+
+InputWordStream *InputWordStream::Create(const std::vector<uint32_t> &words) {
+  return new WordStreamImpl(words);
+}
+
+InputWordStream *InputWordStream::Create(const std::vector<uint8_t> &bytes) {
+  std::vector<uint32_t> words((uint32_t *)bytes.data(),
+                              (uint32_t *)(bytes.data() + bytes.size()));
+  return InputWordStream::Create(words);
+}
+
+InputWordStream *InputWordStream::Create(const char *filePath) {
+  return InputWordStream::Create(readFile<uint32_t>(filePath));
+}
+
+OutputWordStream *OutputWordStream::Create() { return new WordStreamImpl(); }
+
+WordStream *WordStream::Create() { return new WordStreamImpl(); }
+
+WordStream *WordStream::Create(const std::vector<uint32_t> &words) {
+  return new WordStreamImpl(words);
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/word_stream.h b/rsov/compiler/spirit/word_stream.h
new file mode 100644
index 0000000..94333bb
--- /dev/null
+++ b/rsov/compiler/spirit/word_stream.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WORD_STREAM_H
+#define WORD_STREAM_H
+
+#include "core_defs.h"
+#include "types_generated.h"
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+struct IdRef;
+class Instruction;
+
+class InputWordStream {
+public:
+  static InputWordStream *Create();
+  static InputWordStream *Create(std::vector<uint32_t> &&words);
+  static InputWordStream *Create(const std::vector<uint32_t> &words);
+  static InputWordStream *Create(const std::vector<uint8_t> &bytes);
+  static InputWordStream *Create(const char *fileName);
+
+  virtual ~InputWordStream() {}
+
+  virtual bool empty() const = 0;
+  virtual uint32_t operator*() = 0;
+
+  virtual InputWordStream &operator>>(uint32_t *RHS) = 0;
+  virtual InputWordStream &operator>>(LiteralContextDependentNumber *num) = 0;
+  virtual InputWordStream &operator>>(std::string *str) = 0;
+
+  InputWordStream &operator>>(int32_t *RHS) { return *this >> (uint32_t *)RHS; }
+
+  InputWordStream &operator>>(OpCodeAndWordCount *codeCount) {
+    uint32_t word;
+    *this >> &word;
+    *codeCount = word;
+    return *this;
+  }
+
+  InputWordStream &operator>>(IdRef *RHS) {
+    // The referred instruction will be resolved later towards the end of the
+    // deserialization of the module after all instructions have been
+    // deserialized.
+    // It cannot be resolved here because it may be a forward reference.
+    RHS->mInstruction = nullptr;
+    return *this >> &RHS->mId;
+    ;
+  }
+
+  InputWordStream &operator>>(PairLiteralIntegerIdRef *RHS) {
+    return *this >> &RHS->mField0 >> &RHS->mField1;
+  }
+
+  InputWordStream &operator>>(PairIdRefLiteralInteger *RHS) {
+    return *this >> &RHS->mField0 >> &RHS->mField1;
+  }
+
+  InputWordStream &operator>>(PairIdRefIdRef *RHS) {
+    return *this >> &RHS->mField0 >> &RHS->mField1;
+  }
+
+#define HANDLE_ENUM(Enum)                                                      \
+  InputWordStream &operator>>(Enum *RHS) { return *this >> (uint32_t *)RHS; }
+#include "enum_dispatches_generated.h"
+#undef HANDLE_ENUM
+};
+
+class OutputWordStream {
+public:
+  static OutputWordStream *Create();
+
+  virtual ~OutputWordStream() {}
+
+  virtual std::vector<uint32_t> getWords() = 0;
+
+  virtual OutputWordStream &operator<<(const uint32_t RHS) = 0;
+  virtual OutputWordStream &
+  operator<<(const LiteralContextDependentNumber &RHS) = 0;
+  virtual OutputWordStream &operator<<(const std::string &str) = 0;
+
+  OutputWordStream &operator<<(const int32_t RHS) {
+    return *this << (uint32_t)RHS;
+  }
+
+  OutputWordStream &operator<<(const OpCodeAndWordCount codeCount) {
+    return *this << (uint32_t)codeCount;
+  }
+
+  OutputWordStream &operator<<(const IdRef &RHS) {
+    return *this << RHS.mId;
+  }
+
+  OutputWordStream &operator<<(const PairLiteralIntegerIdRef &RHS) {
+    return *this << RHS.mField0 << RHS.mField1;
+  }
+
+  OutputWordStream &operator<<(const PairIdRefLiteralInteger &RHS) {
+    return *this << RHS.mField0 << RHS.mField1;
+  }
+
+  OutputWordStream &operator<<(const PairIdRefIdRef &RHS) {
+    return *this << RHS.mField0 << RHS.mField1;
+  }
+
+#define HANDLE_ENUM(Enum)                                                      \
+  OutputWordStream &operator<<(const Enum RHS) {                               \
+    return *this << static_cast<uint32_t>(RHS);                                \
+  }
+#include "enum_dispatches_generated.h"
+#undef HANDLE_ENUM
+};
+
+class WordStream : public InputWordStream, public OutputWordStream {
+public:
+  static WordStream *Create();
+  static WordStream *Create(const std::vector<uint32_t> &words);
+
+  virtual ~WordStream() {}
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // WORD_STREAM_H
diff --git a/rsov/compiler/spirit/word_stream_impl.cpp b/rsov/compiler/spirit/word_stream_impl.cpp
new file mode 100644
index 0000000..33749e7
--- /dev/null
+++ b/rsov/compiler/spirit/word_stream_impl.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "word_stream_impl.h"
+
+namespace android {
+namespace spirit {
+
+WordStreamImpl::WordStreamImpl() {}
+
+WordStreamImpl::WordStreamImpl(const std::vector<uint32_t> &words)
+    : mWords(words), mIter(mWords.begin()) {}
+
+WordStreamImpl::WordStreamImpl(std::vector<uint32_t> &&words)
+    : mWords(words), mIter(mWords.begin()) {}
+
+WordStreamImpl &WordStreamImpl::operator<<(const std::string &str) {
+  const size_t len = str.length();
+  const uint32_t *begin = (uint32_t *)str.c_str();
+  const uint32_t *end = begin + (len / 4);
+  mWords.insert(mWords.end(), begin, end);
+
+  uint32_t lastWord = *end;
+  uint32_t mask = 0xFF;
+  bool clear = false;
+  for (int i = 0; i < 4; i++, mask <<= 8) {
+    if (clear) {
+      lastWord &= ~mask;
+    } else {
+      clear = ((lastWord & mask) == 0);
+    }
+  }
+  mWords.push_back(lastWord);
+  return *this;
+}
+
+WordStreamImpl &WordStreamImpl::operator>>(std::string *str) {
+  const char *s = (const char *)&*mIter;
+  str->assign(s);
+  while (*mIter++ & 0xFF000000) {
+  }
+  return *this;
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/spirit/word_stream_impl.h b/rsov/compiler/spirit/word_stream_impl.h
new file mode 100644
index 0000000..365e3d5
--- /dev/null
+++ b/rsov/compiler/spirit/word_stream_impl.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WORD_STREAM_IMPL_H
+#define WORD_STREAM_IMPL_H
+
+#include "word_stream.h"
+
+#include <string>
+
+namespace android {
+namespace spirit {
+
+class WordStreamImpl : public WordStream {
+public:
+  WordStreamImpl();
+  WordStreamImpl(const std::vector<uint32_t> &words);
+  WordStreamImpl(std::vector<uint32_t> &&words);
+
+  bool empty() const override {
+    return mWords.empty() || mIter == mWords.end();
+  }
+
+  uint32_t operator*() { return *mIter; }
+
+  WordStreamImpl &operator>>(uint32_t *RHS) override {
+    *RHS = *mIter++;
+    return *this;
+  }
+
+  WordStreamImpl &operator>>(LiteralContextDependentNumber *RHS) override {
+    // TODO: check context in the instruction class to decide the actual size.
+    return *this >> (uint32_t *)(&RHS->intValue);
+  }
+
+  WordStreamImpl &operator>>(std::string *str) override;
+
+  std::vector<uint32_t> getWords() override { return mWords; }
+
+  WordStreamImpl &operator<<(const uint32_t RHS) override {
+    mWords.push_back(RHS);
+    return *this;
+  }
+
+  WordStreamImpl &
+  operator<<(const LiteralContextDependentNumber &RHS) override {
+    // TODO: check context in the instruction class to decide the actual size.
+    // TODO: maybe a word stream class should never take a context dependent
+    // type as argument. Always take concrete types such as int32, int64, float,
+    // double, etc.
+    return *this << (uint32_t)(RHS.intValue);
+  }
+  WordStreamImpl &operator<<(const std::string &str) override;
+
+private:
+  std::vector<uint32_t> mWords;
+  std::vector<uint32_t>::const_iterator mIter;
+};
+
+} // namespace spirit
+} // namespace android
+
+#endif // WORD_STREAM_IMPL_H
diff --git a/rsov/compiler/spirit/word_stream_test.cpp b/rsov/compiler/spirit/word_stream_test.cpp
new file mode 100644
index 0000000..2735e15
--- /dev/null
+++ b/rsov/compiler/spirit/word_stream_test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "word_stream.h"
+
+#include "gtest/gtest.h"
+
+#include <vector>
+
+namespace android {
+namespace spirit {
+
+TEST(WordStreamTest, testStringOutput1) {
+  std::unique_ptr<OutputWordStream> OS(OutputWordStream::Create());
+  *OS << "ABCDEFG";
+  auto words = OS->getWords();
+  const std::vector<uint8_t> bytes((uint8_t *)words.data(),
+                                   (uint8_t *)(words.data() + words.size()));
+  const std::vector<uint8_t> bytesExpected = {0x41, 0x42, 0x43, 0x44,
+                                              0x45, 0x46, 0x47, 0x00};
+  EXPECT_EQ(bytesExpected, bytes);
+}
+
+TEST(WordStreamTest, testStringOutput2) {
+  std::unique_ptr<OutputWordStream> OS(OutputWordStream::Create());
+  *OS << "GLSL.std.450";
+  auto words = OS->getWords();
+  const std::vector<uint8_t> bytes((uint8_t *)words.data(),
+                                   (uint8_t *)(words.data() + words.size()));
+  const std::vector<uint8_t> bytesExpected = {
+      0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64,
+      0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00};
+  EXPECT_EQ(bytesExpected, bytes);
+}
+
+TEST(WordStreamTest, testStringInput1) {
+  uint8_t bytes[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x00};
+  std::vector<uint32_t> words((uint32_t *)bytes,
+                              (uint32_t *)(bytes + sizeof(bytes)));
+  std::unique_ptr<InputWordStream> IS(InputWordStream::Create(words));
+  std::string s;
+  *IS >> &s;
+  EXPECT_STREQ("ABCDEFG", s.c_str());
+}
+
+TEST(WordStreamTest, testStringInput2) {
+  uint8_t bytes[] = {0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64,
+                     0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00};
+  std::vector<uint32_t> words((uint32_t *)bytes,
+                              (uint32_t *)(bytes + sizeof(bytes)));
+  std::unique_ptr<InputWordStream> IS(InputWordStream::Create(words));
+  std::string s;
+  *IS >> &s;
+  EXPECT_STREQ("GLSL.std.450", s.c_str());
+}
+
+} // namespace spirit
+} // namespace android
diff --git a/rsov/compiler/tests/arguments/foreach_multi_simple.ll b/rsov/compiler/tests/arguments/foreach_multi_simple.ll
new file mode 100644
index 0000000..ee6284e
--- /dev/null
+++ b/rsov/compiler/tests/arguments/foreach_multi_simple.ll
@@ -0,0 +1,46 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+; Decorations
+; CHECK: OpDecorate %[[BUF_0S:.*]] BufferBlock
+; CHECK: OpDecorate %[[BUF_VAR0:.*]] Binding 3
+; CHECK: OpDecorate %[[BUF_1S:.*]] BufferBlock
+; CHECK: OpDecorate %[[BUF_VAR1:.*]] Binding 4
+
+; CHECK:%[[BUF_PTR_TY0:.*]] = OpTypePointer Uniform %[[BUF_0S]]
+; CHECK:%[[BUF_VAR0]] = OpVariable %[[BUF_PTR_TY0]] Uniform
+; CHECK:%[[BUF_PTR_TY1:.*]] = OpTypePointer Uniform %[[BUF_1S]]
+; CHECK:%[[BUF_VAR1]] = OpVariable %[[BUF_PTR_TY1]] Uniform
+
+; Wrapper
+; CHECK: %[[ADDR0:.*]] = OpAccessChain %{{.*}} %[[BUF_VAR0]]
+; CHECK:OpLoad {{.*}} %[[ADDR0]]
+; CHECK: %[[ADDR1:.*]] = OpAccessChain %{{.*}} %[[BUF_VAR1]]
+; CHECK:OpLoad {{.*}} %[[ADDR1]]
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; Function Attrs: norecurse nounwind readnone
+define float @sum2(float %in0, float %in1, i32 %x) local_unnamed_addr #0 {
+entry:
+  %add = fadd float %in0, %in1
+  ret float %add
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_foreach_name = !{!5, !6}
+!\23rs_export_foreach = !{!7, !8}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"com.android.rs.rsov.test"}
+!5 = !{!"root"}
+!6 = !{!"sum2"}
+!7 = !{!"0"}
+!8 = !{!"43"}
diff --git a/rsov/compiler/tests/arguments/signedness.ll b/rsov/compiler/tests/arguments/signedness.ll
new file mode 100644
index 0000000..c173114
--- /dev/null
+++ b/rsov/compiler/tests/arguments/signedness.ll
@@ -0,0 +1,130 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+; CHECK: OpDecorate [[InVar1:%.*]] Binding 3
+; CHECK: OpDecorate [[OutVar1:%.*]] Binding 2
+
+; CHECK: OpDecorate [[InVar2:%.*]] Binding 3
+; CHECK: OpDecorate [[OutVar2:%.*]] Binding 2
+
+; CHECK: OpDecorate [[InVar3:%.*]] Binding 3
+; CHECK: OpDecorate [[OutVar3:%.*]] Binding 2
+
+; CHECK: OpDecorate [[InVar4:%.*]] Binding 3
+; CHECK: OpDecorate [[OutVar4:%.*]] Binding 2
+
+; CHECK: [[MemberTy1:%.*]] = OpTypeRuntimeArray %v4uint
+; CHECK: [[Struct1:%.*]] = OpTypeStruct [[MemberTy1]]
+; CHECK: [[PtrTy1:%.*]] = OpTypePointer Uniform [[Struct1]]
+; CHECK: [[InVar1]] = OpVariable [[PtrTy1]]
+
+; CHECK: [[OutMemberTy1:%.*]] = OpTypeRuntimeArray %v4uint
+; CHECK: [[OutStruct1:%.*]] = OpTypeStruct [[OutMemberTy1]]
+; CHECK: [[OutPtrTy1:%.*]] = OpTypePointer Uniform [[OutStruct1]]
+; CHECK: [[OutVar1]] = OpVariable [[OutPtrTy1]]
+
+; CHECK: [[MemberTy2:%.*]] = OpTypeRuntimeArray %v4uint
+; CHECK: [[Struct2:%.*]] = OpTypeStruct [[MemberTy2]]
+; CHECK: [[PtrTy2:%.*]] = OpTypePointer Uniform [[Struct2]]
+; CHECK: [[InVar2]] = OpVariable [[PtrTy2]]
+
+; CHECK: [[OutMemberTy2:%.*]] = OpTypeRuntimeArray %v4uint
+; CHECK: [[OutStruct2:%.*]] = OpTypeStruct [[OutMemberTy2]]
+; CHECK: [[OutPtrTy2:%.*]] = OpTypePointer Uniform [[OutStruct2]]
+; CHECK: [[OutVar2]] = OpVariable [[OutPtrTy2]]
+
+; CHECK: [[MemberTy3:%.*]] = OpTypeRuntimeArray %uint
+; CHECK: [[Struct3:%.*]] = OpTypeStruct [[MemberTy3]]
+; CHECK: [[PtrTy3:%.*]] = OpTypePointer Uniform [[Struct3]]
+; CHECK: [[InVar3]] = OpVariable [[PtrTy3]]
+
+; CHECK: [[OutMemberTy3:%.*]] = OpTypeRuntimeArray %uint
+; CHECK: [[OutStruct3:%.*]] = OpTypeStruct [[OutMemberTy3]]
+; CHECK: [[OutPtrTy3:%.*]] = OpTypePointer Uniform [[OutStruct3]]
+; CHECK: [[OutVar3]] = OpVariable [[OutPtrTy3]]
+
+; CHECK: [[MemberTy4:%.*]] = OpTypeRuntimeArray %uint
+; CHECK: [[Struct4:%.*]] = OpTypeStruct [[MemberTy4]]
+; CHECK: [[PtrTy4:%.*]] = OpTypePointer Uniform [[Struct4]]
+; CHECK: [[InVar4]] = OpVariable [[PtrTy4]]
+
+; CHECK: [[OutMemberTy4:%.*]] = OpTypeRuntimeArray %uint
+; CHECK: [[OutStruct4:%.*]] = OpTypeStruct [[OutMemberTy4]]
+; CHECK: [[OutPtrTy4:%.*]] = OpTypePointer Uniform [[OutStruct4]]
+; CHECK: [[OutVar4]] = OpVariable [[OutPtrTy4]]
+
+; // the RS the .rs from which this .ll is generated
+; #pragma version(1)
+; #pragma rs java_package_name(com.android.rs.test)
+
+; int4 RS_KERNEL increment4(int4 in)
+; {
+;     return in + 1;
+; }
+
+; uint4 RS_KERNEL uincrement4(uint4 in)
+; {
+;     return in + 1;
+; }
+
+; int RS_KERNEL increment(int in)
+; {
+;     return in + 1;
+; }
+
+; unsigned RS_KERNEL uincrement(unsigned in)
+; {
+;     return in + 1;
+; }
+
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; Function Attrs: norecurse nounwind readnone
+define <4 x i32> @increment4(<4 x i32> %in) local_unnamed_addr #0 {
+entry:
+  %add = add <4 x i32> %in, <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x i32> %add
+}
+
+; Function Attrs: norecurse nounwind readnone
+define <4 x i32> @uincrement4(<4 x i32> %in) local_unnamed_addr #0 {
+entry:
+  %add = add <4 x i32> %in, <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x i32> %add
+}
+
+; Function Attrs: norecurse nounwind readnone
+define i32 @increment(i32 %in) local_unnamed_addr #0 {
+entry:
+  %add = add nsw i32 %in, 1
+  ret i32 %add
+}
+
+; Function Attrs: norecurse nounwind readnone
+define i32 @uincrement(i32 %in) local_unnamed_addr #0 {
+entry:
+  %add = add i32 %in, 1
+  ret i32 %add
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_foreach_name = !{!5, !6, !7, !8, !9}
+!\23rs_export_foreach = !{!10, !11, !11, !11, !11}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"com.android.rs.test"}
+!5 = !{!"root"}
+!6 = !{!"increment4"}
+!7 = !{!"uincrement4"}
+!8 = !{!"increment"}
+!9 = !{!"uincrement"}
+!10 = !{!"0"}
+!11 = !{!"35"}
diff --git a/rsov/compiler/tests/errors/unsupported_type.rs b/rsov/compiler/tests/errors/unsupported_type.rs
new file mode 100644
index 0000000..a5af55d
--- /dev/null
+++ b/rsov/compiler/tests/errors/unsupported_type.rs
@@ -0,0 +1,6 @@
+#pragma version(1)
+#pragma rs java_package_name(identity)
+
+#define TYPE short
+
+TYPE RS_KERNEL tSet(TYPE v) { return v; }
diff --git a/rsov/compiler/tests/globals/mul.ll b/rsov/compiler/tests/globals/mul.ll
new file mode 100644
index 0000000..e0710fb
--- /dev/null
+++ b/rsov/compiler/tests/globals/mul.ll
@@ -0,0 +1,52 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpString ".rsov.ExportedVars:0;"
+
+; CHECK-DAG: OpDecorate [[GPUBlockVar:%[a-zA-Z_0-9]+]] Binding 0
+; CHECK-DAG: OpDecorate [[STRUCT:%struct__.*]] BufferBlock
+; CHECK-DAG: OpMemberDecorate [[STRUCT]] 0 Offset 0
+
+; CHECK: [[STRUCT]] = OpTypeStruct %float
+; CHECK: [[STRUCT_PTR_TY:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform [[STRUCT]]
+
+; CHECK: [[GPUBlockVar]] = OpVariable [[STRUCT_PTR_TY]] Uniform
+
+@c1 = common global float 0.000000e+00, align 4
+
+; Function Attrs: norecurse nounwind readonly
+define <4 x float> @k1(<4 x float> %in) #0 {
+entry:
+  %0 = load float, float* @c1, align 4, !tbaa !11
+  %splat.splatinsert = insertelement <4 x float> undef, float %0, i32 0
+  %splat.splat = shufflevector <4 x float> %splat.splatinsert, <4 x float> undef, <4 x i32> zeroinitializer
+  %mul = fmul <4 x float> %splat.splat, %in
+  ret <4 x float> %mul
+}
+
+attributes #0 = { norecurse nounwind readonly "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6}
+!\23rs_object_slots = !{}
+!\23rs_export_foreach_name = !{!7, !8}
+!\23rs_export_foreach = !{!9, !10}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"1"}
+!7 = !{!"root"}
+!8 = !{!"k1"}
+!9 = !{!"0"}
+!10 = !{!"35"}
+!11 = !{!12, !12, i64 0}
+!12 = !{!"float", !13, i64 0}
+!13 = !{!"omnipotent char", !14, i64 0}
+!14 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/globals/mul.rs b/rsov/compiler/tests/globals/mul.rs
new file mode 100644
index 0000000..77c5c52
--- /dev/null
+++ b/rsov/compiler/tests/globals/mul.rs
@@ -0,0 +1,23 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+float c1;
+
+float4 __attribute__((kernel)) k1(float4 in) {
+  return c1 * in;
+}
diff --git a/rsov/compiler/tests/globals/mul2.ll b/rsov/compiler/tests/globals/mul2.ll
new file mode 100644
index 0000000..ee47542
--- /dev/null
+++ b/rsov/compiler/tests/globals/mul2.ll
@@ -0,0 +1,64 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpString ".rsov.ExportedVars:0;24;8;28;"
+
+; CHECK-DAG: OpDecorate [[GPUBlockVar:%[a-zA-Z_0-9]+]] Binding 0
+; CHECK-DAG: OpDecorate [[STRUCT:%struct__.*]] BufferBlock
+; CHECK-DAG: OpMemberDecorate [[STRUCT]] 0 Offset 0
+; CHECK-DAG: OpMemberDecorate [[STRUCT]] 1 Offset 8
+; CHECK-DAG: OpMemberDecorate [[STRUCT]] 2 Offset 24
+; CHECK-DAG: OpMemberDecorate [[STRUCT]] 3 Offset 28
+
+; CHECK: [[STRUCT]] = OpTypeStruct %float %v4float %uchar %uint{{.*}}
+; CHECK: [[STRUCT_PTR_TY:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform [[STRUCT]]
+
+; CHECK: [[GPUBlockVar]] = OpVariable [[STRUCT_PTR_TY]] Uniform
+
+@c1 = common global float 0.000000e+00, align 4
+@c2 = common global <4 x float> zeroinitializer, align 16
+@d = common global i8 0, align 1
+@i = common global i32 0, align 4
+
+; Function Attrs: norecurse nounwind readonly
+define <4 x float> @k1(<4 x float> %in) #0 {
+entry:
+  %0 = load float, float* @c1, align 4, !tbaa !14
+  %splat.splatinsert = insertelement <4 x float> undef, float %0, i32 0
+  %splat.splat = shufflevector <4 x float> %splat.splatinsert, <4 x float> undef, <4 x i32> zeroinitializer
+  %mul = fmul <4 x float> %splat.splat, %in
+  %1 = load <4 x float>, <4 x float>* @c2, align 16, !tbaa !18
+  %mul1 = fmul <4 x float> %1, %mul
+  ret <4 x float> %mul1
+}
+
+attributes #0 = { norecurse nounwind readonly "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6, !7, !8, !9}
+!\23rs_object_slots = !{}
+!\23rs_export_foreach_name = !{!10, !11}
+!\23rs_export_foreach = !{!12, !13}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"1"}
+!7 = !{!"d", !"7"}
+!8 = !{!"c2", !"float4"}
+!9 = !{!"i", !"5"}
+!10 = !{!"root"}
+!11 = !{!"k1"}
+!12 = !{!"0"}
+!13 = !{!"35"}
+!14 = !{!15, !15, i64 0}
+!15 = !{!"float", !16, i64 0}
+!16 = !{!"omnipotent char", !17, i64 0}
+!17 = !{!"Simple C/C++ TBAA"}
+!18 = !{!16, !16, i64 0}
diff --git a/rsov/compiler/tests/globals/mul2.rs b/rsov/compiler/tests/globals/mul2.rs
new file mode 100644
index 0000000..78e67ac
--- /dev/null
+++ b/rsov/compiler/tests/globals/mul2.rs
@@ -0,0 +1,26 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+float c1;
+uchar d;
+float4 c2;
+int i;
+
+float4 __attribute__((kernel)) k1(float4 in) {
+  return c1 * in * c2;
+}
diff --git a/rsov/compiler/tests/image/blend.ll b/rsov/compiler/tests/image/blend.ll
new file mode 100644
index 0000000..1788845
--- /dev/null
+++ b/rsov/compiler/tests/image/blend.ll
@@ -0,0 +1,62 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute [[WrapperId:%[a-zA-Z_0-9]*]] "entry_setImageAlpha"
+
+; CHECK-NOT: OpFunctionCall %v4uchar %__Z14convert_uchar4Dv4_j
+; CHECK-NOT: OpFunctionCall %v4uint %__Z13convert_uint4Dv4_h
+
+; CHECK: OpUConvert %v4uint
+; CHECK: OpUConvert %v4uchar
+
+@alpha = global i8 0, align 1
+
+; Function Attrs: nounwind readonly
+define <4 x i8> @setImageAlpha(<4 x i8> %in, i32 %x, i32 %y) #0 {
+entry:
+  %call = tail call <4 x i32> @_Z13convert_uint4Dv4_h(<4 x i8> %in) #2
+  %0 = load i8, i8* @alpha, align 1, !tbaa !11
+  %conv = zext i8 %0 to i32
+  %splat.splatinsert = insertelement <4 x i32> undef, i32 %conv, i32 0
+  %splat.splat = shufflevector <4 x i32> %splat.splatinsert, <4 x i32> undef, <4 x i32> zeroinitializer
+  %mul = mul <4 x i32> %splat.splat, %call
+  %shr = lshr <4 x i32> %mul, <i32 8, i32 8, i32 8, i32 8>
+  %call1 = tail call <4 x i8> @_Z14convert_uchar4Dv4_j(<4 x i32> %shr) #2
+  %1 = insertelement <4 x i8> %call1, i8 %0, i32 3
+  ret <4 x i8> %1
+}
+
+; Function Attrs: nounwind readnone
+declare <4 x i8> @_Z14convert_uchar4Dv4_j(<4 x i32>) #1
+
+; Function Attrs: nounwind readnone
+declare <4 x i32> @_Z13convert_uint4Dv4_h(<4 x i8>) #1
+
+attributes #0 = { nounwind readonly "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readnone }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6}
+!\23rs_object_slots = !{}
+!\23rs_export_foreach_name = !{!7, !8}
+!\23rs_export_foreach = !{!9, !10}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"alpha", !"7"}
+!7 = !{!"root"}
+!8 = !{!"setImageAlpha"}
+!9 = !{!"0"}
+!10 = !{!"59"}
+!11 = !{!12, !12, i64 0}
+!12 = !{!"omnipotent char", !13, i64 0}
+!13 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/image/blend.rs b/rsov/compiler/tests/image/blend.rs
new file mode 100644
index 0000000..ea1d323
--- /dev/null
+++ b/rsov/compiler/tests/image/blend.rs
@@ -0,0 +1,26 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar alpha = 0x0;
+
+uchar4 __attribute__((kernel)) setImageAlpha(uchar4 in, uint32_t x, uint32_t y) {
+    uchar4 out;
+    out.rgba = convert_uchar4((convert_uint4(in.rgba) * alpha) >> (uint4)8);
+    out.a = alpha;
+    return out;
+}
diff --git a/rsov/compiler/tests/image/contrast.ll b/rsov/compiler/tests/image/contrast.ll
new file mode 100644
index 0000000..77cee16
--- /dev/null
+++ b/rsov/compiler/tests/image/contrast.ll
@@ -0,0 +1,101 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: [[GLSL_EXT_INS:%.*]] = OpExtInstImport "GLSL.std.450"
+; CHECK: OpEntryPoint GLCompute [[WrapperId:%[a-zA-Z_0-9]*]] "entry_contrast"
+
+; CHECK-NOT: OpFunctionCall %v3float %_Z14convert_float3Dv3_h
+; CHECK-NOT: OpFunctionCall %v3float %_Z5clampDv3_fff
+; CHECK-NOT: OpFunctionCall %v3uchar %_Z14convert_uchar3Dv3_f
+
+; CHECK: OpConvertUToF %v3float
+; CHECK: OpExtInst %v3float [[GLSL_EXT_INS]] FClamp
+; CHECK: OpConvertFToU %v3uchar
+
+
+@brightM = internal unnamed_addr global float 0.000000e+00, align 4
+@brightC = internal unnamed_addr global float 0.000000e+00, align 4
+
+; Function Attrs: nounwind
+define void @setBright(float %v) #0 {
+entry:
+  %div = fdiv float %v, 1.000000e+02
+  %call = tail call float @_Z3powff(float 2.000000e+00, float %div) #4
+  store float %call, float* @brightM, align 4, !tbaa !11
+  %mul = fmul float %call, 1.270000e+02
+  %sub = fsub float 1.270000e+02, %mul
+  store float %sub, float* @brightC, align 4, !tbaa !11
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @_Z3powff(float, float) #1
+
+; Function Attrs: nounwind readonly
+define <4 x i8> @contrast(<4 x i8> %in) #2 {
+entry:
+  %0 = shufflevector <4 x i8> %in, <4 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+  %call = tail call <3 x float> @_Z14convert_float3Dv3_h(<3 x i8> %0) #4
+  %1 = load float, float* @brightM, align 4, !tbaa !11
+  %splat.splatinsert = insertelement <3 x float> undef, float %1, i32 0
+  %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> undef, <3 x i32> zeroinitializer
+  %mul = fmul <3 x float> %call, %splat.splat
+  %2 = load float, float* @brightC, align 4, !tbaa !11
+  %splat.splatinsert1 = insertelement <3 x float> undef, float %2, i32 0
+  %splat.splat2 = shufflevector <3 x float> %splat.splatinsert1, <3 x float> undef, <3 x i32> zeroinitializer
+  %add = fadd <3 x float> %mul, %splat.splat2
+  %call4 = tail call <3 x float> @_Z5clampDv3_fff(<3 x float> %add, float 0.000000e+00, float 2.550000e+02) #4
+  %call5 = tail call <3 x i8> @_Z14convert_uchar3Dv3_f(<3 x float> %call4) #4
+  %3 = shufflevector <3 x i8> %call5, <3 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
+  %4 = insertelement <4 x i8> %3, i8 -1, i32 3
+  ret <4 x i8> %4
+}
+
+; Function Attrs: nounwind readnone
+declare <3 x float> @_Z14convert_float3Dv3_h(<3 x i8>) #1
+
+; Function Attrs: nounwind readnone
+declare <3 x i8> @_Z14convert_uchar3Dv3_f(<3 x float>) #1
+
+; Function Attrs: nounwind readnone
+declare <3 x float> @_Z5clampDv3_fff(<3 x float>, float, float) #1
+
+; Function Attrs: noinline nounwind
+define void @.helper_setBright({ float }* nocapture) #3 {
+entry:
+  %1 = getelementptr inbounds { float }, { float }* %0, i32 0, i32 0
+  %2 = load float, float* %1, align 4
+  tail call void @setBright(float %2)
+  ret void
+}
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readonly "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { noinline nounwind }
+attributes #4 = { nounwind readnone }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_func = !{!6}
+!\23rs_export_foreach_name = !{!7, !8}
+!\23rs_export_foreach = !{!9, !10}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!".helper_setBright"}
+!7 = !{!"root"}
+!8 = !{!"contrast"}
+!9 = !{!"0"}
+!10 = !{!"35"}
+!11 = !{!12, !12, i64 0}
+!12 = !{!"float", !13, i64 0}
+!13 = !{!"omnipotent char", !14, i64 0}
+!14 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/image/contrast.rs b/rsov/compiler/tests/image/contrast.rs
new file mode 100644
index 0000000..dd95ad3
--- /dev/null
+++ b/rsov/compiler/tests/image/contrast.rs
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+static float brightM = 0.f;
+static float brightC = 0.f;
+
+void setBright(float v) {
+    brightM = pow(2.f, v / 100.f);
+    brightC = 127.f - brightM * 127.f;
+}
+
+uchar4 __attribute__((kernel)) contrast(uchar4 in) {
+    float3 v = convert_float3(in.rgb) * brightM + brightC;
+    uchar4 o;
+    o.rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+    o.a = 0xff;
+    return o;
+}
\ No newline at end of file
diff --git a/rsov/compiler/tests/image/copy.ll b/rsov/compiler/tests/image/copy.ll
new file mode 100644
index 0000000..62617c9
--- /dev/null
+++ b/rsov/compiler/tests/image/copy.ll
@@ -0,0 +1,37 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute [[WrapperId:%[a-zA-Z_0-9]*]] "entry_copy"
+; CHECK: [[KernelId:%[a-zA-Z_0-9]+]] = OpFunction {{.*}}
+
+; Function Attrs: norecurse nounwind readnone
+define <4 x i8> @copy(<4 x i8> %v_in) #0 {
+entry:
+  ret <4 x i8> %v_in
+}
+
+; CHECK: [[WrapperId]] = OpFunction {{.*}}
+; CHECK-NEXT: OpLabel
+; CHECK: %{{[0-9]+}} = OpFunctionCall %{{.*}} [[KernelId]]
+; CHECK: OpReturn
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_foreach_name = !{!6, !7}
+!\23rs_export_foreach = !{!8, !9}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"root"}
+!7 = !{!"copy"}
+!8 = !{!"0"}
+!9 = !{!"35"}
diff --git a/rsov/compiler/tests/image/copy.rs b/rsov/compiler/tests/image/copy.rs
new file mode 100644
index 0000000..1f3ae2e
--- /dev/null
+++ b/rsov/compiler/tests/image/copy.rs
@@ -0,0 +1,7 @@
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar4 __attribute__((kernel)) copy(uchar4 v_in) {
+    return v_in;
+}
diff --git a/rsov/compiler/tests/lit.cfg b/rsov/compiler/tests/lit.cfg
new file mode 100644
index 0000000..66ef028
--- /dev/null
+++ b/rsov/compiler/tests/lit.cfg
@@ -0,0 +1,29 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import re
+
+# name: The name of this test suite.
+config.name = 'rs2spirv'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.ll']
+
+# testFormat: The test format to use to interpret tests.
+import lit.formats
+config.test_format = lit.formats.ShTest()
+
+ANDROID_HOST_OUT = os.getenv("ANDROID_HOST_OUT")
+
+if not ANDROID_HOST_OUT:
+    import sys
+    sys.exit(1)
+
+# test_source_root: The path where tests are located (default is the test suite
+# root).
+config.test_source_root = None
+# test_exec_root: The root path where tests should be run.
+config.test_exec_root = os.path.join(ANDROID_HOST_OUT, 'tests', 'rs2spirv')
+
+tools_dir = os.pathsep.join([os.path.join(ANDROID_HOST_OUT, 'bin'),])
diff --git a/rsov/compiler/tests/llvm-lit b/rsov/compiler/tests/llvm-lit
new file mode 100755
index 0000000..cc6f58e
--- /dev/null
+++ b/rsov/compiler/tests/llvm-lit
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+# In the Android tree, use the environment variables set by envsetup.sh
+# to determine correct path for the root of the source tree.
+# TODO: To run clang tests, @LLVM_BINARY_DIR@ must be substituted also.
+android_source_root = os.getenv('ANDROID_BUILD_TOP', ".")
+llvm_source_root = os.path.join(android_source_root, 'external', 'llvm')
+
+# Make sure we can find the lit package.
+sys.path.append(os.path.join(llvm_source_root, 'utils', 'lit'))
+
+# Set up some builtin parameters, so that by default the LLVM test suite
+# configuration file knows how to find the object tree.
+builtin_parameters = {
+    'llvm_site_config' : os.path.join('./', 'lit.site.cfg')
+}
+
+if __name__=='__main__':
+    import lit
+    lit.main(builtin_parameters)
diff --git a/rsov/compiler/tests/multi_function/blend_mf.ll b/rsov/compiler/tests/multi_function/blend_mf.ll
new file mode 100644
index 0000000..650d661
--- /dev/null
+++ b/rsov/compiler/tests/multi_function/blend_mf.ll
@@ -0,0 +1,68 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute %[[WrapperId:[a-zA-Z_0-9]*]] "entry_setImageAlpha"
+
+; Function Attrs: norecurse nounwind readnone
+define void @NOP() #0 {
+entry:
+  ret void
+}
+
+; CHECK: [[KernelId:%[a-zA-Z_0-9]+]] = OpFunction {{.*}}
+
+; Function calls to _Z14convert_uchar4Dv4_j should be translated into OpUConvert instructions
+; CHECK-NOT: OpFunctionCall %v4uchar %_Z14convert_uchar4Dv4_j
+; CHECK-NOT: OpFunctionCall %v4uint %_Z13convert_uint4Dv4_h
+; CHECK: OpUConvert %v4uint
+; CHECK: OpUConvert %v4uchar
+
+; Function Attrs: nounwind readnone
+define <4 x i8> @setImageAlpha(<4 x i8> %in) #1 {
+entry:
+  %call = tail call <4 x i32> @_Z13convert_uint4Dv4_h(<4 x i8> %in) #2
+  %mul = mul <4 x i32> %call, <i32 37, i32 37, i32 37, i32 37>
+  %shr = lshr <4 x i32> %mul, <i32 8, i32 8, i32 8, i32 8>
+  %call1 = tail call <4 x i8> @_Z14convert_uchar4Dv4_j(<4 x i32> %shr) #2
+  %call2 = tail call fastcc <4 x i8> @twice(<4 x i8> %call1)
+  %0 = insertelement <4 x i8> %call2, i8 37, i32 3
+  ret <4 x i8> %0
+}
+
+; Function Attrs: norecurse nounwind readnone
+define internal fastcc <4 x i8> @twice(<4 x i8> %in) #0 {
+entry:
+  %mul = shl <4 x i8> %in, <i8 1, i8 1, i8 1, i8 1>
+  ret <4 x i8> %mul
+}
+
+; Function Attrs: nounwind readnone
+declare <4 x i8> @_Z14convert_uchar4Dv4_j(<4 x i32>) #1
+
+; Function Attrs: nounwind readnone
+declare <4 x i32> @_Z13convert_uint4Dv4_h(<4 x i8>) #1
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readnone }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_func = !{!6}
+!\23rs_export_foreach_name = !{!7, !8}
+!\23rs_export_foreach = !{!9, !10}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"NOP"}
+!7 = !{!"root"}
+!8 = !{!"setImageAlpha"}
+!9 = !{!"0"}
+!10 = !{!"35"}
diff --git a/rsov/compiler/tests/multi_function/blend_mf.rs b/rsov/compiler/tests/multi_function/blend_mf.rs
new file mode 100644
index 0000000..1769208
--- /dev/null
+++ b/rsov/compiler/tests/multi_function/blend_mf.rs
@@ -0,0 +1,38 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+static uchar4 twice(uchar4 in) {
+  return in * 2;
+}
+
+static uchar getConstant() {
+  return 37;
+}
+
+void NOP() {
+  uchar3 x = {1, 2, 3};
+  (void) convert_float3(x);
+}
+
+uchar4 __attribute__((kernel)) setImageAlpha(uchar4 in) {
+  uchar4 out;
+  out.rgba = twice(convert_uchar4((convert_uint4(in.rgba) * 37) >> (uint4)8));
+  out.a = getConstant();
+  NOP();
+  return out;
+}
diff --git a/rsov/compiler/tests/multi_kernel/invert.ll b/rsov/compiler/tests/multi_kernel/invert.ll
new file mode 100644
index 0000000..4f0bae7
--- /dev/null
+++ b/rsov/compiler/tests/multi_kernel/invert.ll
@@ -0,0 +1,52 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute [[FuncId1:%[0-9]+]] "entry_invert" %gl_GlobalInvocationID
+; CHECK-NEXT: OpEntryPoint GLCompute [[FuncId2:%[0-9]+]] "entry_scalebytwo" %gl_GlobalInvocationID
+
+; Multi-kernel testcase
+;float4 RS_KERNEL invert(float4 a) {
+;    return 1.0f - a;
+;}
+
+; CHECK: [[FuncId1]] = OpFunction %void None
+; Function Attrs: norecurse nounwind readnone
+define <4 x float> @invert(<4 x float> %a) local_unnamed_addr #0 {
+entry:
+  %sub = fsub <4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>, %a
+  ret <4 x float> %sub
+}
+
+
+; CHECK: [[FuncId2]] = OpFunction %void None
+;float RS_KERNEL scalebytwo(float a) {
+;    return a*2;
+;}
+
+; Function Attrs: norecurse nounwind readnone
+define float @scalebytwo(float %a) local_unnamed_addr #0 {
+entry:
+  %mul = fmul float %a, 2.000000e+00
+  ret float %mul
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_foreach_name = !{!5, !6, !7}
+!\23rs_export_foreach = !{!8, !9, !9}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"com.android.rs.rsov.test"}
+!5 = !{!"root"}
+!6 = !{!"invert"}
+!7 = !{!"scalebytwo"}
+!8 = !{!"0"}
+!9 = !{!"35"}
diff --git a/rsov/compiler/tests/rs2spirv_lit_driver.sh b/rsov/compiler/tests/rs2spirv_lit_driver.sh
new file mode 100755
index 0000000..afd6ff3
--- /dev/null
+++ b/rsov/compiler/tests/rs2spirv_lit_driver.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Copyright 2016, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# TODO: Consider rewriting as a native binary instead of shell script.
+
+if [ $# -lt 1 ]; then
+  echo 1>&2 "$0: not enough arguments"
+  echo 1>&2 $#
+  exit 2
+fi
+
+script_path="$1"
+script_name=$(basename $script_path)
+script=${script_name%.*} # Remove extension.
+
+output_folder="driver_out"
+mkdir -p $output_folder
+
+eval llvm-as "$script_path" -o "$output_folder/$script.bc" &&
+eval rs2spirv "$output_folder/$script.bc" -o "$output_folder/$script.spv" &&
+eval spirv-val "$output_folder/$script.spv"
+
+if [ $? -ne 0 ]; then
+  echo 1>&2 "Generated SPIR-V failed validation"
+  exit -1
+fi
+
+eval spirv-dis --no-color "$output_folder/$script.spv"
+
+RET=$?
+
+#eval rm "$output_folder/$script.*"
+
+exit $RET
diff --git a/rsov/compiler/tests/rs_allocation/access_same.ll b/rsov/compiler/tests/rs_allocation/access_same.ll
new file mode 100644
index 0000000..34dd334
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/access_same.ll
@@ -0,0 +1,84 @@
+; XFAIL: *
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: %struct___GPUBuffer = OpTypeStruct %uchar
+; CHECK: [[PTR_TYPE:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform %struct___GPUBuffer
+
+; CHECK: %__GPUBlock = OpVariable [[PTR_TYPE]] Uniform
+
+%struct.rs_allocation = type { i32* }
+
+@a1 = common global %struct.rs_allocation zeroinitializer, align 4
+@c1 = common global i8 0, align 1
+
+; Function Attrs: nounwind
+define <4 x i8> @k1(<4 x i8> %in) #0 {
+entry:
+  %0 = extractelement <4 x i8> %in, i32 0
+  %conv = zext i8 %0 to i32
+  %1 = extractelement <4 x i8> %in, i32 1
+  %conv1 = zext i8 %1 to i32
+  %.unpack = load i32, i32* bitcast (%struct.rs_allocation* @a1 to i32*), align 4
+  %2 = insertvalue [1 x i32] undef, i32 %.unpack, 0
+  %call = tail call <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32] %2, i32 %conv, i32 %conv1) #2
+  %3 = extractelement <4 x i8> %in, i32 2
+  %conv2 = zext i8 %3 to i32
+  %4 = extractelement <4 x i8> %in, i32 3
+  %conv3 = zext i8 %4 to i32
+  %.unpack14 = load i32, i32* bitcast (%struct.rs_allocation* @a1 to i32*), align 4
+  %5 = insertvalue [1 x i32] undef, i32 %.unpack14, 0
+  tail call void @_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj([1 x i32] %5, <4 x i8> %call, i32 %conv2, i32 %conv3) #2
+  %6 = load i8, i8* @c1, align 1, !tbaa !13
+  %conv4 = zext i8 %6 to i32
+  %7 = extractelement <4 x i8> %call, i32 2
+  %conv5 = zext i8 %7 to i32
+  %add = add nuw nsw i32 %conv4, %conv5
+  %conv6 = trunc i32 %add to i8
+  %8 = insertelement <4 x i8> %call, i8 %conv6, i32 2
+  ret <4 x i8> %8
+}
+
+declare <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32], i32, i32) #1
+
+declare void @_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj([1 x i32], <4 x i8>, i32, i32) #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @a1) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6, !7}
+!\23rs_object_slots = !{!8}
+!\23rs_export_foreach_name = !{!9, !10}
+!\23rs_export_foreach = !{!11, !12}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"7"}
+!7 = !{!"a1", !"20"}
+!8 = !{!"1"}
+!9 = !{!"root"}
+!10 = !{!"k1"}
+!11 = !{!"0"}
+!12 = !{!"35"}
+!13 = !{!14, !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/rs_allocation/access_same.rs b/rsov/compiler/tests/rs_allocation/access_same.rs
new file mode 100644
index 0000000..7fce3bb
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/access_same.rs
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar c1;
+rs_allocation a1;
+
+uchar4 __attribute__((kernel)) k1(uchar4 in) {
+  uchar4 res = rsGetElementAt_uchar4(a1, in.r, in.g);
+  rsSetElementAt_uchar4(a1, res, in.b, in.a);
+  res.b += c1;
+  return res;
+}
+
diff --git a/rsov/compiler/tests/rs_allocation/copy_coords.ll b/rsov/compiler/tests/rs_allocation/copy_coords.ll
new file mode 100644
index 0000000..b29e288
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/copy_coords.ll
@@ -0,0 +1,37 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: [[InvocationID:%.*]] = OpLoad %v3uint %gl_GlobalInvocationID
+; CHECK: {{%.*}} = OpCompositeExtract %uint [[InvocationID]] 0
+; CHECK: {{%.*}} = OpCompositeExtract %uint [[InvocationID]] 1
+
+; Function Attrs: norecurse nounwind readnone
+define <4 x i8> @copy_coords(<4 x i8> %in, i32 %x, i32 %y) #0 {
+entry:
+  %conv = trunc i32 %x to i8
+  %0 = insertelement <4 x i8> %in, i8 %conv, i32 0
+  %conv1 = trunc i32 %y to i8
+  %1 = insertelement <4 x i8> %0, i8 %conv1, i32 1
+  ret <4 x i8> %1
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_foreach_name = !{!6, !7}
+!\23rs_export_foreach = !{!8, !9}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"root"}
+!7 = !{!"copy_coords"}
+!8 = !{!"0"}
+!9 = !{!"59"}
diff --git a/rsov/compiler/tests/rs_allocation/copy_coords.rs b/rsov/compiler/tests/rs_allocation/copy_coords.rs
new file mode 100644
index 0000000..2b36ee7
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/copy_coords.rs
@@ -0,0 +1,24 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar4 __attribute__((kernel)) copy_coords(uchar4 in, uint32_t x, uint32_t y) {
+  uchar4 res = in;
+  res.r = (uchar) x;
+  res.g = (uchar) y;
+  return res;
+}
diff --git a/rsov/compiler/tests/rs_allocation/getdimx.ll b/rsov/compiler/tests/rs_allocation/getdimx.ll
new file mode 100644
index 0000000..6fdeca8
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/getdimx.ll
@@ -0,0 +1,76 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+; rs_allocation g;
+; extern uint32_t __rsov_rsAllocationGetDimX(uint32_t ga);
+; int32_t RS_KERNEL getDim(int32_t dummy) {
+;    // lowered accessor by an earlier LLVM pass
+;    return __rsov_rsAllocationGetDimX(0);
+;}
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+%struct.rs_allocation = type { i32* }
+; CHECK-NOT OpCapability Kernel
+; CHECK-NOT OpDecorate %{{[a-zA-Z_0-9]*}} Alignment {{[0-9]*}}
+; CHECK: OpMemberDecorate [[MetadataS:%[a-zA-Z_0-9]*]] 0 Offset 4
+; CHECK: OpMemberDecorate [[MetadataS]] 1 Offset 8
+; CHECK: OpMemberDecorate [[MetadataS]] 2 Offset 12
+; CHECK: OpMemberDecorate [[MetadataS]] 3 Offset 16
+; CHECK: OpDecorate [[RuntimeArrS:%[a-zA-Z_0-9]*]] ArrayStride {{[0-9]*}}
+; CHECK: OpDecorate [[MetadataSSBO:%[a-zA-Z_0-9]*]] BufferBlock
+; CHECK: OpDecorate [[Metadata:%[a-zA-Z_0-9]*]] DescriptorSet 0
+; CHECK: OpDecorate [[Metadata]] Binding 1
+
+
+; CHECK: [[MetadataSSBO]] = OpTypeStruct [[RuntimeArrS]]
+; CHECK: [[MetadataPtr:%[a-zA-Z_0-9]*]] = OpTypePointer Uniform [[MetadataSSBO]]
+; CHECK: [[Metadata]] = OpVariable [[MetadataPtr]]
+
+@g = common global %struct.rs_allocation zeroinitializer, align 4
+
+
+; CHECK-NOT OpFunctionCall %uint %__rsov_rsAllocationGetDimX %{{[a-zA-Z_0-9]*}}
+; CHECK: [[DimX:%[a-zA-Z_0-9]*]] = OpAccessChain %_ptr_Uniform_uint [[Metadata]]
+; CHECK: [[Res:%[a-zA-Z_0-9]*]] = OpLoad %uint [[DimX]]
+; CHECK: OpReturnValue [[Res]]
+
+; Function Attrs: nounwind
+define i32 @getDim(i32 %dummy) local_unnamed_addr #0 {
+entry:
+  %call = tail call i32 @__rsov_rsAllocationGetDimX(i32 0) #2
+  ret i32 %call
+}
+
+declare i32 @__rsov_rsAllocationGetDimX(i32) local_unnamed_addr #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() local_unnamed_addr #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @g) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) local_unnamed_addr #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_var = !{!5}
+!\23rs_object_slots = !{!6}
+!\23rs_export_foreach_name = !{!7, !8}
+!\23rs_export_foreach = !{!6, !9}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"com.android.rs.rsov.test"}
+!5 = !{!"g", !"20"}
+!6 = !{!"0"}
+!7 = !{!"root"}
+!8 = !{!"getDim"}
+!9 = !{!"35"}
diff --git a/rsov/compiler/tests/rs_allocation/getdimx_64.ll b/rsov/compiler/tests/rs_allocation/getdimx_64.ll
new file mode 100644
index 0000000..c7792cb
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/getdimx_64.ll
@@ -0,0 +1,76 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+; Source:
+; rs_allocation g;
+; int32_t RS_KERNEL getDim(int32_t dummy) {
+;    return rsAllocationGetDimX(g);
+; }
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; CHECK: OpString "{\"__RSoV_GA\": {\"g\":0}}"
+; CHECK: OpMemberDecorate [[MetadataS:%[a-zA-Z_0-9]*]] 0 Offset 4
+; CHECK: OpMemberDecorate [[MetadataS]] 1 Offset 8
+; CHECK: OpMemberDecorate [[MetadataS]] 2 Offset 12
+; CHECK: OpMemberDecorate [[MetadataS]] 3 Offset 16
+; CHECK: OpDecorate [[RuntimeArrS:%[a-zA-Z_0-9]*]] ArrayStride {{[0-9]*}}
+; CHECK: OpDecorate [[MetadataSSBO:%[a-zA-Z_0-9]*]] BufferBlock
+; CHECK: OpDecorate [[Metadata:%[a-zA-Z_0-9]*]] DescriptorSet 0
+; CHECK: OpDecorate [[Metadata]] Binding 1
+
+%struct.rs_allocation.1 = type { i64*, i64*, i64*, i64* }
+
+@g = common global %struct.rs_allocation.1 zeroinitializer, align 8
+; CHECK-NOT: %g = OpVariable %{{.*}} Uniform
+; CHECK-NOT: OpCopyMemorySized
+; CHECK-NOT: OpFunctionCall %uint %__rsov_rsAllocationGetDimX
+; CHECK: [[DimX:%[a-zA-Z_0-9]*]] = OpAccessChain %_ptr_Uniform_uint [[Metadata]]
+; CHECK: [[Res:%[a-zA-Z_0-9]*]] = OpLoad %uint [[DimX]]
+; CHECK: OpReturnValue [[Res]]
+
+; Function Attrs: nounwind
+define i32 @getDim(i32 %dummy) unnamed_addr #0 {
+entry:
+  %tmp = alloca %struct.rs_allocation.1, align 8
+  %0 = bitcast %struct.rs_allocation.1* %tmp to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast (%struct.rs_allocation.1* @g to i8*), i64 32, i32 8, i1 false), !tbaa.struct !8
+  %call = call i32 @_Z19rsAllocationGetDimX13rs_allocation(%struct.rs_allocation.1* %tmp) #0
+  ret i32 %call
+}
+
+declare i32 @_Z19rsAllocationGetDimX13rs_allocation(%struct.rs_allocation.1*) unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() unnamed_addr #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation.1* @g) #0
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation.1*) unnamed_addr
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2}
+!\23rs_export_var = !{!3}
+!\23rs_object_slots = !{!4}
+!\23rs_export_foreach_name = !{!5, !6}
+!\23rs_export_foreach = !{!4, !7}
+
+!0 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"com.android.rs.rsov.test"}
+!3 = !{!"g", !"20"}
+!4 = !{!"0"}
+!5 = !{!"root"}
+!6 = !{!"getDim"}
+!7 = !{!"35"}
+!8 = !{i64 0, i64 8, !9, i64 8, i64 8, !9, i64 16, i64 8, !9, i64 24, i64 8, !9}
+!9 = !{!10, !10, i64 0}
+!10 = !{!"any pointer", !11, i64 0}
+!11 = !{!"omnipotent char", !12, i64 0}
+!12 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/rs_allocation/multi_read.ll b/rsov/compiler/tests/rs_allocation/multi_read.ll
new file mode 100644
index 0000000..3e960f5
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/multi_read.ll
@@ -0,0 +1,87 @@
+; XFAIL: *
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: %struct___GPUBuffer = OpTypeStruct %uchar
+; CHECK: [[PTR_TYPE:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform %struct___GPUBuffer
+
+; CHECK: %__GPUBlock = OpVariable [[PTR_TYPE]] Uniform
+
+%struct.rs_allocation = type { i32* }
+
+@a1 = common global %struct.rs_allocation zeroinitializer, align 4
+@a2 = common global %struct.rs_allocation zeroinitializer, align 4
+@c1 = common global i8 0, align 1
+
+; Function Attrs: nounwind
+define <4 x i8> @k1(<4 x i8> %in) #0 {
+entry:
+  %0 = extractelement <4 x i8> %in, i32 0
+  %conv = zext i8 %0 to i32
+  %1 = extractelement <4 x i8> %in, i32 1
+  %conv1 = zext i8 %1 to i32
+  %.unpack = load i32, i32* bitcast (%struct.rs_allocation* @a1 to i32*), align 4
+  %2 = insertvalue [1 x i32] undef, i32 %.unpack, 0
+  %call = tail call <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32] %2, i32 %conv, i32 %conv1) #2
+  %3 = extractelement <4 x i8> %in, i32 2
+  %conv2 = zext i8 %3 to i32
+  %4 = extractelement <4 x i8> %in, i32 3
+  %conv3 = zext i8 %4 to i32
+  %.unpack16 = load i32, i32* bitcast (%struct.rs_allocation* @a2 to i32*), align 4
+  %5 = insertvalue [1 x i32] undef, i32 %.unpack16, 0
+  %call4 = tail call <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32] %5, i32 %conv2, i32 %conv3) #2
+  %add = add <4 x i8> %call4, %call
+  %6 = load i8, i8* @c1, align 1, !tbaa !15
+  %conv5 = zext i8 %6 to i32
+  %7 = extractelement <4 x i8> %add, i32 2
+  %conv6 = zext i8 %7 to i32
+  %add7 = add nuw nsw i32 %conv6, %conv5
+  %conv8 = trunc i32 %add7 to i8
+  %8 = insertelement <4 x i8> %add, i8 %conv8, i32 2
+  ret <4 x i8> %8
+}
+
+declare <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32], i32, i32) #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @a1) #2
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @a2) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6, !7, !8}
+!\23rs_object_slots = !{!9, !10}
+!\23rs_export_foreach_name = !{!11, !12}
+!\23rs_export_foreach = !{!13, !14}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"7"}
+!7 = !{!"a1", !"20"}
+!8 = !{!"a2", !"20"}
+!9 = !{!"1"}
+!10 = !{!"2"}
+!11 = !{!"root"}
+!12 = !{!"k1"}
+!13 = !{!"0"}
+!14 = !{!"35"}
+!15 = !{!16, !16, i64 0}
+!16 = !{!"omnipotent char", !17, i64 0}
+!17 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/rs_allocation/multi_read.rs b/rsov/compiler/tests/rs_allocation/multi_read.rs
new file mode 100644
index 0000000..bebb0f9
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/multi_read.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar c1;
+rs_allocation a1;
+rs_allocation a2;
+
+uchar4 __attribute__((kernel)) k1(uchar4 in) {
+  uchar4 res = rsGetElementAt_uchar4(a1, in.r, in.g);
+  res += rsGetElementAt_uchar4(a2, in.b, in.a);
+  res.b += c1;
+  return res;
+}
+
diff --git a/rsov/compiler/tests/rs_allocation/read.ll b/rsov/compiler/tests/rs_allocation/read.ll
new file mode 100644
index 0000000..178fdf7
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/read.ll
@@ -0,0 +1,75 @@
+; XFAIL: *
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: %struct___GPUBuffer = OpTypeStruct %uchar
+; CHECK: [[PTR_TYPE:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform %struct___GPUBuffer
+
+; CHECK: %__GPUBlock = OpVariable [[PTR_TYPE]] Uniform
+
+%struct.rs_allocation = type { i32* }
+
+@alloc = common global %struct.rs_allocation zeroinitializer, align 4
+@c1 = common global i8 0, align 1
+
+; Function Attrs: nounwind
+define <4 x i8> @k1(<4 x i8> %in) #0 {
+entry:
+  %0 = extractelement <4 x i8> %in, i32 0
+  %conv = zext i8 %0 to i32
+  %1 = extractelement <4 x i8> %in, i32 1
+  %conv1 = zext i8 %1 to i32
+  %.unpack = load i32, i32* bitcast (%struct.rs_allocation* @alloc to i32*), align 4
+  %2 = insertvalue [1 x i32] undef, i32 %.unpack, 0
+  %call = tail call <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32] %2, i32 %conv, i32 %conv1) #2
+  %3 = load i8, i8* @c1, align 1, !tbaa !13
+  %conv2 = zext i8 %3 to i32
+  %4 = extractelement <4 x i8> %call, i32 2
+  %conv3 = zext i8 %4 to i32
+  %add = add nuw nsw i32 %conv3, %conv2
+  %conv4 = trunc i32 %add to i8
+  %5 = insertelement <4 x i8> %call, i8 %conv4, i32 2
+  ret <4 x i8> %5
+}
+
+declare <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32], i32, i32) #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @alloc) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6, !7}
+!\23rs_object_slots = !{!8}
+!\23rs_export_foreach_name = !{!9, !10}
+!\23rs_export_foreach = !{!11, !12}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"7"}
+!7 = !{!"alloc", !"20"}
+!8 = !{!"1"}
+!9 = !{!"root"}
+!10 = !{!"k1"}
+!11 = !{!"0"}
+!12 = !{!"35"}
+!13 = !{!14, !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/rs_allocation/read.rs b/rsov/compiler/tests/rs_allocation/read.rs
new file mode 100644
index 0000000..0cde99f
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/read.rs
@@ -0,0 +1,26 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar c1;
+rs_allocation alloc;
+
+uchar4 __attribute__((kernel)) k1(uchar4 in) {
+  uchar4 res = rsGetElementAt_uchar4(alloc, in.r, in.g);
+  res.b += c1;
+  return res;
+}
diff --git a/rsov/compiler/tests/rs_allocation/read_write.ll b/rsov/compiler/tests/rs_allocation/read_write.ll
new file mode 100644
index 0000000..3f0e47f
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/read_write.ll
@@ -0,0 +1,78 @@
+; XFAIL: *
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: %struct___GPUBuffer = OpTypeStruct %uchar
+; CHECK: [[PTR_TYPE:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform %struct___GPUBuffer
+
+; CHECK: %__GPUBlock = OpVariable [[PTR_TYPE]] Uniform
+
+%struct.rs_allocation = type { i32* }
+
+@r = common global %struct.rs_allocation zeroinitializer, align 4
+@w = common global %struct.rs_allocation zeroinitializer, align 4
+@c1 = common global i8 0, align 1
+
+; Function Attrs: nounwind
+define <4 x i8> @k1(<4 x i8> %in, i32 %x, i32 %y) #0 {
+entry:
+  %.unpack = load i32, i32* bitcast (%struct.rs_allocation* @r to i32*), align 4
+  %0 = insertvalue [1 x i32] undef, i32 %.unpack, 0
+  %call = tail call <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32] %0, i32 %x, i32 %y) #2
+  %1 = load i8, i8* @c1, align 1, !tbaa !15
+  %splat.splatinsert = insertelement <4 x i8> undef, i8 %1, i32 0
+  %splat.splat = shufflevector <4 x i8> %splat.splatinsert, <4 x i8> undef, <4 x i32> zeroinitializer
+  %add = add <4 x i8> %call, %in
+  %add1 = add <4 x i8> %add, %splat.splat
+  %.unpack6 = load i32, i32* bitcast (%struct.rs_allocation* @w to i32*), align 4
+  %2 = insertvalue [1 x i32] undef, i32 %.unpack6, 0
+  tail call void @_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj([1 x i32] %2, <4 x i8> %add1, i32 %x, i32 %y) #2
+  ret <4 x i8> %in
+}
+
+declare <4 x i8> @_Z21rsGetElementAt_uchar413rs_allocationjj([1 x i32], i32, i32) #1
+
+declare void @_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj([1 x i32], <4 x i8>, i32, i32) #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @r) #2
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @w) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6, !7, !8}
+!\23rs_object_slots = !{!9, !10}
+!\23rs_export_foreach_name = !{!11, !12}
+!\23rs_export_foreach = !{!13, !14}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"7"}
+!7 = !{!"r", !"20"}
+!8 = !{!"w", !"20"}
+!9 = !{!"1"}
+!10 = !{!"2"}
+!11 = !{!"root"}
+!12 = !{!"k1"}
+!13 = !{!"0"}
+!14 = !{!"59"}
+!15 = !{!16, !16, i64 0}
+!16 = !{!"omnipotent char", !17, i64 0}
+!17 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/rs_allocation/read_write.rs b/rsov/compiler/tests/rs_allocation/read_write.rs
new file mode 100644
index 0000000..8852c82
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/read_write.rs
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar c1;
+rs_allocation r;
+rs_allocation w;
+
+uchar4 __attribute__((kernel)) k1(uchar4 in, uint32_t x, uint32_t y) {
+  uchar4 read = rsGetElementAt_uchar4(r, x, y);
+  rsSetElementAt_uchar4(w, in + c1 + read, x, y);
+  return in;
+}
diff --git a/rsov/compiler/tests/rs_allocation/rewrite_getdim.ll b/rsov/compiler/tests/rs_allocation/rewrite_getdim.ll
new file mode 100644
index 0000000..c2a9534
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/rewrite_getdim.ll
@@ -0,0 +1,71 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+; Source:
+; rs_allocation g;
+; int32_t RS_KERNEL getDim(int32_t dummy) {
+;    return rsAllocationGetDimX(g);
+; }
+source_filename = "global_query4_out/bc32/global_query4.ll"
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: OpMemberDecorate [[MetadataS:%[a-zA-Z_0-9]*]] 0 Offset 4
+; CHECK: OpMemberDecorate [[MetadataS]] 1 Offset 8
+; CHECK: OpMemberDecorate [[MetadataS]] 2 Offset 12
+; CHECK: OpMemberDecorate [[MetadataS]] 3 Offset 16
+; CHECK: OpDecorate [[RuntimeArrS:%[a-zA-Z_0-9]*]] ArrayStride {{[0-9]*}}
+; CHECK: OpDecorate [[MetadataSSBO:%[a-zA-Z_0-9]*]] BufferBlock
+; CHECK: OpDecorate [[Metadata:%[a-zA-Z_0-9]*]] DescriptorSet 0
+; CHECK: OpDecorate [[Metadata]] Binding 1
+
+%struct.rs_allocation = type { i32* }
+
+@g = common global %struct.rs_allocation zeroinitializer, align 4
+
+; CHECK-NOT: %g = OpVariable %{{.*}} Uniform
+; CHECK-NOT: OpFunctionCall %uint %__rsov_rsAllocationGetDimX
+; CHECK: [[DimX:%[a-zA-Z_0-9]*]] = OpAccessChain %_ptr_Uniform_uint [[Metadata]]
+; CHECK: [[Res:%[a-zA-Z_0-9]*]] = OpLoad %uint [[DimX]]
+; CHECK: OpReturnValue [[Res]]
+
+; Function Attrs: nounwind
+define i32 @getDim(i32 %dummy) local_unnamed_addr #0 {
+entry:
+  %.unpack = load i32, i32* bitcast (%struct.rs_allocation* @g to i32*), align 4
+  %0 = insertvalue [1 x i32] undef, i32 %.unpack, 0
+  %call = tail call i32 @_Z19rsAllocationGetDimX13rs_allocation([1 x i32] %0) #2
+  ret i32 %call
+}
+
+declare i32 @_Z19rsAllocationGetDimX13rs_allocation([1 x i32]) local_unnamed_addr #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() local_unnamed_addr #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @g) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) local_unnamed_addr #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_var = !{!5}
+!\23rs_object_slots = !{!6}
+!\23rs_export_foreach_name = !{!7, !8}
+!\23rs_export_foreach = !{!6, !9}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"com.android.rs.rsov.test"}
+!5 = !{!"g", !"20"}
+!6 = !{!"0"}
+!7 = !{!"root"}
+!8 = !{!"getDim"}
+!9 = !{!"35"}
diff --git a/rsov/compiler/tests/rs_allocation/write.ll b/rsov/compiler/tests/rs_allocation/write.ll
new file mode 100644
index 0000000..8865fb6
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/write.ll
@@ -0,0 +1,68 @@
+; XFAIL: *
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+; CHECK: %struct___GPUBuffer = OpTypeStruct {{.*}}
+; CHECK: [[PTR_TYPE:%[a-zA-Z_0-9]+]] = OpTypePointer Uniform %struct___GPUBuffer
+
+; CHECK: %__GPUBlock = OpVariable [[PTR_TYPE]] Uniform
+
+%struct.rs_allocation = type { i32* }
+
+@alloc = common global %struct.rs_allocation zeroinitializer, align 4
+@c1 = common global i8 0, align 1
+
+; Function Attrs: nounwind
+define <4 x i8> @k1(<4 x i8> %in, i32 %x, i32 %y) #0 {
+entry:
+  %0 = load i8, i8* @c1, align 1, !tbaa !13
+  %splat.splatinsert = insertelement <4 x i8> undef, i8 %0, i32 0
+  %splat.splat = shufflevector <4 x i8> %splat.splatinsert, <4 x i8> undef, <4 x i32> zeroinitializer
+  %add = add <4 x i8> %splat.splat, %in
+  %.unpack = load i32, i32* bitcast (%struct.rs_allocation* @alloc to i32*), align 4
+  %1 = insertvalue [1 x i32] undef, i32 %.unpack, 0
+  tail call void @_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj([1 x i32] %1, <4 x i8> %add, i32 %x, i32 %y) #2
+  ret <4 x i8> %in
+}
+
+declare void @_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj([1 x i32], <4 x i8>, i32, i32) #1
+
+; Function Attrs: nounwind
+define void @.rs.dtor() #0 {
+entry:
+  tail call void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation* nonnull @alloc) #2
+  ret void
+}
+
+declare void @_Z13rsClearObjectP13rs_allocation(%struct.rs_allocation*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4, !5}
+!\23rs_export_var = !{!6, !7}
+!\23rs_object_slots = !{!8}
+!\23rs_export_foreach_name = !{!9, !10}
+!\23rs_export_foreach = !{!11, !12}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!"rs_fp_relaxed", !""}
+!6 = !{!"c1", !"7"}
+!7 = !{!"alloc", !"20"}
+!8 = !{!"1"}
+!9 = !{!"root"}
+!10 = !{!"k1"}
+!11 = !{!"0"}
+!12 = !{!"59"}
+!13 = !{!14, !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
diff --git a/rsov/compiler/tests/rs_allocation/write.rs b/rsov/compiler/tests/rs_allocation/write.rs
new file mode 100644
index 0000000..ef87c7a
--- /dev/null
+++ b/rsov/compiler/tests/rs_allocation/write.rs
@@ -0,0 +1,25 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+uchar c1;
+rs_allocation alloc;
+
+uchar4 __attribute__((kernel)) k1(uchar4 in, uint32_t x, uint32_t y) {
+  rsSetElementAt_uchar4(alloc, in + c1, x, y);
+  return in;
+}
diff --git a/rsov/compiler/tests/run-lit-tests.sh b/rsov/compiler/tests/run-lit-tests.sh
new file mode 100755
index 0000000..54bb559
--- /dev/null
+++ b/rsov/compiler/tests/run-lit-tests.sh
@@ -0,0 +1,17 @@
+#!/bin/bash -e
+
+current_dir=$(pwd)
+export PATH=$current_dir:$PATH
+LIT_PATH=$current_dir/llvm-lit
+LIBSPIRV_TESTS=$current_dir
+
+for arg in $@ ; do
+  if [[ -a "$arg" ]] ; then
+    # Looks like the user specified one or more files,
+    # so don't implicitly specify the current directory.
+    LIBSPIRV_TESTS=
+    break
+  fi
+done
+
+$LIT_PATH $LIBSPIRV_TESTS $@
diff --git a/rsov/compiler/tests/single_kernel/duff.ll b/rsov/compiler/tests/single_kernel/duff.ll
new file mode 100644
index 0000000..535888b
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/duff.ll
@@ -0,0 +1,104 @@
+; Expecting validation failure
+; RUN: not rs2spirv_lit_driver.sh %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute %[[WrapperId:[a-zA-Z_0-9]*]] "entry_duff"
+; CHECK: [[KernelId:%[a-zA-Z_0-9]+]] = OpFunction {{.*}}
+; Function Attrs: norecurse nounwind readnone
+define i32 @duff(i32 %count) #0 {
+entry:
+  %add = add nsw i32 %count, 7
+  %div = sdiv i32 %add, 8
+  %rem = srem i32 %count, 8
+  switch i32 %rem, label %sw.epilog [
+    i32 0, label %do.body
+    i32 7, label %sw.bb1
+    i32 6, label %sw.bb2
+    i32 5, label %sw.bb3
+    i32 4, label %sw.bb6
+    i32 3, label %sw.bb8
+    i32 2, label %sw.bb12
+    i32 1, label %sw.bb14
+  ]
+
+do.body:                                          ; preds = %entry, %sw.bb14
+  %n.0 = phi i32 [ %dec15, %sw.bb14 ], [ %div, %entry ]
+  %x.0 = phi i32 [ %shl, %sw.bb14 ], [ 321, %entry ]
+  %mul = mul nsw i32 %x.0, 5
+  br label %sw.bb1
+
+sw.bb1:                                           ; preds = %entry, %do.body
+  %n.1 = phi i32 [ %n.0, %do.body ], [ %div, %entry ]
+  %x.1 = phi i32 [ %mul, %do.body ], [ 321, %entry ]
+  %dec = add nsw i32 %x.1, -1
+  br label %sw.bb2
+
+sw.bb2:                                           ; preds = %entry, %sw.bb1
+  %n.2 = phi i32 [ %n.1, %sw.bb1 ], [ %div, %entry ]
+  %x.2 = phi i32 [ %dec, %sw.bb1 ], [ 321, %entry ]
+  %xor = xor i32 %x.2, 27
+  br label %sw.bb3
+
+sw.bb3:                                           ; preds = %entry, %sw.bb2
+  %n.3 = phi i32 [ %n.2, %sw.bb2 ], [ %div, %entry ]
+  %x.3 = phi i32 [ %xor, %sw.bb2 ], [ 321, %entry ]
+  %mul4 = mul nsw i32 %x.3, %x.3
+  %sub.neg = add i32 %x.3, 12
+  %sub5 = sub i32 %sub.neg, %mul4
+  br label %sw.bb6
+
+sw.bb6:                                           ; preds = %entry, %sw.bb3
+  %n.4 = phi i32 [ %n.3, %sw.bb3 ], [ %div, %entry ]
+  %x.4 = phi i32 [ %sub5, %sw.bb3 ], [ 321, %entry ]
+  %add7 = add nsw i32 %x.4, 2
+  br label %sw.bb8
+
+sw.bb8:                                           ; preds = %entry, %sw.bb6
+  %n.5 = phi i32 [ %n.4, %sw.bb6 ], [ %div, %entry ]
+  %x.5 = phi i32 [ %add7, %sw.bb6 ], [ 321, %entry ]
+  %rem9 = srem i32 %x.5, 32
+  %mul10 = mul nsw i32 %x.5, %x.5
+  %add11 = add nsw i32 %rem9, %mul10
+  br label %sw.bb12
+
+sw.bb12:                                          ; preds = %entry, %sw.bb8
+  %n.6 = phi i32 [ %n.5, %sw.bb8 ], [ %div, %entry ]
+  %x.6 = phi i32 [ %add11, %sw.bb8 ], [ 321, %entry ]
+  %sub13 = add nsw i32 %x.6, -2
+  br label %sw.bb14
+
+sw.bb14:                                          ; preds = %entry, %sw.bb12
+  %n.7 = phi i32 [ %div, %entry ], [ %n.6, %sw.bb12 ]
+  %x.7 = phi i32 [ 321, %entry ], [ %sub13, %sw.bb12 ]
+  %shl = shl i32 %x.7, 3
+  %dec15 = add nsw i32 %n.7, -1
+  %cmp = icmp sgt i32 %n.7, 1
+  br i1 %cmp, label %do.body, label %sw.epilog
+
+sw.epilog:                                        ; preds = %sw.bb14, %entry
+  %x.8 = phi i32 [ 321, %entry ], [ %shl, %sw.bb14 ]
+  ret i32 %x.8
+}
+
+; CHECK: %[[WrapperId]] = OpFunction {{.*}}
+; CHECK-NEXT: OpLabel
+; CHECK: %{{[0-9]+}} = OpFunctionCall %{{.*}} [[KernelId]]
+; CHECK: OpReturn
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4, !5}
+!\23rs_export_foreach = !{!6, !7}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2spirv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"duff"}
+!6 = !{!"0"}
+!7 = !{!"35"}
diff --git a/rsov/compiler/tests/single_kernel/fib.ll b/rsov/compiler/tests/single_kernel/fib.ll
new file mode 100644
index 0000000..fe62505
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/fib.ll
@@ -0,0 +1,45 @@
+; Expecting validation failure
+; RUN: not rs2spirv_lit_driver.sh %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Function Attrs: nounwind readnone
+; CHECK: OpEntryPoint GLCompute %{{[a-zA-Z_0-9]*}} "entry_fib" %gl_GlobalInvocationID
+define i32 @fib(i32 %n) #0 {
+entry:
+  %n.off8 = add i32 %n, -1
+  %0 = icmp ult i32 %n.off8, 2
+  br i1 %0, label %return, label %if.end
+
+if.end:                                           ; preds = %entry, %if.end
+  %n.tr10 = phi i32 [ %sub2, %if.end ], [ %n, %entry ]
+  %accumulator.tr9 = phi i32 [ %add, %if.end ], [ 1, %entry ]
+  %sub = add nsw i32 %n.tr10, -1
+  %call = tail call i32 @fib(i32 %sub)
+  %sub2 = add nsw i32 %n.tr10, -2
+  %add = add nsw i32 %call, %accumulator.tr9
+  %n.off = add i32 %n.tr10, -3
+  %1 = icmp ult i32 %n.off, 2
+  br i1 %1, label %return, label %if.end
+
+return:                                           ; preds = %if.end, %entry
+  %accumulator.tr.lcssa = phi i32 [ 1, %entry ], [ %add, %if.end ]
+  ret i32 %accumulator.tr.lcssa
+}
+
+attributes #0 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4, !5}
+!\23rs_export_foreach = !{!6, !7}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2spirv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"fib"}
+!6 = !{!"0"}
+!7 = !{!"35"}
diff --git a/rsov/compiler/tests/single_kernel/identity.ll b/rsov/compiler/tests/single_kernel/identity.ll
new file mode 100644
index 0000000..4195442
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/identity.ll
@@ -0,0 +1,27 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Function Attrs: norecurse nounwind readnone
+; CHECK: OpEntryPoint GLCompute %{{[a-zA-Z_0-9]*}} "entry_foo" %gl_GlobalInvocationID{{.*}}
+define i32 @foo(i32 %in) #0 {
+; CHECK: OpReturnValue {{.*}}
+  ret i32 %in
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4, !5}
+!\23rs_export_foreach = !{!6, !7}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2spirv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"foo"}
+!6 = !{!"0"}
+!7 = !{!"35"}
diff --git a/rsov/compiler/tests/single_kernel/identity.rs b/rsov/compiler/tests/single_kernel/identity.rs
new file mode 100644
index 0000000..a3bdb6e
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/identity.rs
@@ -0,0 +1,9 @@
+// TODO: Complete the test.
+
+#pragma version(1)
+#pragma rs java_package_name(rs2srpiv)
+#pragma rs_fp_relaxed
+
+int __attribute__((kernel)) foo(int in) {
+  return in;
+}
diff --git a/rsov/compiler/tests/single_kernel/invert.ll b/rsov/compiler/tests/single_kernel/invert.ll
new file mode 100644
index 0000000..8a9efdb
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/invert.ll
@@ -0,0 +1,46 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Function Attrs: norecurse nounwind readnone
+; CHECK:OpDecorate %[[BUF_S:.*]] BufferBlock
+; CHECK:OpDecorate %[[BUF_VAR:.*]] DescriptorSet {{[0-9]}}
+; CHECK:OpDecorate %[[BUF_VAR]] Binding {{[0-9]}}
+; CHECK:%[[BUF_PTR_TY:.*]] = OpTypePointer Uniform %[[BUF_S]]
+; CHECK:%[[BUF_VAR]] = OpVariable %[[BUF_PTR_TY]] Uniform
+; CHECK:%[[ADDR:.*]] = OpAccessChain {{.*}} %[[BUF_VAR]]
+; CHECK:OpLoad {{.*}} %[[ADDR]]
+
+define <4 x float> @invert(<4 x float> %in) #0 {
+entry:
+  %0 = extractelement <4 x float> %in, i64 0
+  %sub = fsub float 1.000000e+00, %0
+  %1 = insertelement <4 x float> undef, float %sub, i64 0
+  %2 = extractelement <4 x float> %in, i64 1
+  %sub1 = fsub float 1.000000e+00, %2
+  %3 = insertelement <4 x float> %1, float %sub1, i64 1
+  %4 = extractelement <4 x float> %in, i64 2
+  %sub2 = fsub float 1.000000e+00, %4
+  %5 = insertelement <4 x float> %3, float %sub2, i64 2
+  %6 = extractelement <4 x float> %in, i64 3
+  %sub3 = fsub float 1.000000e+00, %6
+  %7 = insertelement <4 x float> %5, float %sub3, i64 3
+  ret <4 x float> %7
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4, !5}
+!\23rs_export_foreach = !{!6, !7}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2spirv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"invert"}
+!6 = !{!"0"}
+!7 = !{!"35"}
diff --git a/rsov/compiler/tests/single_kernel/kernel.ll b/rsov/compiler/tests/single_kernel/kernel.ll
new file mode 100644
index 0000000..03bea0e
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/kernel.ll
@@ -0,0 +1,32 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute [[WrapperId:%[a-zA-Z_0-9]*]] "entry_foo"
+; CHECK: [[KernelId:%[a-zA-Z_0-9]+]] = OpFunction {{.*}}
+
+; Function Attrs: norecurse nounwind readnone
+define void @foo() #0 {
+  ret void
+}
+; CHECK: [[WrapperId]] = OpFunction {{.*}}
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT: %{{[0-9]+}} = OpFunctionCall %{{.*}} [[KernelId]]
+; CHECK-NEXT: OpReturn
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4, !5}
+!\23rs_export_foreach = !{!6, !7}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2srpiv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"foo"}
+!6 = !{!"0"}
+!7 = !{!"32"}
diff --git a/rsov/compiler/tests/single_kernel/kernel.rs b/rsov/compiler/tests/single_kernel/kernel.rs
new file mode 100644
index 0000000..2e38a13
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/kernel.rs
@@ -0,0 +1,6 @@
+#pragma version(1)
+#pragma rs java_package_name(rs2spirv)
+#pragma rs_fp_relaxed
+
+void __attribute__((kernel)) foo() {
+}
diff --git a/rsov/compiler/tests/single_kernel/mixed.ll b/rsov/compiler/tests/single_kernel/mixed.ll
new file mode 100644
index 0000000..c968ccc
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/mixed.ll
@@ -0,0 +1,66 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+; CHECK: OpEntryPoint GLCompute %{{[a-zA-Z_0-9]*}} "entry_inc" %gl_GlobalInvocationID
+; CHECK-NOT: an_invokable
+
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+@.str = private unnamed_addr constant [24 x i8] c"test_root_output FAILED\00", align 1
+
+; Function Attrs: nounwind
+define void @an_invokable(float %i) local_unnamed_addr #0 {
+entry:
+  %call = tail call fastcc float @sum(float %i, float 2.000000e+00)
+  %conv = fptosi float %call to i32
+  tail call void @_Z7rsDebugPKci(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i32 0, i32 0), i32 %conv) #4
+  ret void
+}
+
+declare void @_Z7rsDebugPKci(i8*, i32) local_unnamed_addr #1
+
+; Function Attrs: norecurse nounwind readnone
+define internal fastcc float @sum(float %i, float %j) unnamed_addr #2 {
+entry:
+  %add = fadd float %i, %j
+  ret float %add
+}
+
+; Function Attrs: norecurse nounwind readnone
+define float @inc(float %i) local_unnamed_addr #2 {
+entry:
+  %call = tail call fastcc float @sum(float %i, float 1.000000e+00)
+  ret float %call
+}
+
+; Function Attrs: noinline nounwind
+define void @.helper_an_invokable({ float }* nocapture) local_unnamed_addr #3 {
+entry:
+  %1 = getelementptr inbounds { float }, { float }* %0, i32 0, i32 0
+  %2 = load float, float* %1, align 4
+  tail call void @an_invokable(float %2)
+  ret void
+}
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { noinline nounwind }
+attributes #4 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_func = !{!5}
+!\23rs_export_foreach_name = !{!6, !7}
+!\23rs_export_foreach = !{!8, !9}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"Android clang version 3.8.275480  (based on LLVM 3.8.275480)"}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"rs2spirv"}
+!5 = !{!".helper_an_invokable"}
+!6 = !{!"root"}
+!7 = !{!"inc"}
+!8 = !{!"0"}
+!9 = !{!"35"}
diff --git a/rsov/compiler/tests/single_kernel/newroot.ll b/rsov/compiler/tests/single_kernel/newroot.ll
new file mode 100644
index 0000000..c1055b3
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/newroot.ll
@@ -0,0 +1,30 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute [[WrapperId:%[a-zA-Z_0-9]*]] "entry_root"
+; CHECK: [[KernelId:%[a-zA-Z_0-9]+]] = OpFunction {{.*}}
+
+; Function Attrs: norecurse nounwind readnone
+define i32 @root(i32 %a) #0 {
+  ret i32 %a
+}
+; CHECK: [[WrapperId]] = OpFunction {{.*}}
+; CHECK-NEXT: OpLabel
+; CHECK: %{{[0-9]+}} = OpFunctionCall %{{.*}} [[KernelId]]
+; CHECK: OpReturn
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4}
+!\23rs_export_foreach = !{!5}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2srpiv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"35"}
diff --git a/rsov/compiler/tests/single_kernel/oldroot.ll b/rsov/compiler/tests/single_kernel/oldroot.ll
new file mode 100644
index 0000000..1f3da89
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/oldroot.ll
@@ -0,0 +1,23 @@
+; RUN: not rs2spirv_lit_driver.sh %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Function Attrs: norecurse nounwind readnone
+define void @root(i8 *%in, i8 *%out, i32 %x, i32 %y) #0 {
+  ret void
+}
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4}
+!\23rs_export_foreach = !{!5}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2srpiv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"27"}
diff --git a/rsov/compiler/tests/single_kernel/times.ll b/rsov/compiler/tests/single_kernel/times.ll
new file mode 100644
index 0000000..e63bfee
--- /dev/null
+++ b/rsov/compiler/tests/single_kernel/times.ll
@@ -0,0 +1,35 @@
+; RUN: rs2spirv_lit_driver.sh %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; CHECK: OpEntryPoint GLCompute %[[WrapperId:[a-zA-Z_0-9]*]] "entry_times"
+; CHECK: [[KernelId:%[a-zA-Z_0-9]+]] = OpFunction {{.*}}
+
+; Function Attrs: norecurse nounwind readnone
+define i32 @times(i32 %x) #0 {
+entry:
+  %mul = shl i32 %x, 1
+  ret i32 %mul
+}
+
+; CHECK: %[[WrapperId]] = OpFunction {{.*}}
+; CHECK-NEXT: OpLabel
+; CHECK: %{{[0-9]+}} = OpFunctionCall %{{.*}} [[KernelId]]
+; CHECK: OpReturn
+
+attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2, !3}
+!\23rs_export_foreach_name = !{!4, !5}
+!\23rs_export_foreach = !{!6, !7}
+
+!0 = !{!"Android clang version 3.8.256229  (based on LLVM 3.8.256229)"}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"rs2spirv"}
+!3 = !{!"rs_fp_relaxed", !""}
+!4 = !{!"root"}
+!5 = !{!"times"}
+!6 = !{!"0"}
+!7 = !{!"42"}
diff --git a/rsov/compiler/unit_tests/TestRunner.h b/rsov/compiler/unit_tests/TestRunner.h
new file mode 100644
index 0000000..4e8f57a
--- /dev/null
+++ b/rsov/compiler/unit_tests/TestRunner.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RS2SPIRV_TEST_RUNNER
+#define RS2SPIRV_TEST_RUNNER
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <cassert>
+#include <vector>
+
+namespace rs2spirv {
+
+struct TestCase {
+  void (*testPtr)(void);
+  const char *const description;
+};
+
+class TestRunnerContext {
+public:
+  static TestRunnerContext &getInstance() {
+    static TestRunnerContext ctx;
+    return ctx;
+  }
+
+  static void addTest(TestCase TC) { getInstance().tests.push_back(TC); }
+  static size_t &getCheckSuccessNum() { return getInstance().checkSuccessNum; }
+  static size_t &getTotalCheckNum() { return getInstance().totalCheckNum; }
+
+  static int runTests() {
+    bool Failed = false;
+    for (auto &TC : getInstance().tests) {
+      getCheckSuccessNum() = getTotalCheckNum() = 0;
+      llvm::outs() << "Test(" << TC.description << ") {\n";
+      TC.testPtr();
+      llvm::outs() << "\n} (" << TC.description << ") [" << getCheckSuccessNum()
+                   << "/" << getTotalCheckNum() << "]\n\n";
+      Failed |= getCheckSuccessNum() != getTotalCheckNum();
+    }
+
+    return static_cast<int>(Failed);
+  }
+
+private:
+  TestRunnerContext() = default;
+  std::vector<TestCase> tests;
+  size_t checkSuccessNum;
+  size_t totalCheckNum;
+};
+
+struct TestAdder {
+  TestAdder(TestCase TC) { TestRunnerContext::addTest(TC); }
+};
+
+#define RS2SPIRV_CONCAT_IMPL(S1, S2) S1##S2
+#define RS2SPIRV_CONCAT(S1, S2) RS2SPIRV_CONCAT_IMPL(S1, S2)
+#define RS2SPIRV_ANONYMOUS(X) RS2SPIRV_CONCAT(X, __COUNTER__)
+
+#if RS2SPIRV_DEBUG
+#define RS2SPIRV_TEST_CASE_ADD_IMPL(FNAME, VNAME, DESCRIPTION)                 \
+  static void FNAME();                                                         \
+  static rs2spirv::TestAdder VNAME({FNAME, DESCRIPTION});                      \
+  inline void FNAME()
+#elif defined(__GNUC__) || defined(__clang__)
+#define RS2SPIRV_TEST_CASE_ADD_IMPL(FNAME, VNAME, DESCRIPTION)                 \
+  static inline void __attribute__((unused)) FNAME()
+#else
+#define RS2SPIRV_TEST_CASE_ADD_IMPL(FNAME, VNAME, DESCRIPTION)                 \
+  static inline void FNAME()
+#endif
+
+#define RS2SPIRV_TEST_CASE_ADD(NAME, DESCRIPTION)                              \
+  RS2SPIRV_TEST_CASE_ADD_IMPL(RS2SPIRV_ANONYMOUS(NAME),                        \
+                              RS2SPIRV_ANONYMOUS(NAME), DESCRIPTION)
+
+#define TEST_CASE(DESCRIPTION) RS2SPIRV_TEST_CASE_ADD(TC, DESCRIPTION)
+
+#define CHECK(CONDITION)                                                       \
+  ++rs2spirv::TestRunnerContext::getTotalCheckNum();                           \
+  if (!(CONDITION))                                                            \
+    llvm::errs() << "\nCHECK <(  " #CONDITION "  )> failed!\n";                \
+  else                                                                         \
+    ++rs2spirv::TestRunnerContext::getCheckSuccessNum();                       \
+  (void)0
+
+} // namespace rs2spirv
+
+#endif
diff --git a/rsov/driver/.clang-format b/rsov/driver/.clang-format
new file mode 100644
index 0000000..e8b6a2d
--- /dev/null
+++ b/rsov/driver/.clang-format
@@ -0,0 +1,95 @@
+---
+Language:        Cpp
+# BasedOnStyle:  Google
+AccessModifierOffset: -1
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: true
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: true
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+  AfterClass:      false
+  AfterControlStatement: false
+  AfterEnum:       false
+  AfterFunction:   false
+  AfterNamespace:  false
+  AfterObjCDeclaration: false
+  AfterStruct:     false
+  AfterUnion:      false
+  BeforeCatch:     false
+  BeforeElse:      false
+  IndentBraces:    false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeCategories:
+  - Regex:           '^<.*\.h>'
+    Priority:        1
+  - Regex:           '^<.*'
+    Priority:        2
+  - Regex:           '.*'
+    Priority:        3
+IncludeIsMainRegex: '([-_](test|unittest))?$'
+IndentCaseLabels: true
+IndentWidth:     2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments:  true
+SortIncludes:    true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Auto
+TabWidth:        8
+UseTab:          Never
+...
+
diff --git a/rsov/driver/Android.mk b/rsov/driver/Android.mk
new file mode 100644
index 0000000..8154c9e
--- /dev/null
+++ b/rsov/driver/Android.mk
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH :=$(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libRSDriver_RSoV
+
+LOCAL_SRC_FILES := \
+    rsovAllocation.cpp \
+    rsovContext.cpp \
+    rsovCore.cpp \
+    rsovElement.cpp \
+    rsovRuntimeStubs.cpp \
+    rsovSampler.cpp \
+    rsovScript.cpp \
+    rsovScriptGroup.cpp \
+    rsovType.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libRS_internal \
+    libRSCpuRef \
+    libbcinfo \
+    libc++ \
+    liblog \
+    libspirit \
+    libvulkan \
+    libgui
+
+LOCAL_C_INCLUDES := \
+    frameworks/compile/libbcc/include \
+    frameworks/native/vulkan/include \
+    frameworks/rs \
+    frameworks/rs/cpu_ref \
+    frameworks/rs/rsov/compiler \
+
+LOCAL_C_INCLUDES += \
+
+LOCAL_CFLAGS := -Werror -Wall -Wextra
+# TODO: remove warnings on unused variables and parameters
+LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-parameter
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/rsov/driver/rsovAllocation.cpp b/rsov/driver/rsovAllocation.cpp
new file mode 100644
index 0000000..b9d3c98
--- /dev/null
+++ b/rsov/driver/rsovAllocation.cpp
@@ -0,0 +1,698 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovAllocation.h"
+
+#include "rsAllocation.h"
+#include "rsContext.h"
+#include "rsCppUtils.h"
+#include "rsElement.h"
+#include "rsType.h"
+#include "rsovContext.h"
+#include "rsovCore.h"
+
+namespace android {
+namespace renderscript {
+namespace rsov {
+
+namespace {
+
+size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
+  // For the flexible YCbCr format, layout is initialized during call to
+  // Allocation::ioReceive.  Return early and avoid clobberring any
+  // pre-existing layout.
+  if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+    return 0;
+  }
+
+  // YUV only supports basic 2d
+  // so we can stash the plane pointers in the mipmap levels.
+  size_t uvSize = 0;
+  state->lod[1].dimX = state->lod[0].dimX / 2;
+  state->lod[1].dimY = state->lod[0].dimY / 2;
+  state->lod[2].dimX = state->lod[0].dimX / 2;
+  state->lod[2].dimY = state->lod[0].dimY / 2;
+  state->yuv.shift = 1;
+  state->yuv.step = 1;
+  state->lodCount = 3;
+
+  switch (yuv) {
+    case HAL_PIXEL_FORMAT_YV12:
+      state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
+      state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
+                                (state->lod[0].stride * state->lod[0].dimY);
+      uvSize += state->lod[2].stride * state->lod[2].dimY;
+
+      state->lod[1].stride = state->lod[2].stride;
+      state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
+                                (state->lod[2].stride * state->lod[2].dimY);
+      uvSize += state->lod[1].stride * state->lod[2].dimY;
+      break;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
+      // state->lod[1].dimX = state->lod[0].dimX;
+      state->lod[1].stride = state->lod[0].stride;
+      state->lod[2].stride = state->lod[0].stride;
+      state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
+                                (state->lod[0].stride * state->lod[0].dimY);
+      state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1;
+      uvSize += state->lod[1].stride * state->lod[1].dimY;
+      state->yuv.step = 2;
+      break;
+    default:
+      rsAssert(0);
+  }
+
+  return uvSize;
+}
+
+// TODO: Dedup this with the same code under frameworks/rs/driver
+size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
+                                   const Type *type, uint8_t *ptr,
+                                   size_t requiredAlignment) {
+  alloc->mHal.drvState.lod[0].dimX = type->getDimX();
+  alloc->mHal.drvState.lod[0].dimY = type->getDimY();
+  alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
+  alloc->mHal.drvState.lod[0].mallocPtr = 0;
+  // Stride needs to be aligned to a boundary defined by requiredAlignment!
+  size_t stride =
+      alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
+  alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment);
+  alloc->mHal.drvState.lodCount = type->getLODCount();
+  alloc->mHal.drvState.faceCount = type->getDimFaces();
+
+  size_t offsets[Allocation::MAX_LOD];
+  memset(offsets, 0, sizeof(offsets));
+
+  size_t o = alloc->mHal.drvState.lod[0].stride *
+             rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
+             rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
+  if (alloc->mHal.state.yuv) {
+    o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
+
+    for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
+      offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
+    }
+  } else if (alloc->mHal.drvState.lodCount > 1) {
+    uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
+    uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
+    uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
+    for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) {
+      alloc->mHal.drvState.lod[lod].dimX = tx;
+      alloc->mHal.drvState.lod[lod].dimY = ty;
+      alloc->mHal.drvState.lod[lod].dimZ = tz;
+      alloc->mHal.drvState.lod[lod].stride =
+          rsRound(tx * type->getElementSizeBytes(), requiredAlignment);
+      offsets[lod] = o;
+      o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
+      if (tx > 1) tx >>= 1;
+      if (ty > 1) ty >>= 1;
+      if (tz > 1) tz >>= 1;
+    }
+  }
+
+  alloc->mHal.drvState.faceOffset = o;
+
+  alloc->mHal.drvState.lod[0].mallocPtr = ptr;
+  for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) {
+    alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
+  }
+
+  size_t allocSize = alloc->mHal.drvState.faceOffset;
+  if (alloc->mHal.drvState.faceCount) {
+    allocSize *= 6;
+  }
+
+  return allocSize;
+}
+
+size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
+                                   const Type *type, uint8_t *ptr) {
+  return AllocationBuildPointerTable(rsc, alloc, type, ptr,
+                                     Allocation::kMinimumRSAlignment);
+}
+
+uint8_t *GetOffsetPtr(const Allocation *alloc, uint32_t xoff, uint32_t yoff,
+                      uint32_t zoff, uint32_t lod,
+                      RsAllocationCubemapFace face) {
+  uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
+  ptr += face * alloc->mHal.drvState.faceOffset;
+  ptr += zoff * alloc->mHal.drvState.lod[lod].dimY *
+         alloc->mHal.drvState.lod[lod].stride;
+  ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
+  ptr += xoff * alloc->mHal.state.elementSizeBytes;
+  return ptr;
+}
+
+void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
+  uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
+  uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
+
+  for (uint32_t y = 0; y < h; y++) {
+    uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
+    const uint16_t *i1 =
+        (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2, lod, face);
+    const uint16_t *i2 =
+        (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2 + 1, lod, face);
+
+    for (uint32_t x = 0; x < w; x++) {
+      *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
+      oPtr++;
+      i1 += 2;
+      i2 += 2;
+    }
+  }
+}
+
+void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
+  uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
+  uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
+
+  for (uint32_t y = 0; y < h; y++) {
+    uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
+    const uint32_t *i1 =
+        (uint32_t *)GetOffsetPtr(alloc, 0, y * 2, 0, lod, face);
+    const uint32_t *i2 =
+        (uint32_t *)GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face);
+
+    for (uint32_t x = 0; x < w; x++) {
+      *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
+      oPtr++;
+      i1 += 2;
+      i2 += 2;
+    }
+  }
+}
+
+void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
+  uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
+  uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
+
+  for (uint32_t y = 0; y < h; y++) {
+    uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
+    const uint8_t *i1 = GetOffsetPtr(alloc, 0, y * 2, 0, lod, face);
+    const uint8_t *i2 = GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face);
+
+    for (uint32_t x = 0; x < w; x++) {
+      *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
+      oPtr++;
+      i1 += 2;
+      i2 += 2;
+    }
+  }
+}
+
+}  // anonymous namespace
+
+RSoVAllocation::RSoVAllocation(RSoVContext *context, const Type *type,
+                               size_t bufferSize)
+    : mBuffer(new RSoVBuffer(context, bufferSize)),
+      mType(type),
+      mWidth(type->getDimX()),
+      mHeight(type->getDimY()),
+      mDepth(type->getDimZ()) {}
+
+RSoVBuffer::RSoVBuffer(RSoVContext *context, size_t size)
+    : mRSoV(context), mDevice(context->getDevice()) {
+  InitBuffer(size);
+}
+
+RSoVBuffer::~RSoVBuffer() {
+  vkUnmapMemory(mDevice, mMem);
+  vkDestroyBuffer(mDevice, mBuf, nullptr);
+  vkFreeMemory(mDevice, mMem, nullptr);
+}
+
+void RSoVBuffer::InitBuffer(size_t bufferSize) {
+  VkResult res;
+
+  VkBufferCreateInfo buf_info = {
+      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+      .pNext = nullptr,
+      .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+      .size = bufferSize,
+      .queueFamilyIndexCount = 0,
+      .pQueueFamilyIndices = nullptr,
+      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+      .flags = 0,
+  };
+  res = vkCreateBuffer(mDevice, &buf_info, nullptr, &mBuf);
+  rsAssert(res == VK_SUCCESS);
+
+  VkMemoryRequirements mem_reqs;
+  vkGetBufferMemoryRequirements(mDevice, mBuf, &mem_reqs);
+
+  VkMemoryAllocateInfo allocateInfo = {
+      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+      .pNext = nullptr,
+      .memoryTypeIndex = 0,
+      .allocationSize = mem_reqs.size,
+  };
+
+  bool pass;
+  pass =
+      mRSoV->MemoryTypeFromProperties(mem_reqs.memoryTypeBits,
+                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                          VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+                                      &allocateInfo.memoryTypeIndex);
+  rsAssert(pass);
+
+  // TODO: Make this aligned
+  res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem);
+  rsAssert(res == VK_SUCCESS);
+
+  res = vkBindBufferMemory(mDevice, mBuf, mMem, 0);
+  rsAssert(res == VK_SUCCESS);
+
+  mBufferInfo.buffer = mBuf;
+  mBufferInfo.offset = 0;
+  mBufferInfo.range = bufferSize;
+
+  res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr);
+  rsAssert(res == VK_SUCCESS);
+}
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
+
+using android::renderscript::Allocation;
+using android::renderscript::Context;
+using android::renderscript::Element;
+using android::renderscript::Type;
+using android::renderscript::rs_allocation;
+using android::renderscript::rsMax;
+using namespace android::renderscript::rsov;
+
+bool rsovAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
+  RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv);
+  RSoVContext *rsov = hal->mRSoV;
+  const Type *type = alloc->getType();
+
+  // Calculate the object size.
+  size_t allocSize = AllocationBuildPointerTable(rsc, alloc, type, nullptr);
+  RSoVAllocation *rsovAlloc = new RSoVAllocation(rsov, type, allocSize);
+  alloc->mHal.drv = rsovAlloc;
+  AllocationBuildPointerTable(rsc, alloc, type,
+                              (uint8_t *)rsovAlloc->getHostPtr());
+  return true;
+}
+
+void rsovAllocationDestroy(const Context *rsc, Allocation *alloc) {
+  RSoVAllocation *rsovAlloc = static_cast<RSoVAllocation *>(alloc->mHal.drv);
+  delete rsovAlloc;
+  alloc->mHal.drv = nullptr;
+}
+
+void rsovAllocationData1D(const Context *rsc, const Allocation *alloc,
+                          uint32_t xoff, uint32_t lod, size_t count,
+                          const void *data, size_t sizeBytes) {
+  const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
+  uint8_t *ptr =
+      GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+  size_t size = count * eSize;
+  if (ptr != data) {
+    // Skip the copy if we are the same allocation. This can arise from
+    // our Bitmap optimization, where we share the same storage.
+    if (alloc->mHal.state.hasReferences) {
+      alloc->incRefs(data, count);
+      alloc->decRefs(ptr, count);
+    }
+    memcpy(ptr, data, size);
+  }
+}
+
+void rsovAllocationData2D(const Context *rsc, const Allocation *alloc,
+                          uint32_t xoff, uint32_t yoff, uint32_t lod,
+                          RsAllocationCubemapFace face, uint32_t w, uint32_t h,
+                          const void *data, size_t sizeBytes, size_t stride) {
+  size_t eSize = alloc->mHal.state.elementSizeBytes;
+  size_t lineSize = eSize * w;
+  if (!stride) {
+    stride = lineSize;
+  }
+
+  if (alloc->mHal.drvState.lod[0].mallocPtr) {
+    const uint8_t *src = static_cast<const uint8_t *>(data);
+    uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
+
+    for (uint32_t line = yoff; line < (yoff + h); line++) {
+      if (alloc->mHal.state.hasReferences) {
+        alloc->incRefs(src, w);
+        alloc->decRefs(dst, w);
+      }
+      memcpy(dst, src, lineSize);
+      src += stride;
+      dst += alloc->mHal.drvState.lod[lod].stride;
+    }
+    // TODO: handle YUV Allocations
+    if (alloc->mHal.state.yuv) {
+      size_t clineSize = lineSize;
+      int lod = 1;
+      int maxLod = 2;
+      if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) {
+        maxLod = 3;
+        clineSize >>= 1;
+      } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+        lod = 2;
+        maxLod = 3;
+      }
+
+      while (lod < maxLod) {
+        uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
+
+        for (uint32_t line = (yoff >> 1); line < ((yoff + h) >> 1); line++) {
+          memcpy(dst, src, clineSize);
+          // When copying from an array to an Allocation, the src pointer
+          // to the array should just move by the number of bytes copied.
+          src += clineSize;
+          dst += alloc->mHal.drvState.lod[lod].stride;
+        }
+        lod++;
+      }
+    }
+  }
+}
+
+void rsovAllocationData3D(const Context *rsc, const Allocation *alloc,
+                          uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                          uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
+                          const void *data, size_t sizeBytes, size_t stride) {
+  uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+  uint32_t lineSize = eSize * w;
+  if (!stride) {
+    stride = lineSize;
+  }
+
+  if (alloc->mHal.drvState.lod[0].mallocPtr) {
+    const uint8_t *src = static_cast<const uint8_t *>(data);
+    for (uint32_t z = zoff; z < (d + zoff); z++) {
+      uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
+                                  RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+      for (uint32_t line = yoff; line < (yoff + h); line++) {
+        if (alloc->mHal.state.hasReferences) {
+          alloc->incRefs(src, w);
+          alloc->decRefs(dst, w);
+        }
+        memcpy(dst, src, lineSize);
+        src += stride;
+        dst += alloc->mHal.drvState.lod[lod].stride;
+      }
+    }
+  }
+}
+
+void rsovAllocationRead1D(const Context *rsc, const Allocation *alloc,
+                          uint32_t xoff, uint32_t lod, size_t count, void *data,
+                          size_t sizeBytes) {
+  const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
+  const uint8_t *ptr =
+      GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+  if (data != ptr) {
+    // Skip the copy if we are the same allocation. This can arise from
+    // our Bitmap optimization, where we share the same storage.
+    memcpy(data, ptr, count * eSize);
+  }
+}
+
+void rsovAllocationRead2D(const Context *rsc, const Allocation *alloc,
+                          uint32_t xoff, uint32_t yoff, uint32_t lod,
+                          RsAllocationCubemapFace face, uint32_t w, uint32_t h,
+                          void *data, size_t sizeBytes, size_t stride) {
+  size_t eSize = alloc->mHal.state.elementSizeBytes;
+  size_t lineSize = eSize * w;
+  if (!stride) {
+    stride = lineSize;
+  }
+
+  if (alloc->mHal.drvState.lod[0].mallocPtr) {
+    uint8_t *dst = static_cast<uint8_t *>(data);
+    const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
+    if (dst == src) {
+      // Skip the copy if we are the same allocation. This can arise from
+      // our Bitmap optimization, where we share the same storage.
+      return;
+    }
+
+    for (uint32_t line = yoff; line < (yoff + h); line++) {
+      memcpy(dst, src, lineSize);
+      dst += stride;
+      src += alloc->mHal.drvState.lod[lod].stride;
+    }
+  } else {
+    ALOGE("Add code to readback from non-script memory");
+  }
+}
+
+void rsovAllocationRead3D(const Context *rsc, const Allocation *alloc,
+                          uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                          uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
+                          void *data, size_t sizeBytes, size_t stride) {
+  uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+  uint32_t lineSize = eSize * w;
+  if (!stride) {
+    stride = lineSize;
+  }
+
+  if (alloc->mHal.drvState.lod[0].mallocPtr) {
+    uint8_t *dst = static_cast<uint8_t *>(data);
+    for (uint32_t z = zoff; z < (d + zoff); z++) {
+      const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
+                                        RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+      if (dst == src) {
+        // Skip the copy if we are the same allocation. This can arise from
+        // our Bitmap optimization, where we share the same storage.
+        return;
+      }
+
+      for (uint32_t line = yoff; line < (yoff + h); line++) {
+        memcpy(dst, src, lineSize);
+        dst += stride;
+        src += alloc->mHal.drvState.lod[lod].stride;
+      }
+    }
+  }
+}
+
+void *rsovAllocationLock1D(const Context *rsc, const Allocation *alloc) {
+  return alloc->mHal.drvState.lod[0].mallocPtr;
+}
+
+void rsovAllocationUnlock1D(const Context *rsc, const Allocation *alloc) {}
+
+void rsovAllocationData1D_alloc(const Context *rsc, const Allocation *dstAlloc,
+                                uint32_t dstXoff, uint32_t dstLod, size_t count,
+                                const Allocation *srcAlloc, uint32_t srcXoff,
+                                uint32_t srcLod) {}
+
+void rsovAllocationData2D_alloc_script(
+    const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+    uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
+    uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
+  size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
+  for (uint32_t i = 0; i < h; i++) {
+    uint8_t *dstPtr =
+        GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
+    uint8_t *srcPtr =
+        GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
+    memcpy(dstPtr, srcPtr, w * elementSize);
+  }
+}
+
+void rsovAllocationData3D_alloc_script(
+    const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
+    uint32_t d, const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff,
+    uint32_t srcZoff, uint32_t srcLod) {
+  uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
+  for (uint32_t j = 0; j < d; j++) {
+    for (uint32_t i = 0; i < h; i++) {
+      uint8_t *dstPtr =
+          GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, dstLod,
+                       RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+      uint8_t *srcPtr =
+          GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, srcLod,
+                       RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+      memcpy(dstPtr, srcPtr, w * elementSize);
+    }
+  }
+}
+
+void rsovAllocationData2D_alloc(
+    const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+    uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
+    uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
+  if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
+    rsc->setError(RS_ERROR_FATAL_DRIVER,
+                  "Non-script allocation copies not "
+                  "yet implemented.");
+    return;
+  }
+  rsovAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstLod,
+                                    dstFace, w, h, srcAlloc, srcXoff, srcYoff,
+                                    srcLod, srcFace);
+}
+
+void rsovAllocationData3D_alloc(const Context *rsc, const Allocation *dstAlloc,
+                                uint32_t dstXoff, uint32_t dstYoff,
+                                uint32_t dstZoff, uint32_t dstLod, uint32_t w,
+                                uint32_t h, uint32_t d,
+                                const Allocation *srcAlloc, uint32_t srcXoff,
+                                uint32_t srcYoff, uint32_t srcZoff,
+                                uint32_t srcLod) {
+  if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
+    rsc->setError(RS_ERROR_FATAL_DRIVER,
+                  "Non-script allocation copies not "
+                  "yet implemented.");
+    return;
+  }
+  rsovAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
+                                    dstLod, w, h, d, srcAlloc, srcXoff, srcYoff,
+                                    srcZoff, srcLod);
+}
+
+void rsovAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
+  // Get a base pointer to the new LOD
+  const Allocation *base = alloc->mHal.state.baseAlloc;
+  const Type *type = alloc->mHal.state.type;
+  if (base == nullptr) {
+    return;
+  }
+
+  const int lodBias = alloc->mHal.state.originLOD;
+  uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
+  for (uint32_t lod = 0; lod < lodCount; lod++) {
+    alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
+    alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(
+        alloc, alloc->mHal.state.originX, alloc->mHal.state.originY,
+        alloc->mHal.state.originZ, lodBias,
+        (RsAllocationCubemapFace)alloc->mHal.state.originFace);
+  }
+}
+
+bool rsovAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
+// TODO: may need a RSoV Allocation here
+#if 0
+    DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
+    if (!drv) {
+        return false;
+    }
+    alloc->mHal.drv = drv;
+#endif
+  // We need to build an allocation that looks like a subset of the parent
+  // allocation
+  rsovAllocationAdapterOffset(rsc, alloc);
+
+  return true;
+}
+
+void rsovAllocationSyncAll(const Context *rsc, const Allocation *alloc,
+                           RsAllocationUsageType src) {
+  // TODO: anything to do here?
+}
+
+void rsovAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
+  // TODO: anything to do here?
+}
+
+void rsovAllocationResize(const Context *rsc, const Allocation *alloc,
+                          const Type *newType, bool zeroNew) {
+  // TODO: implement this
+  // can this be done without copying, if the new size is greater than the
+  // original?
+}
+
+void rsovAllocationGenerateMipmaps(const Context *rsc,
+                                   const Allocation *alloc) {
+  if (!alloc->mHal.drvState.lod[0].mallocPtr) {
+    return;
+  }
+  uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
+  for (uint32_t face = 0; face < numFaces; face++) {
+    for (uint32_t lod = 0; lod < (alloc->getType()->getLODCount() - 1); lod++) {
+      switch (alloc->getType()->getElement()->getSizeBits()) {
+        case 32:
+          mip8888(alloc, lod, (RsAllocationCubemapFace)face);
+          break;
+        case 16:
+          mip565(alloc, lod, (RsAllocationCubemapFace)face);
+          break;
+        case 8:
+          mip8(alloc, lod, (RsAllocationCubemapFace)face);
+          break;
+      }
+    }
+  }
+}
+
+uint32_t rsovAllocationGrallocBits(const Context *rsc, Allocation *alloc) {
+  return 0;
+}
+
+void rsovAllocationUpdateCachedObject(const Context *rsc,
+                                      const Allocation *alloc,
+                                      rs_allocation *obj) {
+  obj->p = alloc;
+#ifdef __LP64__
+  obj->unused1 = nullptr;
+  obj->unused2 = nullptr;
+  obj->unused3 = nullptr;
+#endif
+}
+
+void rsovAllocationSetSurface(const Context *rsc, Allocation *alloc,
+                              ANativeWindow *nw) {
+  // TODO: implement this
+}
+
+void rsovAllocationIoSend(const Context *rsc, Allocation *alloc) {
+  // TODO: implement this
+}
+
+void rsovAllocationIoReceive(const Context *rsc, Allocation *alloc) {
+  // TODO: implement this
+}
+
+void rsovAllocationElementData(const Context *rsc, const Allocation *alloc,
+                               uint32_t x, uint32_t y, uint32_t z,
+                               const void *data, uint32_t cIdx,
+                               size_t sizeBytes) {
+  uint8_t *ptr =
+      GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+
+  const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
+  ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
+
+  if (alloc->mHal.state.hasReferences) {
+    e->incRefs(data);
+    e->decRefs(ptr);
+  }
+
+  memcpy(ptr, data, sizeBytes);
+}
+
+void rsovAllocationElementRead(const Context *rsc, const Allocation *alloc,
+                               uint32_t x, uint32_t y, uint32_t z, void *data,
+                               uint32_t cIdx, size_t sizeBytes) {
+  uint8_t *ptr =
+      GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+
+  const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
+  ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
+
+  memcpy(data, ptr, sizeBytes);
+}
diff --git a/rsov/driver/rsovAllocation.h b/rsov/driver/rsovAllocation.h
new file mode 100644
index 0000000..edbf7ff
--- /dev/null
+++ b/rsov/driver/rsovAllocation.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_ALLOCATION_H
+#define RSOV_ALLOCATION_H
+
+#include <vulkan/vulkan.h>
+
+#include "rsDefines.h"
+#include "rs_hal.h"
+#include "system/window.h"
+
+namespace android {
+namespace renderscript {
+
+class Allocation;
+class Context;
+class Type;
+
+namespace rsov {
+
+class RSoVContext;
+// Abstraction for a Vulkan Buffer
+class RSoVBuffer {
+ public:
+  RSoVBuffer(RSoVContext *context, size_t bufferSize);
+  ~RSoVBuffer();
+
+  const VkDescriptorBufferInfo *getBufferInfo() const { return &mBufferInfo; }
+  char *getHostPtr() const { return mPtr; }
+
+ private:
+  void InitBuffer(size_t);
+
+  char *mPtr;  // Host pointer to mmapped device memory for the Buffer
+  RSoVContext *mRSoV;
+  VkDevice mDevice;
+
+  VkDeviceMemory mMem;
+  VkBuffer mBuf;
+  VkDescriptorBufferInfo mBufferInfo;
+};
+
+class RSoVAllocation {
+ public:
+  RSoVAllocation(RSoVContext *context, const Type *type, size_t bufferSize);
+  ~RSoVAllocation() { delete mBuffer; }
+
+  const Type *getType() const { return mType; }
+  uint32_t getWidth() const { return mWidth; }
+  uint32_t getHeight() const { return mHeight; }
+  uint32_t getDepth() const { return mDepth; }
+  RSoVBuffer *getBuffer() const { return mBuffer; }
+  char *getHostPtr() const { return mBuffer->getHostPtr(); }
+
+ private:
+  RSoVBuffer *mBuffer;
+  const Type *mType;
+  const uint32_t mWidth;
+  const uint32_t mHeight;
+  const uint32_t mDepth;
+};
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
+
+extern bool rsovAllocationInit(const android::renderscript::Context *rsc,
+                               android::renderscript::Allocation *alloc,
+                               bool forceZero);
+
+extern void rsovAllocationDestroy(const android::renderscript::Context *rsc,
+                                  android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationData1D(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 uint32_t xoff, uint32_t lod, size_t count,
+                                 const void *data, size_t sizeBytes);
+
+extern void rsovAllocationData2D(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 uint32_t xoff, uint32_t yoff, uint32_t lod,
+                                 RsAllocationCubemapFace face, uint32_t w,
+                                 uint32_t h, const void *data, size_t sizeBytes,
+                                 size_t stride);
+
+extern void rsovAllocationData3D(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                                 uint32_t lod, uint32_t w, uint32_t h,
+                                 uint32_t d, const void *data, size_t sizeBytes,
+                                 size_t stride);
+
+extern void rsovAllocationRead1D(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 uint32_t xoff, uint32_t lod, size_t count,
+                                 void *data, size_t sizeBytes);
+
+extern void rsovAllocationRead2D(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 uint32_t xoff, uint32_t yoff, uint32_t lod,
+                                 RsAllocationCubemapFace face, uint32_t w,
+                                 uint32_t h, void *data, size_t sizeBytes,
+                                 size_t stride);
+
+extern void rsovAllocationRead3D(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                                 uint32_t lod, uint32_t w, uint32_t h,
+                                 uint32_t d, void *data, size_t sizeBytes,
+                                 size_t stride);
+
+extern void *rsovAllocationLock1D(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationUnlock1D(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationData1D_alloc(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstLod, size_t count,
+    const android::renderscript::Allocation *srcAlloc, uint32_t srcXoff,
+    uint32_t srcLod);
+
+extern void rsovAllocationData2D_alloc_script(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+    uint32_t w, uint32_t h, const android::renderscript::Allocation *srcAlloc,
+    uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+    RsAllocationCubemapFace srcFace);
+
+extern void rsovAllocationData2D_alloc(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+    uint32_t w, uint32_t h, const android::renderscript::Allocation *srcAlloc,
+    uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+    RsAllocationCubemapFace srcFace);
+
+extern void rsovAllocationData3D_alloc_script(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
+    uint32_t d, const android::renderscript::Allocation *srcAlloc,
+    uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod);
+
+extern void rsovAllocationData3D_alloc(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+    uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
+    uint32_t d, const android::renderscript::Allocation *srcAlloc,
+    uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod);
+
+extern void rsovAllocationAdapterOffset(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc);
+
+extern bool rsovAllocationAdapterInit(const android::renderscript::Context *rsc,
+                                      android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationSyncAll(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc, RsAllocationUsageType src);
+
+extern void rsovAllocationMarkDirty(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationResize(const android::renderscript::Context *rsc,
+                                 const android::renderscript::Allocation *alloc,
+                                 const android::renderscript::Type *newType,
+                                 bool zeroNew);
+
+extern void rsovAllocationGenerateMipmaps(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc);
+
+extern uint32_t rsovAllocationGrallocBits(
+    const android::renderscript::Context *rsc,
+    android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationUpdateCachedObject(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc,
+    android::renderscript::rs_allocation *obj);
+
+extern void rsovAllocationSetSurface(const android::renderscript::Context *rsc,
+                                     android::renderscript::Allocation *alloc,
+                                     ANativeWindow *nw);
+
+extern void rsovAllocationIoSend(const android::renderscript::Context *rsc,
+                                 android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationIoReceive(const android::renderscript::Context *rsc,
+                                    android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationElementData(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc, uint32_t x, uint32_t y,
+    uint32_t z, const void *data, uint32_t cIdx, size_t sizeBytes);
+
+extern void rsovAllocationElementRead(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Allocation *alloc, uint32_t x, uint32_t y,
+    uint32_t z, void *data, uint32_t cIdx, size_t sizeBytes);
+
+#endif  // RSOV_ALLOCATION_H
diff --git a/rsov/driver/rsovContext.cpp b/rsov/driver/rsovContext.cpp
new file mode 100644
index 0000000..4aba017
--- /dev/null
+++ b/rsov/driver/rsovContext.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovContext.h"
+
+#include <vector>
+
+#include "rsUtils.h"
+
+namespace android {
+namespace renderscript {
+namespace rsov {
+
+RSoVContext* RSoVContext::mContext = nullptr;
+std::once_flag RSoVContext::mInitFlag;
+
+bool RSoVContext::Initialize(char const* const name) {
+  // Initialize instance
+  VkApplicationInfo appInfo = {
+      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+      .pNext = nullptr,
+      .pApplicationName = name,  // TODO: set to app name
+      .applicationVersion = 1,
+      .pEngineName = name,
+      .engineVersion = 1,
+      .apiVersion = VK_API_VERSION_1_0};
+
+  VkInstanceCreateInfo instInfo = {
+      .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+      .pNext = nullptr,
+      .flags = 0,
+      .pApplicationInfo = &appInfo,
+  };
+
+  VkResult res;
+  res = vkCreateInstance(&instInfo, nullptr, &mInstance);
+  if (res != VK_SUCCESS) {
+    return false;
+  }
+
+  // Enumerate devices
+  uint32_t gpu_count;
+
+  res = vkEnumeratePhysicalDevices(mInstance, &gpu_count, nullptr);
+  if (gpu_count == 0) {
+    return false;
+  }
+
+  std::vector<VkPhysicalDevice> GPUs(gpu_count);
+
+  res = vkEnumeratePhysicalDevices(mInstance, &gpu_count, GPUs.data());
+  if (!(res == VK_SUCCESS && gpu_count > 0)) {
+    return false;
+  }
+
+  mGPU = GPUs[0];
+
+  // Get device memory properties
+  vkGetPhysicalDeviceMemoryProperties(mGPU, &mMemoryProperties);
+
+  // Initialize device
+
+  float queuePriorities[] = {0.0};
+
+  VkDeviceQueueCreateInfo queueInfo = {
+      .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+      .pNext = nullptr,
+      .queueCount = 1,
+      .pQueuePriorities = queuePriorities,
+  };
+
+  VkDeviceCreateInfo deviceInfo = {
+      .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+      .pNext = nullptr,
+      .queueCreateInfoCount = 1,
+      .pQueueCreateInfos = &queueInfo,
+      .pEnabledFeatures = nullptr,
+  };
+
+  res = vkCreateDevice(mGPU, &deviceInfo, nullptr, &mDevice);
+  if (res != VK_SUCCESS) {
+    return false;
+  }
+
+  // Initialize queue family index
+  uint32_t queueCount;
+
+  vkGetPhysicalDeviceQueueFamilyProperties(mGPU, &queueCount, nullptr);
+  if (queueCount == 0) {
+    return false;
+  }
+
+  std::vector<VkQueueFamilyProperties> queueProps(queueCount);
+
+  vkGetPhysicalDeviceQueueFamilyProperties(mGPU, &queueCount,
+                                           queueProps.data());
+  if (queueCount == 0) {
+    return false;
+  }
+
+  uint32_t queueFamilyIndex = UINT_MAX;
+  bool found = false;
+  for (unsigned int i = 0; i < queueCount; i++) {
+    if (queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+      queueFamilyIndex = i;
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    return false;
+  }
+
+  // Create a device queue
+
+  vkGetDeviceQueue(mDevice, queueFamilyIndex, 0, &mQueue);
+
+  // Create command pool
+
+  VkCommandPoolCreateInfo cmd_pool_info = {
+      .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+      .pNext = nullptr,
+      .queueFamilyIndex = queueFamilyIndex,
+      .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+  };
+
+  res = vkCreateCommandPool(mDevice, &cmd_pool_info, nullptr, &mCmdPool);
+  if (res != VK_SUCCESS) {
+    return false;
+  }
+
+  return true;
+}
+
+bool RSoVContext::MemoryTypeFromProperties(uint32_t typeBits,
+                                           VkFlags requirements_mask,
+                                           uint32_t* typeIndex) {
+  for (uint32_t i = 0; i < 32; i++) {
+    if ((typeBits & 1) == 1) {
+      const uint32_t prop = mMemoryProperties.memoryTypes[i].propertyFlags;
+      if ((prop & requirements_mask) == requirements_mask) {
+        *typeIndex = i;
+        return true;
+      }
+    }
+    typeBits >>= 1;
+  }
+
+  return false;
+}
+
+RSoVContext::RSoVContext() {}
+
+RSoVContext::~RSoVContext() {}
+
+RSoVContext* RSoVContext::create() {
+  std::call_once(mInitFlag, []() {
+    std::unique_ptr<RSoVContext> context(new RSoVContext());
+    char engineName[] = "RSoV";
+
+    if (context && context->Initialize(engineName)) {
+      mContext = context.release();
+    }
+  });
+  return mContext;
+}
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
diff --git a/rsov/driver/rsovContext.h b/rsov/driver/rsovContext.h
new file mode 100644
index 0000000..8c933cf
--- /dev/null
+++ b/rsov/driver/rsovContext.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_CONTEXT_H
+#define RSOV_CONTEXT_H
+
+#include <vulkan/vulkan.h>
+#include <mutex>
+
+namespace android {
+namespace renderscript {
+
+namespace rsov {
+
+class RSoVContext {
+ public:
+  static RSoVContext* create();
+  ~RSoVContext();
+
+  VkDevice getDevice() const { return mDevice; }
+  VkQueue getQueue() const { return mQueue; }
+  VkCommandPool getCmdPool() const { return mCmdPool; }
+
+  bool MemoryTypeFromProperties(uint32_t typeBits, VkFlags requirements_mask,
+                                uint32_t* typeIndex);
+
+ private:
+  RSoVContext();
+
+  bool Initialize(char const* const name);
+
+  static RSoVContext* mContext;
+  static std::once_flag mInitFlag;
+
+  VkInstance mInstance;
+  VkPhysicalDevice mGPU;
+  VkDevice mDevice;
+  VkPhysicalDeviceMemoryProperties mMemoryProperties;
+  VkQueue mQueue;
+  VkCommandPool mCmdPool;
+};
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
+
+#endif  // RSOV_CONTEXT_H
diff --git a/rsov/driver/rsovCore.cpp b/rsov/driver/rsovCore.cpp
new file mode 100644
index 0000000..123930e
--- /dev/null
+++ b/rsov/driver/rsovCore.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovCore.h"
+
+#include <malloc.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+
+#include "cpu_ref/rsd_cpu.h"
+#include "rsContext.h"
+#include "rsovAllocation.h"
+#include "rsovContext.h"
+#include "rsovElement.h"
+#include "rsovSampler.h"
+#include "rsovScript.h"
+#include "rsovScriptGroup.h"
+#include "rsovType.h"
+
+namespace android {
+namespace renderscript {
+
+namespace {
+
+void SetPriority(const Context *rsc, int32_t priority) {
+  RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+
+  dc->mCpuRef->setPriority(priority);
+}
+
+void Shutdown(Context *rsc) {
+  RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+  delete dc->mCpuRef;
+  free(dc);
+  rsc->mHal.drv = nullptr;
+}
+
+void *AllocRuntimeMem(size_t size, uint32_t flags) {
+    void* buffer = calloc(size, sizeof(char));
+    return buffer;
+}
+
+void FreeRuntimeMem(void* ptr) {
+    free(ptr);
+}
+
+const RsdCpuReference::CpuSymbol *lookupRuntimeStubs(
+    Context *pContext, char const *name) {
+  return nullptr;
+}
+
+}  // anonymous namespace
+
+namespace rsov {
+
+namespace {
+
+RsdCpuReference::CpuScript *lookupCpuScript(Context *rsc, const Script *s) {
+  if (RSoVScript::isScriptCpuBacked(s)) {
+    return reinterpret_cast<RsdCpuReference::CpuScript *>(s->mHal.drv);
+  }
+
+  RSoVScript *rsovScript = reinterpret_cast<RSoVScript *>(s->mHal.drv);
+  return rsovScript->getCpuScript();
+}
+
+}  // anonymous namespace
+
+}  // namespace rsov
+
+
+extern "C" bool rsdHalQueryHal(RsHalInitEnums entry, void **fnPtr) {
+  switch (entry) {
+    case RS_HAL_ALLOCATION_INIT:
+      fnPtr[0] = (void *)rsovAllocationInit;
+      break;
+    case RS_HAL_ALLOCATION_INIT_OEM:
+      fnPtr[0] = (void *)nullptr;
+      break;
+    case RS_HAL_ALLOCATION_INIT_ADAPTER:
+      fnPtr[0] = (void *)rsovAllocationAdapterInit;
+      break;
+    case RS_HAL_ALLOCATION_DESTROY:
+      fnPtr[0] = (void *)rsovAllocationDestroy;
+      break;
+    case RS_HAL_ALLOCATION_GET_GRALLOC_BITS:
+      fnPtr[0] = (void *)rsovAllocationGrallocBits;
+      break;
+    case RS_HAL_ALLOCATION_DATA_1D:
+      fnPtr[0] = (void *)rsovAllocationData1D;
+      break;
+    case RS_HAL_ALLOCATION_DATA_2D:
+      fnPtr[0] = (void *)rsovAllocationData2D;
+      break;
+    case RS_HAL_ALLOCATION_DATA_3D:
+      fnPtr[0] = (void *)rsovAllocationData3D;
+      break;
+    case RS_HAL_ALLOCATION_READ_1D:
+      fnPtr[0] = (void *)rsovAllocationRead1D;
+      break;
+    case RS_HAL_ALLOCATION_READ_2D:
+      fnPtr[0] = (void *)rsovAllocationRead2D;
+      break;
+    case RS_HAL_ALLOCATION_READ_3D:
+      fnPtr[0] = (void *)rsovAllocationRead3D;
+      break;
+    case RS_HAL_ALLOCATION_LOCK_1D:
+      fnPtr[0] = (void *)rsovAllocationLock1D;
+      break;
+    case RS_HAL_ALLOCATION_UNLOCK_1D:
+      fnPtr[0] = (void *)rsovAllocationUnlock1D;
+      break;
+    case RS_HAL_ALLOCATION_COPY_1D:
+      fnPtr[0] = (void *)rsovAllocationData1D_alloc;
+      break;
+    case RS_HAL_ALLOCATION_COPY_2D:
+      fnPtr[0] = (void *)rsovAllocationData2D_alloc;
+      break;
+    case RS_HAL_ALLOCATION_COPY_3D:
+      fnPtr[0] = (void *)rsovAllocationData3D_alloc;
+      break;
+    case RS_HAL_ALLOCATION_ADAPTER_OFFSET:
+      fnPtr[0] = (void *)rsovAllocationAdapterOffset;
+      break;
+    case RS_HAL_ALLOCATION_RESIZE:
+      fnPtr[0] = (void *)rsovAllocationResize;
+      break;
+    case RS_HAL_ALLOCATION_SYNC_ALL:
+      fnPtr[0] = (void *)rsovAllocationSyncAll;
+      break;
+    case RS_HAL_ALLOCATION_MARK_DIRTY:
+      fnPtr[0] = (void *)rsovAllocationMarkDirty;
+      break;
+    case RS_HAL_ALLOCATION_GENERATE_MIPMAPS:
+      fnPtr[0] = (void *)rsovAllocationGenerateMipmaps;
+      break;
+    case RS_HAL_ALLOCATION_UPDATE_CACHED_OBJECT:
+      fnPtr[0] = (void *)rsovAllocationUpdateCachedObject;
+      break;
+    case RS_HAL_ALLOCATION_GET_POINTER:
+      fnPtr[0] = (void *)nullptr;
+      break;
+    case RS_HAL_ALLOCATION_SET_SURFACE:
+      fnPtr[0] = (void *)rsovAllocationSetSurface;
+      break;
+    case RS_HAL_ALLOCATION_IO_SEND:
+      fnPtr[0] = (void *)rsovAllocationIoSend;
+      break;
+    case RS_HAL_ALLOCATION_IO_RECEIVE:
+      fnPtr[0] = (void *)rsovAllocationIoReceive;
+      break;
+    case RS_HAL_ALLOCATION_ELEMENT_DATA:
+      fnPtr[0] = (void *)rsovAllocationElementData;
+      break;
+    case RS_HAL_ALLOCATION_ELEMENT_READ:
+      fnPtr[0] = (void *)rsovAllocationElementRead;
+      break;
+
+    case RS_HAL_CORE_SHUTDOWN:
+      fnPtr[0] = (void *)Shutdown;
+      break;
+    case RS_HAL_CORE_SET_PRIORITY:
+      fnPtr[0] = (void *)SetPriority;
+      break;
+    case RS_HAL_CORE_ALLOC_RUNTIME_MEM:
+      fnPtr[0] = (void *)AllocRuntimeMem;
+      break;
+    case RS_HAL_CORE_FREE_RUNTIME_MEM:
+      fnPtr[0] = (void *)FreeRuntimeMem;
+      break;
+    case RS_HAL_CORE_FINISH:
+      fnPtr[0] = (void *)nullptr;
+      break;
+
+    case RS_HAL_SCRIPT_INIT:
+      fnPtr[0] = (void *)rsovScriptInit;
+      break;
+    case RS_HAL_SCRIPT_INIT_INTRINSIC:
+      fnPtr[0] = (void *)rsovInitIntrinsic;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_FUNCTION:
+      fnPtr[0] = (void *)rsovScriptInvokeFunction;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_ROOT:
+      fnPtr[0] = (void *)rsovScriptInvokeRoot;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_FOR_EACH:
+      fnPtr[0] = (void *)rsovScriptInvokeForEach;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_INIT:
+      fnPtr[0] = (void *)rsovScriptInvokeInit;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_FREE_CHILDREN:
+      fnPtr[0] = (void *)rsovScriptInvokeFreeChildren;
+      break;
+    case RS_HAL_SCRIPT_DESTROY:
+      fnPtr[0] = (void *)rsovScriptDestroy;
+      break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_VAR:
+      fnPtr[0] = (void *)rsovScriptSetGlobalVar;
+      break;
+    case RS_HAL_SCRIPT_GET_GLOBAL_VAR:
+      fnPtr[0] = (void *)rsovScriptGetGlobalVar;
+      break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_VAR_WITH_ELEMENT_DIM:
+      fnPtr[0] = (void *)rsovScriptSetGlobalVarWithElemDims;
+      break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_BIND:
+      fnPtr[0] = (void *)rsovScriptSetGlobalBind;
+      break;
+    case RS_HAL_SCRIPT_SET_GLOBAL_OBJECT:
+      fnPtr[0] = (void *)rsovScriptSetGlobalObj;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_FOR_EACH_MULTI:
+      fnPtr[0] = (void *)rsovScriptInvokeForEachMulti;
+      break;
+    case RS_HAL_SCRIPT_UPDATE_CACHED_OBJECT:
+      fnPtr[0] = (void *)rsovScriptUpdateCachedObject;
+      break;
+    case RS_HAL_SCRIPT_INVOKE_REDUCE:
+      fnPtr[0] = (void *)rsovScriptInvokeReduce;
+      break;
+
+    case RS_HAL_SAMPLER_INIT:
+      fnPtr[0] = (void *)rsovSamplerInit;
+      break;
+    case RS_HAL_SAMPLER_DESTROY:
+      fnPtr[0] = (void *)rsovSamplerDestroy;
+      break;
+    case RS_HAL_SAMPLER_UPDATE_CACHED_OBJECT:
+      fnPtr[0] = (void *)rsovSamplerUpdateCachedObject;
+      break;
+
+    case RS_HAL_TYPE_INIT:
+      fnPtr[0] = (void *)rsovTypeInit;
+      break;
+    case RS_HAL_TYPE_DESTROY:
+      fnPtr[0] = (void *)rsovTypeDestroy;
+      break;
+    case RS_HAL_TYPE_UPDATE_CACHED_OBJECT:
+      fnPtr[0] = (void *)rsovTypeUpdateCachedObject;
+      break;
+
+    case RS_HAL_ELEMENT_INIT:
+      fnPtr[0] = (void *)rsovElementInit;
+      break;
+    case RS_HAL_ELEMENT_DESTROY:
+      fnPtr[0] = (void *)rsovElementDestroy;
+      break;
+    case RS_HAL_ELEMENT_UPDATE_CACHED_OBJECT:
+      fnPtr[0] = (void *)rsovElementUpdateCachedObject;
+      break;
+
+    case RS_HAL_SCRIPT_GROUP_INIT:
+      fnPtr[0] = (void *)rsovScriptGroupInit;
+      break;
+    case RS_HAL_SCRIPT_GROUP_DESTROY:
+      fnPtr[0] = (void *)rsovScriptGroupDestroy;
+      break;
+    case RS_HAL_SCRIPT_GROUP_UPDATE_CACHED_OBJECT:
+      fnPtr[0] = (void *)nullptr;
+      break;
+    case RS_HAL_SCRIPT_GROUP_SET_INPUT:
+      fnPtr[0] = (void *)rsovScriptGroupSetInput;
+      break;
+    case RS_HAL_SCRIPT_GROUP_SET_OUTPUT:
+      fnPtr[0] = (void *)rsovScriptGroupSetOutput;
+      break;
+    case RS_HAL_SCRIPT_GROUP_EXECUTE:
+      fnPtr[0] = (void *)rsovScriptGroupExecute;
+      break;
+
+    // Ignore entries for the legacy graphics api,
+
+    default:
+      ALOGE("ERROR: unknown RenderScript HAL API query, %i", entry);
+      return false;
+  }
+
+  return true;
+}
+
+extern "C" void rsdHalAbort(RsContext) {}
+
+extern "C" bool rsdHalQueryVersion(uint32_t *major, uint32_t *minor) {
+  *major = RS_HAL_VERSION;
+  *minor = 0;
+  return true;
+}
+
+extern "C" bool rsdHalInit(RsContext c, uint32_t version_major,
+                           uint32_t version_minor) {
+  Context *rsc = (Context *)c;
+
+  std::unique_ptr<RSoVHal> hal(new RSoVHal());
+  if (!hal) {
+    ALOGE("Failed creating RSoV driver hal.");
+    return false;
+  }
+
+  std::unique_ptr<rsov::RSoVContext> rsov(rsov::RSoVContext::create());
+  if (!rsov) {
+    ALOGE("RSoVContext::create for driver hal failed.");
+    return false;
+  }
+
+  std::unique_ptr<RsdCpuReference> cpuref(RsdCpuReference::create(rsc, version_major, version_minor,
+                                                                  &lookupRuntimeStubs,
+                                                                  &rsov::lookupCpuScript));
+  if (!cpuref) {
+    ALOGE("RsdCpuReference::create for driver hal failed.");
+    return false;
+  }
+
+  hal->mRSoV = rsov.release();
+  hal->mCpuRef = cpuref.release();
+  rsc->mHal.drv = hal.release();
+
+  return true;
+}
+
+}  // namespace renderscript
+}  // namespace android
diff --git a/rsov/driver/rsovCore.h b/rsov/driver/rsovCore.h
new file mode 100644
index 0000000..d0c160d
--- /dev/null
+++ b/rsov/driver/rsovCore.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_CORE_H
+#define RSOV_CORE_H
+
+namespace android {
+namespace renderscript {
+
+class RsdCpuReference;
+
+namespace rsov {
+
+class RSoVContext;
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
+
+struct RSoVHal {
+  android::renderscript::rsov::RSoVContext* mRSoV;
+  android::renderscript::RsdCpuReference *mCpuRef;
+};
+
+#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
+
+#endif
diff --git a/rsov/driver/rsovElement.cpp b/rsov/driver/rsovElement.cpp
new file mode 100644
index 0000000..114e4e3
--- /dev/null
+++ b/rsov/driver/rsovElement.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsElement.h"
+
+using android::renderscript::Context;
+using android::renderscript::Element;
+using android::renderscript::rs_element;
+
+bool rsovElementInit(const Context *rsc, const Element *e) { return true; }
+
+void rsovElementDestroy(const Context *rsc, const Element *e) {}
+
+void rsovElementUpdateCachedObject(const Context *rsc, const Element *element,
+                                   rs_element *obj) {
+  obj->p = element;
+#ifdef __LP64__
+  obj->unused1 = nullptr;
+  obj->unused2 = nullptr;
+  obj->unused3 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovElement.h b/rsov/driver/rsovElement.h
new file mode 100644
index 0000000..e3d46bc
--- /dev/null
+++ b/rsov/driver/rsovElement.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_ELEMENT_H
+#define RSOV_ELEMENT_H
+
+#include "rs_hal.h"
+
+extern bool rsovElementInit(const android::renderscript::Context *rsc,
+                            const android::renderscript::Element *);
+
+extern void rsovElementDestroy(const android::renderscript::Context *rsc,
+                               const android::renderscript::Element *);
+
+extern void rsovElementUpdateCachedObject(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Element *,
+    android::renderscript::rs_element *obj);
+
+#endif  // RSOV_ELEMENT_H
diff --git a/rsov/driver/rsovRuntimeStubs.cpp b/rsov/driver/rsovRuntimeStubs.cpp
new file mode 100644
index 0000000..2aa7798
--- /dev/null
+++ b/rsov/driver/rsovRuntimeStubs.cpp
@@ -0,0 +1,1148 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <time.h>
+
+#include "rsContext.h"
+#include "rsElement.h"
+#include "rsMatrix2x2.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix4x4.h"
+#include "rsRuntime.h"
+#include "rsScriptC.h"
+#include "rsType.h"
+#include "rsovAllocation.h"
+#include "rsovCore.h"
+#include "rsovScript.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+typedef __fp16 half;
+typedef half half2 __attribute__((ext_vector_type(2)));
+typedef half half3 __attribute__((ext_vector_type(3)));
+typedef half half4 __attribute__((ext_vector_type(4)));
+
+typedef float float2 __attribute__((ext_vector_type(2)));
+typedef float float3 __attribute__((ext_vector_type(3)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double double3 __attribute__((ext_vector_type(3)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+typedef char char2 __attribute__((ext_vector_type(2)));
+typedef char char3 __attribute__((ext_vector_type(3)));
+typedef char char4 __attribute__((ext_vector_type(4)));
+typedef unsigned char uchar2 __attribute__((ext_vector_type(2)));
+typedef unsigned char uchar3 __attribute__((ext_vector_type(3)));
+typedef unsigned char uchar4 __attribute__((ext_vector_type(4)));
+typedef int16_t short2 __attribute__((ext_vector_type(2)));
+typedef int16_t short3 __attribute__((ext_vector_type(3)));
+typedef int16_t short4 __attribute__((ext_vector_type(4)));
+typedef uint16_t ushort2 __attribute__((ext_vector_type(2)));
+typedef uint16_t ushort3 __attribute__((ext_vector_type(3)));
+typedef uint16_t ushort4 __attribute__((ext_vector_type(4)));
+typedef int32_t int2 __attribute__((ext_vector_type(2)));
+typedef int32_t int3 __attribute__((ext_vector_type(3)));
+typedef int32_t int4 __attribute__((ext_vector_type(4)));
+typedef uint32_t uint2 __attribute__((ext_vector_type(2)));
+typedef uint32_t uint3 __attribute__((ext_vector_type(3)));
+typedef uint32_t uint4 __attribute__((ext_vector_type(4)));
+typedef int64_t long2 __attribute__((ext_vector_type(2)));
+typedef int64_t long3 __attribute__((ext_vector_type(3)));
+typedef int64_t long4 __attribute__((ext_vector_type(4)));
+typedef uint64_t ulong2 __attribute__((ext_vector_type(2)));
+typedef uint64_t ulong3 __attribute__((ext_vector_type(3)));
+typedef uint64_t ulong4 __attribute__((ext_vector_type(4)));
+
+typedef uint8_t uchar;
+typedef uint16_t ushort;
+typedef uint32_t uint;
+typedef uint64_t ulong;
+
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#ifndef __LP64__
+#define OPAQUETYPE(t)   \
+  typedef struct {      \
+    const int *const p; \
+  } __attribute__((packed, aligned(4))) t; /*NOLINT*/
+#else
+#define OPAQUETYPE(t)     \
+  typedef struct {        \
+    const void *p;        \
+    const void *unused1;  \
+    const void *unused2;  \
+    const void *unused3;  \
+  } t; /*NOLINT*/
+#endif
+
+OPAQUETYPE(rs_element)
+OPAQUETYPE(rs_type)
+OPAQUETYPE(rs_allocation)
+OPAQUETYPE(rs_sampler)
+OPAQUETYPE(rs_script)
+OPAQUETYPE(rs_script_call)
+
+OPAQUETYPE(rs_program_fragment);
+OPAQUETYPE(rs_program_store);
+OPAQUETYPE(rs_program_vertex);
+OPAQUETYPE(rs_program_raster);
+OPAQUETYPE(rs_mesh);
+OPAQUETYPE(rs_font);
+
+#undef OPAQUETYPE
+
+typedef enum {
+  // Empty to avoid conflicting definitions with RsAllocationCubemapFace
+} rs_allocation_cubemap_face;
+
+typedef enum {
+  // Empty to avoid conflicting definitions with RsYuvFormat
+} rs_yuv_format;
+
+typedef enum {
+  // Empty to avoid conflicting definitions with RsAllocationMipmapControl
+} rs_allocation_mipmap_control;
+
+typedef struct { unsigned int val; } rs_allocation_usage_type;
+
+typedef struct {
+  int tm_sec;    ///< seconds
+  int tm_min;    ///< minutes
+  int tm_hour;   ///< hours
+  int tm_mday;   ///< day of the month
+  int tm_mon;    ///< month
+  int tm_year;   ///< year
+  int tm_wday;   ///< day of the week
+  int tm_yday;   ///< day of the year
+  int tm_isdst;  ///< daylight savings time
+} rs_tm;
+
+// Some RS functions are not threadsafe but can be called from an invoke
+// function.  Instead of summarily marking scripts that call these functions as
+// not-threadable we detect calls to them in the driver and sends a fatal error
+// message.
+static bool failIfInKernel(Context *rsc, const char *funcName) {
+  RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+  RsdCpuReference *impl = (RsdCpuReference *)dc->mCpuRef;
+
+  if (impl->getInKernel()) {
+    char buf[256];
+    snprintf(buf, sizeof(buf),
+             "Error: Call to unsupported function %s "
+             "in kernel",
+             funcName);
+    rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
+    return true;
+  }
+  return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Allocation routines
+//////////////////////////////////////////////////////////////////////////////
+#if defined(__i386__) || (defined(__mips__) && __mips == 32)
+// i386 and MIPS32 have different struct return passing to ARM; emulate with a
+// pointer
+const Allocation *rsGetAllocation(const void *ptr) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  const Script *sc = RsdCpuReference::getTlsScript();
+  Allocation *alloc = rsovScriptGetAllocationForPointer(rsc, sc, ptr);
+  android::renderscript::rs_allocation obj = {0};
+  alloc->callUpdateCacheObject(rsc, &obj);
+  return (Allocation *)obj.p;
+}
+#else
+const android::renderscript::rs_allocation rsGetAllocation(const void *ptr) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  const Script *sc = RsdCpuReference::getTlsScript();
+  Allocation *alloc = rsovScriptGetAllocationForPointer(rsc, sc, ptr);
+
+#ifndef __LP64__  // ARMv7
+  android::renderscript::rs_allocation obj = {0};
+#else             // AArch64/x86_64/MIPS64
+  android::renderscript::rs_allocation obj = {0, 0, 0, 0};
+#endif
+  alloc->callUpdateCacheObject(rsc, &obj);
+  return obj;
+}
+#endif
+
+void __attribute__((overloadable)) rsAllocationIoSend(::rs_allocation a) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  if (failIfInKernel(rsc, "rsAllocationIoSend")) return;
+  rsrAllocationIoSend(rsc, (Allocation *)a.p);
+}
+
+void __attribute__((overloadable)) rsAllocationIoReceive(::rs_allocation a) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  if (failIfInKernel(rsc, "rsAllocationIoReceive")) return;
+  rsrAllocationIoReceive(rsc, (Allocation *)a.p);
+}
+
+void __attribute__((overloadable))
+rsAllocationCopy1DRange(::rs_allocation dstAlloc, uint32_t dstOff,
+                        uint32_t dstMip, uint32_t count,
+                        ::rs_allocation srcAlloc, uint32_t srcOff,
+                        uint32_t srcMip) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  if (failIfInKernel(rsc, "rsAllocationCopy1DRange")) return;
+  rsrAllocationCopy1DRange(rsc, (Allocation *)dstAlloc.p, dstOff, dstMip, count,
+                           (Allocation *)srcAlloc.p, srcOff, srcMip);
+}
+
+void __attribute__((overloadable))
+rsAllocationCopy2DRange(::rs_allocation dstAlloc, uint32_t dstXoff,
+                        uint32_t dstYoff, uint32_t dstMip,
+                        rs_allocation_cubemap_face dstFace, uint32_t width,
+                        uint32_t height, ::rs_allocation srcAlloc,
+                        uint32_t srcXoff, uint32_t srcYoff, uint32_t srcMip,
+                        rs_allocation_cubemap_face srcFace) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  if (failIfInKernel(rsc, "rsAllocationCopy2DRange")) return;
+  rsrAllocationCopy2DRange(
+      rsc, (Allocation *)dstAlloc.p, dstXoff, dstYoff, dstMip, dstFace, width,
+      height, (Allocation *)srcAlloc.p, srcXoff, srcYoff, srcMip, srcFace);
+}
+
+static android::renderscript::rs_element CreateElement(RsDataType dt,
+                                                       RsDataKind dk,
+                                                       bool isNormalized,
+                                                       uint32_t vecSize) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+
+  // No need for validation here.  The rsCreateElement overload below is not
+  // exposed to the Script.  The Element-creation APIs call this function in a
+  // consistent manner and rsComponent.cpp asserts on any inconsistency.
+  Element *element =
+      (Element *)rsrElementCreate(rsc, dt, dk, isNormalized, vecSize);
+  android::renderscript::rs_element obj = {};
+  if (element == nullptr) return obj;
+  element->callUpdateCacheObject(rsc, &obj);
+
+  // Any new rsObject created from inside a script should have the usrRefCount
+  // initialized to 0 and the sysRefCount initialized to 1.
+  element->incSysRef();
+  element->decUserRef();
+
+  return obj;
+}
+
+static android::renderscript::rs_type CreateType(RsElement element,
+                                                 uint32_t dimX, uint32_t dimY,
+                                                 uint32_t dimZ, bool mipmaps,
+                                                 bool faces,
+                                                 uint32_t yuv_format) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  android::renderscript::rs_type obj = {};
+
+  if (element == nullptr) {
+    ALOGE("rs_type creation error: Invalid element");
+    return obj;
+  }
+
+  // validate yuv_format
+  RsYuvFormat yuv = (RsYuvFormat)yuv_format;
+  if (yuv != RS_YUV_NONE && yuv != RS_YUV_YV12 && yuv != RS_YUV_NV21 &&
+      yuv != RS_YUV_420_888) {
+    ALOGE("rs_type creation error: Invalid yuv_format %d\n", yuv_format);
+    return obj;
+  }
+
+  // validate consistency of shape parameters
+  if (dimZ > 0) {
+    if (dimX < 1 || dimY < 1) {
+      ALOGE(
+          "rs_type creation error: Both X and Y dimension required "
+          "when Z is present.");
+      return obj;
+    }
+    if (mipmaps) {
+      ALOGE("rs_type creation error: mipmap control requires 2D types");
+      return obj;
+    }
+    if (faces) {
+      ALOGE("rs_type creation error: Cube maps require 2D types");
+      return obj;
+    }
+  }
+  if (dimY > 0 && dimX < 1) {
+    ALOGE(
+        "rs_type creation error: X dimension required when Y is "
+        "present.");
+    return obj;
+  }
+  if (mipmaps && dimY < 1) {
+    ALOGE("rs_type creation error: mipmap control require 2D Types.");
+    return obj;
+  }
+  if (faces && dimY < 1) {
+    ALOGE("rs_type creation error: Cube maps require 2D Types.");
+    return obj;
+  }
+  if (yuv_format != RS_YUV_NONE) {
+    if (dimZ != 0 || dimY == 0 || faces || mipmaps) {
+      ALOGE("rs_type creation error: YUV only supports basic 2D.");
+      return obj;
+    }
+  }
+
+  Type *type = (Type *)rsrTypeCreate(rsc, element, dimX, dimY, dimZ, mipmaps,
+                                     faces, yuv_format);
+  if (type == nullptr) return obj;
+  type->callUpdateCacheObject(rsc, &obj);
+
+  // Any new rsObject created from inside a script should have the usrRefCount
+  // initialized to 0 and the sysRefCount initialized to 1.
+  type->incSysRef();
+  type->decUserRef();
+
+  return obj;
+}
+
+static android::renderscript::rs_allocation CreateAllocation(
+    RsType type, RsAllocationMipmapControl mipmaps, uint32_t usages,
+    void *ptr) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  android::renderscript::rs_allocation obj = {};
+
+  if (type == nullptr) {
+    ALOGE("rs_allocation creation error: Invalid type");
+    return obj;
+  }
+
+  uint32_t validUsages =
+      RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
+  if (usages & ~validUsages) {
+    ALOGE("rs_allocation creation error: Invalid usage flag");
+    return obj;
+  }
+
+  Allocation *alloc = (Allocation *)rsrAllocationCreateTyped(
+      rsc, type, mipmaps, usages, (uintptr_t)ptr);
+  if (alloc == nullptr) return obj;
+  alloc->callUpdateCacheObject(rsc, &obj);
+
+  // Any new rsObject created from inside a script should have the usrRefCount
+  // initialized to 0 and the sysRefCount initialized to 1.
+  alloc->incSysRef();
+  alloc->decUserRef();
+
+  return obj;
+}
+
+// Define rsCreateElement, rsCreateType and rsCreateAllocation entry points
+// differently for 32-bit x86 and Mips.  The definitions for ARM32 and all
+// 64-bit architectures is further below.
+#if defined(__i386__) || (defined(__mips__) && __mips == 32)
+
+// The calling convention for the driver on 32-bit x86 and Mips returns
+// rs_element etc. as a stack-return parameter.  The Script uses ARM32 calling
+// conventions that return the structs in a register.  To match this convention,
+// emulate the return value using a pointer.
+Element *rsCreateElement(int32_t dt, int32_t dk, bool isNormalized,
+                         uint32_t vecSize) {
+  android::renderscript::rs_element obj =
+      CreateElement((RsDataType)dt, (RsDataKind)dk, isNormalized, vecSize);
+  return (Element *)obj.p;
+}
+
+Type *rsCreateType(::rs_element element, uint32_t dimX, uint32_t dimY,
+                   uint32_t dimZ, bool mipmaps, bool faces,
+                   rs_yuv_format yuv_format) {
+  android::renderscript::rs_type obj =
+      CreateType((RsElement)element.p, dimX, dimY, dimZ, mipmaps, faces,
+                 (RsYuvFormat)yuv_format);
+  return (Type *)obj.p;
+}
+
+Allocation *rsCreateAllocation(::rs_type type,
+                               rs_allocation_mipmap_control mipmaps,
+                               uint32_t usages, void *ptr) {
+  android::renderscript::rs_allocation obj;
+  obj = CreateAllocation((RsType)type.p, (RsAllocationMipmapControl)mipmaps,
+                         usages, ptr);
+  return (Allocation *)obj.p;
+}
+
+#else
+android::renderscript::rs_element rsCreateElement(int32_t dt, int32_t dk,
+                                                  bool isNormalized,
+                                                  uint32_t vecSize) {
+  return CreateElement((RsDataType)dt, (RsDataKind)dk, isNormalized, vecSize);
+}
+
+android::renderscript::rs_type rsCreateType(::rs_element element, uint32_t dimX,
+                                            uint32_t dimY, uint32_t dimZ,
+                                            bool mipmaps, bool faces,
+                                            rs_yuv_format yuv_format) {
+  return CreateType((RsElement)element.p, dimX, dimY, dimZ, mipmaps, faces,
+                    yuv_format);
+}
+
+android::renderscript::rs_allocation rsCreateAllocation(
+    ::rs_type type, rs_allocation_mipmap_control mipmaps, uint32_t usages,
+    void *ptr) {
+  return CreateAllocation((RsType)type.p, (RsAllocationMipmapControl)mipmaps,
+                          usages, ptr);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Object routines
+//////////////////////////////////////////////////////////////////////////////
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#define IS_CLEAR_SET_OBJ(t)                                                  \
+  bool rsIsObject(t src) { return src.p != nullptr; }                        \
+  void __attribute__((overloadable)) rsClearObject(t *dst) { /*NOLINT*/      \
+    rsrClearObject(reinterpret_cast<rs_object_base *>(dst));                 \
+  }                                                                          \
+  void __attribute__((overloadable)) rsSetObject(t *dst, t src) { /*NOLINT*/ \
+    Context *rsc = RsdCpuReference::getTlsContext();                         \
+    rsrSetObject(rsc, reinterpret_cast<rs_object_base *>(dst),               \
+                 (ObjectBase *)src.p);                                       \
+  }
+
+IS_CLEAR_SET_OBJ(::rs_element)
+IS_CLEAR_SET_OBJ(::rs_type)
+IS_CLEAR_SET_OBJ(::rs_allocation)
+IS_CLEAR_SET_OBJ(::rs_sampler)
+IS_CLEAR_SET_OBJ(::rs_script)
+
+IS_CLEAR_SET_OBJ(::rs_mesh)
+IS_CLEAR_SET_OBJ(::rs_program_fragment)
+IS_CLEAR_SET_OBJ(::rs_program_vertex)
+IS_CLEAR_SET_OBJ(::rs_program_raster)
+IS_CLEAR_SET_OBJ(::rs_program_store)
+IS_CLEAR_SET_OBJ(::rs_font)
+
+#undef IS_CLEAR_SET_OBJ
+
+//////////////////////////////////////////////////////////////////////////////
+// Element routines
+//////////////////////////////////////////////////////////////////////////////
+static void *ElementAt(Allocation *a, RsDataType dt, uint32_t vecSize,
+                       uint32_t x, uint32_t y, uint32_t z) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  const Type *t = a->getType();
+  const Element *e = t->getElement();
+
+  char buf[256];
+  if (x && (x >= t->getLODDimX(0))) {
+    snprintf(buf, sizeof(buf), "Out range ElementAt X %i of %i", x,
+             t->getLODDimX(0));
+    rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+    return nullptr;
+  }
+
+  if (y && (y >= t->getLODDimY(0))) {
+    snprintf(buf, sizeof(buf), "Out range ElementAt Y %i of %i", y,
+             t->getLODDimY(0));
+    rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+    return nullptr;
+  }
+
+  if (z && (z >= t->getLODDimZ(0))) {
+    snprintf(buf, sizeof(buf), "Out range ElementAt Z %i of %i", z,
+             t->getLODDimZ(0));
+    rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+    return nullptr;
+  }
+
+  if (vecSize > 0) {
+    if (vecSize != e->getVectorSize()) {
+      snprintf(buf, sizeof(buf), "Vector size mismatch for ElementAt %i of %i",
+               vecSize, e->getVectorSize());
+      rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+      return nullptr;
+    }
+
+    if (dt != e->getType()) {
+      snprintf(buf, sizeof(buf), "Data type mismatch for ElementAt %i of %i",
+               dt, e->getType());
+      rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+      return nullptr;
+    }
+  }
+
+  uint8_t *p = (uint8_t *)a->mHal.drvState.lod[0].mallocPtr;
+  const uint32_t eSize = e->getSizeBytes();
+  const uint32_t stride = a->mHal.drvState.lod[0].stride;
+  const uint32_t dimY = a->mHal.drvState.lod[0].dimY;
+  return &p[(x * eSize) + (y * stride) + (z * stride * dimY)];
+}
+
+void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x, uint32_t y,
+                    uint32_t z) {
+  const Type *t = const_cast<Allocation *>((Allocation *)a.p)->getType();
+  const Element *e = t->getElement();
+  void *tmp = ElementAt((Allocation *)a.p, RS_TYPE_UNSIGNED_8, 0, x, y, z);
+  if (tmp != nullptr) memcpy(tmp, ptr, e->getSizeBytes());
+}
+
+void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x,
+                    uint32_t y) {
+  rsSetElementAt(a, ptr, x, y, 0);
+}
+
+void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x) {
+  rsSetElementAt(a, ptr, x, 0, 0);
+}
+
+const void *rsGetElementAt(::rs_allocation a, uint32_t x, uint32_t y,
+                           uint32_t z) {
+  return ElementAt((Allocation *)a.p, RS_TYPE_UNSIGNED_8, 0, x, y, z);
+}
+
+const void *rsGetElementAt(::rs_allocation a, uint32_t x, uint32_t y) {
+  return rsGetElementAt(a, x, y, 0);
+}
+
+const void *rsGetElementAt(::rs_allocation a, uint32_t x) {
+  return rsGetElementAt(a, x, 0, 0);
+}
+
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#define ELEMENT_AT(T, DT, VS)                                                 \
+  void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x,        \
+                          uint32_t y, uint32_t z) {                           \
+    void *r = ElementAt((Allocation *)a.p, DT, VS, x, y, z);                  \
+    if (r != nullptr)                                                         \
+      ((T *)r)[0] = *val;                                                     \
+    else                                                                      \
+      ALOGE("Error from %s", __PRETTY_FUNCTION__);                            \
+  }                                                                           \
+  void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x,        \
+                          uint32_t y) {                                       \
+    rsSetElementAt_##T(a, val, x, y, 0);                                      \
+  }                                                                           \
+  void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x) {      \
+    rsSetElementAt_##T(a, val, x, 0, 0);                                      \
+  }                                                                           \
+  void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x, uint32_t y,  \
+                          uint32_t z) { /*NOLINT*/                            \
+    void *r = ElementAt((Allocation *)a.p, DT, VS, x, y, z);                  \
+    if (r != nullptr)                                                         \
+      *val = ((T *)r)[0];                                                     \
+    else                                                                      \
+      ALOGE("Error from %s", __PRETTY_FUNCTION__);                            \
+  }                                                                           \
+  void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x,              \
+                          uint32_t y) { /*NOLINT*/                            \
+    rsGetElementAt_##T(a, val, x, y, 0);                                      \
+  }                                                                           \
+  void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x) { /*NOLINT*/ \
+    rsGetElementAt_##T(a, val, x, 0, 0);                                      \
+  }
+
+ELEMENT_AT(char, RS_TYPE_SIGNED_8, 1)
+ELEMENT_AT(char2, RS_TYPE_SIGNED_8, 2)
+ELEMENT_AT(char3, RS_TYPE_SIGNED_8, 3)
+ELEMENT_AT(char4, RS_TYPE_SIGNED_8, 4)
+ELEMENT_AT(uchar, RS_TYPE_UNSIGNED_8, 1)
+ELEMENT_AT(uchar2, RS_TYPE_UNSIGNED_8, 2)
+ELEMENT_AT(uchar3, RS_TYPE_UNSIGNED_8, 3)
+ELEMENT_AT(uchar4, RS_TYPE_UNSIGNED_8, 4)
+ELEMENT_AT(short, RS_TYPE_SIGNED_16, 1)
+ELEMENT_AT(short2, RS_TYPE_SIGNED_16, 2)
+ELEMENT_AT(short3, RS_TYPE_SIGNED_16, 3)
+ELEMENT_AT(short4, RS_TYPE_SIGNED_16, 4)
+ELEMENT_AT(ushort, RS_TYPE_UNSIGNED_16, 1)
+ELEMENT_AT(ushort2, RS_TYPE_UNSIGNED_16, 2)
+ELEMENT_AT(ushort3, RS_TYPE_UNSIGNED_16, 3)
+ELEMENT_AT(ushort4, RS_TYPE_UNSIGNED_16, 4)
+ELEMENT_AT(int, RS_TYPE_SIGNED_32, 1)
+ELEMENT_AT(int2, RS_TYPE_SIGNED_32, 2)
+ELEMENT_AT(int3, RS_TYPE_SIGNED_32, 3)
+ELEMENT_AT(int4, RS_TYPE_SIGNED_32, 4)
+ELEMENT_AT(uint, RS_TYPE_UNSIGNED_32, 1)
+ELEMENT_AT(uint2, RS_TYPE_UNSIGNED_32, 2)
+ELEMENT_AT(uint3, RS_TYPE_UNSIGNED_32, 3)
+ELEMENT_AT(uint4, RS_TYPE_UNSIGNED_32, 4)
+ELEMENT_AT(long, RS_TYPE_SIGNED_64, 1)
+ELEMENT_AT(long2, RS_TYPE_SIGNED_64, 2)
+ELEMENT_AT(long3, RS_TYPE_SIGNED_64, 3)
+ELEMENT_AT(long4, RS_TYPE_SIGNED_64, 4)
+ELEMENT_AT(ulong, RS_TYPE_UNSIGNED_64, 1)
+ELEMENT_AT(ulong2, RS_TYPE_UNSIGNED_64, 2)
+ELEMENT_AT(ulong3, RS_TYPE_UNSIGNED_64, 3)
+ELEMENT_AT(ulong4, RS_TYPE_UNSIGNED_64, 4)
+ELEMENT_AT(half, RS_TYPE_FLOAT_16, 1)
+ELEMENT_AT(half2, RS_TYPE_FLOAT_16, 2)
+ELEMENT_AT(half3, RS_TYPE_FLOAT_16, 3)
+ELEMENT_AT(half4, RS_TYPE_FLOAT_16, 4)
+ELEMENT_AT(float, RS_TYPE_FLOAT_32, 1)
+ELEMENT_AT(float2, RS_TYPE_FLOAT_32, 2)
+ELEMENT_AT(float3, RS_TYPE_FLOAT_32, 3)
+ELEMENT_AT(float4, RS_TYPE_FLOAT_32, 4)
+ELEMENT_AT(double, RS_TYPE_FLOAT_64, 1)
+ELEMENT_AT(double2, RS_TYPE_FLOAT_64, 2)
+ELEMENT_AT(double3, RS_TYPE_FLOAT_64, 3)
+ELEMENT_AT(double4, RS_TYPE_FLOAT_64, 4)
+
+#undef ELEMENT_AT
+
+#ifndef __LP64__
+/*
+ * We miss some symbols for rs{Get,Set}Element_long,ulong variants because 64
+ * bit integer values are 'long' in RS-land but might be 'long long' in the
+ * driver.  Define native_long* and native_ulong* types to be vectors of
+ * 'long' as seen by the driver and define overloaded versions of
+ * rsSetElementAt_* and rsGetElementAt_*.  This should get us the correct
+ * mangled names in the driver.
+ */
+
+typedef long native_long2 __attribute__((ext_vector_type(2)));
+typedef long native_long3 __attribute__((ext_vector_type(3)));
+typedef long native_long4 __attribute__((ext_vector_type(4)));
+typedef unsigned long native_ulong2 __attribute__((ext_vector_type(2)));
+typedef unsigned long native_ulong3 __attribute__((ext_vector_type(3)));
+typedef unsigned long native_ulong4 __attribute__((ext_vector_type(4)));
+
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#define ELEMENT_AT_OVERLOADS(T, U)                                            \
+  void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x,        \
+                          uint32_t y, uint32_t z) {                           \
+    rsSetElementAt_##T(a, (T *)val, x, y, z);                                 \
+  }                                                                           \
+  void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x,        \
+                          uint32_t y) {                                       \
+    rsSetElementAt_##T(a, (T *)val, x, y, 0);                                 \
+  }                                                                           \
+  void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x) {      \
+    rsSetElementAt_##T(a, (T *)val, x, 0, 0);                                 \
+  }                                                                           \
+  void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x, uint32_t y,  \
+                          uint32_t z) { /*NOLINT*/                            \
+    rsGetElementAt_##T(a, (T *)val, x, y, z);                                 \
+  }                                                                           \
+  void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x,              \
+                          uint32_t y) { /*NOLINT*/                            \
+    rsGetElementAt_##T(a, (T *)val, x, y, 0);                                 \
+  }                                                                           \
+  void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x) { /*NOLINT*/ \
+    rsGetElementAt_##T(a, (T *)val, x, 0, 0);                                 \
+  }
+
+ELEMENT_AT_OVERLOADS(long2, native_long2)
+ELEMENT_AT_OVERLOADS(long3, native_long3)
+ELEMENT_AT_OVERLOADS(long4, native_long4)
+ELEMENT_AT_OVERLOADS(ulong, unsigned long)
+ELEMENT_AT_OVERLOADS(ulong2, native_ulong2)
+ELEMENT_AT_OVERLOADS(ulong3, native_ulong3)
+ELEMENT_AT_OVERLOADS(ulong4, native_ulong4)
+
+// We also need variants of rs{Get,Set}ElementAt_long that take 'long long *' as
+// we might have this overloaded variant in old APKs.
+ELEMENT_AT_OVERLOADS(long, long long)
+
+#undef ELEMENT_AT_OVERLOADS
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// ForEach routines
+//////////////////////////////////////////////////////////////////////////////
+void rsForEachInternal(int slot, rs_script_call *options, int hasOutput,
+                       int numInputs, ::rs_allocation *allocs) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  Script *s = const_cast<Script *>(RsdCpuReference::getTlsScript());
+  if (numInputs > RS_KERNEL_MAX_ARGUMENTS) {
+    rsc->setError(RS_ERROR_BAD_SCRIPT,
+                  "rsForEachInternal: too many inputs to a kernel.");
+    return;
+  }
+  Allocation *inputs[RS_KERNEL_MAX_ARGUMENTS];
+  for (int i = 0; i < numInputs; i++) {
+    inputs[i] = (Allocation *)allocs[i].p;
+  }
+  Allocation *out = hasOutput ? (Allocation *)allocs[numInputs].p : nullptr;
+  rsrForEach(rsc, s, slot, numInputs, numInputs > 0 ? inputs : nullptr, out,
+             nullptr, 0, (RsScriptCall *)options);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+          const void *usr, const rs_script_call *call) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+             (Allocation *)out.p, usr, 0, (RsScriptCall *)call);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+          const void *usr) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+             (Allocation *)out.p, usr, 0, nullptr);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+             (Allocation *)out.p, nullptr, 0, nullptr);
+}
+
+// These functions are only supported in 32-bit.
+#ifndef __LP64__
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+          const void *usr, uint32_t usrLen) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+             (Allocation *)out.p, usr, usrLen, nullptr);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+          const void *usr, uint32_t usrLen, const rs_script_call *call) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+             (Allocation *)out.p, usr, usrLen, (RsScriptCall *)call);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Message routines
+//////////////////////////////////////////////////////////////////////////////
+uint32_t rsSendToClient(int cmdID) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrToClient(rsc, cmdID, (const void *)nullptr, 0);
+}
+
+uint32_t rsSendToClient(int cmdID, const void *data, uint32_t len) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrToClient(rsc, cmdID, data, len);
+}
+
+uint32_t rsSendToClientBlocking(int cmdID) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrToClientBlocking(rsc, cmdID, (const void *)nullptr, 0);
+}
+
+uint32_t rsSendToClientBlocking(int cmdID, const void *data, uint32_t len) {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrToClientBlocking(rsc, cmdID, data, len);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Time routines
+//////////////////////////////////////////////////////////////////////////////
+
+// time_t is int in 32-bit RenderScript.  time_t is long in bionic.  rsTime and
+// rsLocaltime are set to explicitly take 'const int *' so we generate the
+// correct mangled names.
+#ifndef __LP64__
+int rsTime(int *timer) {
+#else
+time_t rsTime(time_t *timer) {
+#endif
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrTime(rsc, (time_t *)timer);
+}
+
+#ifndef __LP64__
+rs_tm *rsLocaltime(rs_tm *local, const int *timer) {
+#else
+rs_tm *rsLocaltime(rs_tm *local, const time_t *timer) {
+#endif
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return (rs_tm *)rsrLocalTime(rsc, (tm *)local, (time_t *)timer);
+}
+
+int64_t rsUptimeMillis() {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrUptimeMillis(rsc);
+}
+
+int64_t rsUptimeNanos() {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  return rsrUptimeNanos(rsc);
+}
+
+float rsGetDt() {
+  Context *rsc = RsdCpuReference::getTlsContext();
+  const Script *sc = RsdCpuReference::getTlsScript();
+  return rsrGetDt(rsc, sc);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Debug routines
+//////////////////////////////////////////////////////////////////////////////
+void rsDebug(const char *s, float f) {
+  ALOGD("%s %f, 0x%08x", s, f, *((int *)(&f)));
+}
+
+void rsDebug(const char *s, float f1, float f2) {
+  ALOGD("%s {%f, %f}", s, f1, f2);
+}
+
+void rsDebug(const char *s, float f1, float f2, float f3) {
+  ALOGD("%s {%f, %f, %f}", s, f1, f2, f3);
+}
+
+void rsDebug(const char *s, float f1, float f2, float f3, float f4) {
+  ALOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4);
+}
+
+void rsDebug(const char *s, const float2 *f2) {
+  float2 f = *f2;
+  ALOGD("%s {%f, %f}", s, f.x, f.y);
+}
+
+void rsDebug(const char *s, const float3 *f3) {
+  float3 f = *f3;
+  ALOGD("%s {%f, %f, %f}", s, f.x, f.y, f.z);
+}
+
+void rsDebug(const char *s, const float4 *f4) {
+  float4 f = *f4;
+  ALOGD("%s {%f, %f, %f, %f}", s, f.x, f.y, f.z, f.w);
+}
+
+// Accept a half value converted to float.  This eliminates the need in the
+// driver to properly support the half datatype (either by adding compiler flags
+// for half or link against compiler_rt).
+void rsDebug(const char *s, float f, ushort us) {
+  ALOGD("%s {%f} {0x%hx}", s, f, us);
+}
+
+void rsDebug(const char *s, const float2 *f2, const ushort2 *us2) {
+  float2 f = *f2;
+  ushort2 us = *us2;
+  ALOGD("%s {%f %f} {0x%hx 0x%hx}", s, f.x, f.y, us.x, us.y);
+}
+
+void rsDebug(const char *s, const float3 *f3, const ushort3 *us3) {
+  float3 f = *f3;
+  ushort3 us = *us3;
+  ALOGD("%s {%f %f %f} {0x%hx 0x%hx 0x%hx}", s, f.x, f.y, f.z, us.x, us.y,
+        us.z);
+}
+
+void rsDebug(const char *s, const float4 *f4, const ushort4 *us4) {
+  float4 f = *f4;
+  ushort4 us = *us4;
+  ALOGD("%s {%f %f %f %f} {0x%hx 0x%hx 0x%hx 0x%hx}", s, f.x, f.y, f.z, f.w,
+        us.x, us.y, us.z, us.w);
+}
+
+void rsDebug(const char *s, double d) {
+  ALOGD("%s %f, 0x%08llx", s, d, *((long long *)(&d)));
+}
+
+void rsDebug(const char *s, const double2 *d2) {
+  double2 d = *d2;
+  ALOGD("%s {%f, %f}", s, d.x, d.y);
+}
+
+void rsDebug(const char *s, const double3 *d3) {
+  double3 d = *d3;
+  ALOGD("%s {%f, %f, %f}", s, d.x, d.y, d.z);
+}
+
+void rsDebug(const char *s, const double4 *d4) {
+  double4 d = *d4;
+  ALOGD("%s {%f, %f, %f, %f}", s, d.x, d.y, d.z, d.w);
+}
+
+void rsDebug(const char *s, const rs_matrix4x4 *m) {
+  float *f = (float *)m;
+  ALOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]);
+  ALOGD("%s  %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]);
+  ALOGD("%s  %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]);
+  ALOGD("%s  %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]);
+}
+
+void rsDebug(const char *s, const rs_matrix3x3 *m) {
+  float *f = (float *)m;
+  ALOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]);
+  ALOGD("%s  %f, %f, %f", s, f[1], f[4], f[7]);
+  ALOGD("%s  %f, %f, %f}", s, f[2], f[5], f[8]);
+}
+
+void rsDebug(const char *s, const rs_matrix2x2 *m) {
+  float *f = (float *)m;
+  ALOGD("%s {%f, %f", s, f[0], f[2]);
+  ALOGD("%s  %f, %f}", s, f[1], f[3]);
+}
+
+void rsDebug(const char *s, char c) {
+  ALOGD("%s %hhd  0x%hhx", s, c, (unsigned char)c);
+}
+
+void rsDebug(const char *s, const char2 *c2) {
+  char2 c = *c2;
+  ALOGD("%s {%hhd, %hhd}  0x%hhx 0x%hhx", s, c.x, c.y, (unsigned char)c.x,
+        (unsigned char)c.y);
+}
+
+void rsDebug(const char *s, const char3 *c3) {
+  char3 c = *c3;
+  ALOGD("%s {%hhd, %hhd, %hhd}  0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y, c.z,
+        (unsigned char)c.x, (unsigned char)c.y, (unsigned char)c.z);
+}
+
+void rsDebug(const char *s, const char4 *c4) {
+  char4 c = *c4;
+  ALOGD("%s {%hhd, %hhd, %hhd, %hhd}  0x%hhx 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y,
+        c.z, c.w, (unsigned char)c.x, (unsigned char)c.y, (unsigned char)c.z,
+        (unsigned char)c.w);
+}
+
+void rsDebug(const char *s, unsigned char c) {
+  ALOGD("%s %hhu  0x%hhx", s, c, c);
+}
+
+void rsDebug(const char *s, const uchar2 *c2) {
+  uchar2 c = *c2;
+  ALOGD("%s {%hhu, %hhu}  0x%hhx 0x%hhx", s, c.x, c.y, c.x, c.y);
+}
+
+void rsDebug(const char *s, const uchar3 *c3) {
+  uchar3 c = *c3;
+  ALOGD("%s {%hhu, %hhu, %hhu}  0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y, c.z, c.x,
+        c.y, c.z);
+}
+
+void rsDebug(const char *s, const uchar4 *c4) {
+  uchar4 c = *c4;
+  ALOGD("%s {%hhu, %hhu, %hhu, %hhu}  0x%hhx 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y,
+        c.z, c.w, c.x, c.y, c.z, c.w);
+}
+
+void rsDebug(const char *s, short c) { ALOGD("%s %hd  0x%hx", s, c, c); }
+
+void rsDebug(const char *s, const short2 *c2) {
+  short2 c = *c2;
+  ALOGD("%s {%hd, %hd}  0x%hx 0x%hx", s, c.x, c.y, c.x, c.y);
+}
+
+void rsDebug(const char *s, const short3 *c3) {
+  short3 c = *c3;
+  ALOGD("%s {%hd, %hd, %hd}  0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z, c.x, c.y,
+        c.z);
+}
+
+void rsDebug(const char *s, const short4 *c4) {
+  short4 c = *c4;
+  ALOGD("%s {%hd, %hd, %hd, %hd}  0x%hx 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z,
+        c.w, c.x, c.y, c.z, c.w);
+}
+
+void rsDebug(const char *s, unsigned short c) {
+  ALOGD("%s %hu  0x%hx", s, c, c);
+}
+
+void rsDebug(const char *s, const ushort2 *c2) {
+  ushort2 c = *c2;
+  ALOGD("%s {%hu, %hu}  0x%hx 0x%hx", s, c.x, c.y, c.x, c.y);
+}
+
+void rsDebug(const char *s, const ushort3 *c3) {
+  ushort3 c = *c3;
+  ALOGD("%s {%hu, %hu, %hu}  0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z, c.x, c.y,
+        c.z);
+}
+
+void rsDebug(const char *s, const ushort4 *c4) {
+  ushort4 c = *c4;
+  ALOGD("%s {%hu, %hu, %hu, %hu}  0x%hx 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z,
+        c.w, c.x, c.y, c.z, c.w);
+}
+
+void rsDebug(const char *s, int i) { ALOGD("%s %d  0x%x", s, i, i); }
+
+void rsDebug(const char *s, const int2 *i2) {
+  int2 i = *i2;
+  ALOGD("%s {%d, %d}  0x%x 0x%x", s, i.x, i.y, i.x, i.y);
+}
+
+void rsDebug(const char *s, const int3 *i3) {
+  int3 i = *i3;
+  ALOGD("%s {%d, %d, %d}  0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.x, i.y, i.z);
+}
+
+void rsDebug(const char *s, const int4 *i4) {
+  int4 i = *i4;
+  ALOGD("%s {%d, %d, %d, %d}  0x%x 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.w, i.x,
+        i.y, i.z, i.w);
+}
+
+void rsDebug(const char *s, unsigned int i) { ALOGD("%s %u  0x%x", s, i, i); }
+
+void rsDebug(const char *s, const uint2 *i2) {
+  uint2 i = *i2;
+  ALOGD("%s {%u, %u}  0x%x 0x%x", s, i.x, i.y, i.x, i.y);
+}
+
+void rsDebug(const char *s, const uint3 *i3) {
+  uint3 i = *i3;
+  ALOGD("%s {%u, %u, %u}  0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.x, i.y, i.z);
+}
+
+void rsDebug(const char *s, const uint4 *i4) {
+  uint4 i = *i4;
+  ALOGD("%s {%u, %u, %u, %u}  0x%x 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.w, i.x,
+        i.y, i.z, i.w);
+}
+
+template <typename T>
+static inline long long LL(const T &x) {
+  return static_cast<long long>(x);
+}
+
+template <typename T>
+static inline unsigned long long LLu(const T &x) {
+  return static_cast<unsigned long long>(x);
+}
+
+void rsDebug(const char *s, long l) {
+  ALOGD("%s %lld  0x%llx", s, LL(l), LL(l));
+}
+
+void rsDebug(const char *s, long long ll) {
+  ALOGD("%s %lld  0x%llx", s, LL(ll), LL(ll));
+}
+
+void rsDebug(const char *s, const long2 *c) {
+  long2 ll = *c;
+  ALOGD("%s {%lld, %lld}  0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
+        LL(ll.y));
+}
+
+void rsDebug(const char *s, const long3 *c) {
+  long3 ll = *c;
+  ALOGD("%s {%lld, %lld, %lld}  0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
+        LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
+}
+
+void rsDebug(const char *s, const long4 *c) {
+  long4 ll = *c;
+  ALOGD("%s {%lld, %lld, %lld, %lld}  0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
+        LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
+}
+
+void rsDebug(const char *s, unsigned long l) {
+  unsigned long long ll = l;
+  ALOGD("%s %llu  0x%llx", s, ll, ll);
+}
+
+void rsDebug(const char *s, unsigned long long ll) {
+  ALOGD("%s %llu  0x%llx", s, ll, ll);
+}
+
+void rsDebug(const char *s, const ulong2 *c) {
+  ulong2 ll = *c;
+  ALOGD("%s {%llu, %llu}  0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
+        LLu(ll.y));
+}
+
+void rsDebug(const char *s, const ulong3 *c) {
+  ulong3 ll = *c;
+  ALOGD("%s {%llu, %llu, %llu}  0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
+        LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
+}
+
+void rsDebug(const char *s, const ulong4 *c) {
+  ulong4 ll = *c;
+  ALOGD("%s {%llu, %llu, %llu, %llu}  0x%llx 0x%llx 0x%llx 0x%llx", s,
+        LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
+        LLu(ll.z), LLu(ll.w));
+}
+
+// FIXME: We need to export these function signatures for the compatibility
+// library. The C++ name mangling that LLVM uses for ext_vector_type requires
+// different versions for "long" vs. "long long". Note that the called
+// functions are still using the appropriate 64-bit sizes.
+
+#ifndef __LP64__
+typedef long l2 __attribute__((ext_vector_type(2)));
+typedef long l3 __attribute__((ext_vector_type(3)));
+typedef long l4 __attribute__((ext_vector_type(4)));
+typedef unsigned long ul2 __attribute__((ext_vector_type(2)));
+typedef unsigned long ul3 __attribute__((ext_vector_type(3)));
+typedef unsigned long ul4 __attribute__((ext_vector_type(4)));
+
+void rsDebug(const char *s, const l2 *c) {
+  long2 ll = *(const long2 *)c;
+  ALOGD("%s {%lld, %lld}  0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
+        LL(ll.y));
+}
+
+void rsDebug(const char *s, const l3 *c) {
+  long3 ll = *(const long3 *)c;
+  ALOGD("%s {%lld, %lld, %lld}  0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
+        LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
+}
+
+void rsDebug(const char *s, const l4 *c) {
+  long4 ll = *(const long4 *)c;
+  ALOGD("%s {%lld, %lld, %lld, %lld}  0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
+        LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
+}
+
+void rsDebug(const char *s, const ul2 *c) {
+  ulong2 ll = *(const ulong2 *)c;
+  ALOGD("%s {%llu, %llu}  0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
+        LLu(ll.y));
+}
+
+void rsDebug(const char *s, const ul3 *c) {
+  ulong3 ll = *(const ulong3 *)c;
+  ALOGD("%s {%llu, %llu, %llu}  0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
+        LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
+}
+
+void rsDebug(const char *s, const ul4 *c) {
+  ulong4 ll = *(const ulong4 *)c;
+  ALOGD("%s {%llu, %llu, %llu, %llu}  0x%llx 0x%llx 0x%llx 0x%llx", s,
+        LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
+        LLu(ll.z), LLu(ll.w));
+}
+#endif
+
+void rsDebug(const char *s, const long2 ll) {
+  ALOGD("%s {%lld, %lld}  0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
+        LL(ll.y));
+}
+
+void rsDebug(const char *s, const long3 ll) {
+  ALOGD("%s {%lld, %lld, %lld}  0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
+        LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
+}
+
+void rsDebug(const char *s, const long4 ll) {
+  ALOGD("%s {%lld, %lld, %lld, %lld}  0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
+        LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
+}
+
+void rsDebug(const char *s, const ulong2 ll) {
+  ALOGD("%s {%llu, %llu}  0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
+        LLu(ll.y));
+}
+
+void rsDebug(const char *s, const ulong3 ll) {
+  ALOGD("%s {%llu, %llu, %llu}  0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
+        LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
+}
+
+void rsDebug(const char *s, const ulong4 ll) {
+  ALOGD("%s {%llu, %llu, %llu, %llu}  0x%llx 0x%llx 0x%llx 0x%llx", s,
+        LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
+        LLu(ll.z), LLu(ll.w));
+}
+
+void rsDebug(const char *s, const void *p) { ALOGD("%s %p", s, p); }
diff --git a/rsov/driver/rsovSampler.cpp b/rsov/driver/rsovSampler.cpp
new file mode 100644
index 0000000..f8d946c
--- /dev/null
+++ b/rsov/driver/rsovSampler.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovSampler.h"
+
+#include "rsContext.h"
+
+using android::renderscript::Context;
+using android::renderscript::Sampler;
+using android::renderscript::rs_sampler;
+
+bool rsovSamplerInit(const Context *rsc, const Sampler *s) { return true; }
+
+void rsovSamplerDestroy(const Context *rsc, const Sampler *s) {}
+
+void rsovSamplerUpdateCachedObject(const Context *rsc, const Sampler *alloc,
+                                   rs_sampler *obj) {
+  obj->p = alloc;
+#ifdef __LP64__
+  obj->unused1 = nullptr;
+  obj->unused2 = nullptr;
+  obj->unused3 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovSampler.h b/rsov/driver/rsovSampler.h
new file mode 100644
index 0000000..9b8112c
--- /dev/null
+++ b/rsov/driver/rsovSampler.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_SAMPLER_H
+#define RSOV_SAMPLER_H
+
+#include "rs_hal.h"
+
+extern bool rsovSamplerInit(const android::renderscript::Context *rsc,
+                            const android::renderscript::Sampler *);
+
+extern void rsovSamplerDestroy(const android::renderscript::Context *rsc,
+                               const android::renderscript::Sampler *);
+
+extern void rsovSamplerUpdateCachedObject(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Sampler *,
+    android::renderscript::rs_sampler *obj);
+
+#endif  // RSD_SAMPLER_H
diff --git a/rsov/driver/rsovScript.cpp b/rsov/driver/rsovScript.cpp
new file mode 100644
index 0000000..d1a6298
--- /dev/null
+++ b/rsov/driver/rsovScript.cpp
@@ -0,0 +1,934 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovScript.h"
+
+#include "bcinfo/MetadataExtractor.h"
+#include "module.h"
+#include "rsContext.h"
+#include "rsDefines.h"
+#include "rsType.h"
+#include "rsUtils.h"
+#include "rsovAllocation.h"
+#include "rsovContext.h"
+#include "rsovCore.h"
+#include "spirit/file_utils.h"
+#include "spirit/instructions.h"
+#include "spirit/module.h"
+
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+extern "C" {
+char*  __GPUBlock = nullptr;
+}
+
+namespace android {
+namespace renderscript {
+namespace rsov {
+
+namespace {
+// Layout of this struct has to be the same as the struct in generated SPIR-V
+// TODO: generate this file from some spec that is shared with the compiler
+struct rsovTypeInfo {
+  uint32_t element_size;  // TODO: not implemented
+  uint32_t x_size;
+  uint32_t y_size;
+  uint32_t z_size;
+};
+
+const char *COMPILER_EXE_PATH = "/system/bin/rs2spirv";
+
+std::vector<const char *> setCompilerArgs(const char *bcFileName,
+                                          const char *cacheDir) {
+  rsAssert(bcFileName && cacheDir);
+
+  std::vector<const char *> args;
+
+  args.push_back(COMPILER_EXE_PATH);
+  args.push_back(bcFileName);
+
+  args.push_back(nullptr);
+  return args;
+}
+
+void writeBytes(const char *filename, const char *bytes, size_t size) {
+  std::ofstream ofs(filename, std::ios::binary);
+  ofs.write(bytes, size);
+  ofs.close();
+}
+
+std::vector<uint32_t> readWords(const char *filename) {
+  std::ifstream ifs(filename, std::ios::binary);
+
+  ifs.seekg(0, ifs.end);
+  int length = ifs.tellg();
+  ifs.seekg(0, ifs.beg);
+
+  rsAssert(((length & 3) == 0) && "File size expected to be multiples of 4");
+
+  std::vector<uint32_t> spvWords(length / sizeof(uint32_t));
+
+  ifs.read((char *)(spvWords.data()), length);
+
+  ifs.close();
+
+  return spvWords;
+}
+
+std::vector<uint32_t> compileBitcode(const char *resName, const char *cacheDir,
+                                     const char *bitcode, size_t bitcodeSize,
+                                     std::vector<uint8_t> &modifiedBitcode) {
+  rsAssert(bitcode && bitcodeSize);
+
+  // TODO: Cache the generated code
+
+  std::string bcFileName(cacheDir);
+  bcFileName.append("/");
+  bcFileName.append(resName);
+  bcFileName.append(".bc");
+
+  writeBytes(bcFileName.c_str(), bitcode, bitcodeSize);
+
+  auto args = setCompilerArgs(bcFileName.c_str(), cacheDir);
+
+  if (!rsuExecuteCommand(COMPILER_EXE_PATH, args.size() - 1, args.data())) {
+    ALOGE("compiler command line failed");
+    return std::vector<uint32_t>();
+  }
+
+  ALOGV("compiler command line succeeded");
+
+  std::string spvFileName(cacheDir);
+  spvFileName.append("/");
+  spvFileName.append(resName);
+  spvFileName.append(".spv");
+
+  std::string modifiedBCFileName(cacheDir);
+  modifiedBCFileName.append("/").append(resName).append("_modified.bc");
+
+  args.pop_back();
+  args.push_back("-bc");
+  args.push_back(modifiedBCFileName.c_str());
+  args.push_back(nullptr);
+
+  if (!rsuExecuteCommand(COMPILER_EXE_PATH, args.size() - 1, args.data())) {
+    ALOGE("compiler command line to create modified bitcode failed");
+    return std::vector<uint32_t>();
+  }
+
+  modifiedBitcode = android::spirit::readFile<uint8_t>(modifiedBCFileName);
+
+  return readWords(spvFileName.c_str());
+}
+
+void splitOffsets(const std::string &str, char delimiter,
+                  std::vector<uint32_t> *offsets) {
+  std::stringstream ss(str);
+  std::string tok;
+
+  while (std::getline(ss, tok, delimiter)) {
+    const uint32_t offset = static_cast<uint32_t>(std::stoi(tok));
+    offsets->push_back(offset);
+  }
+}
+
+}  // anonymous namespace
+
+bool RSoVScript::isScriptCpuBacked(const Script *s) {
+  return s->mHal.info.mVersionMinor == CPU_SCRIPT_MAGIC_NUMBER;
+}
+
+void RSoVScript::initScriptOnCpu(Script *s, RsdCpuReference::CpuScript *cs) {
+  s->mHal.drv = cs;
+  s->mHal.info.mVersionMajor = 0;  // Unused. Don't care.
+  s->mHal.info.mVersionMinor = CPU_SCRIPT_MAGIC_NUMBER;
+}
+
+void RSoVScript::initScriptOnRSoV(Script *s, RSoVScript *rsovScript) {
+  s->mHal.drv = rsovScript;
+  s->mHal.info.mVersionMajor = 0;  // Unused. Don't care.
+  s->mHal.info.mVersionMinor = 0;
+}
+
+using android::spirit::Module;
+using android::spirit::Deserialize;
+
+RSoVScript::RSoVScript(RSoVContext *context, std::vector<uint32_t> &&spvWords,
+                       bcinfo::MetadataExtractor *ME,
+                       std::map<std::string, int> *GA2ID)
+    : mRSoV(context),
+      mDevice(context->getDevice()),
+      mSPIRVWords(std::move(spvWords)),
+      mME(ME),
+      mGlobalAllocationMetadata(nullptr),
+      mGAMapping(GA2ID) {
+  std::unique_ptr<Module> module(Deserialize<Module>(mSPIRVWords));
+
+  const std::string &strGlobalSize =
+      module->findStringOfPrefix(".rsov.GlobalSize:");
+  if (strGlobalSize.empty()) {
+    mGlobals.reset(new RSoVBuffer(context, 4));
+    return;
+  }
+  const size_t colonPosSize = strGlobalSize.find(':');
+  const std::string &strVal = strGlobalSize.substr(colonPosSize + 1);
+  const uint64_t globalSize = static_cast<uint64_t>(std::stol(strVal));
+  if (globalSize > 0) {
+    mGlobals.reset(new RSoVBuffer(context, globalSize));
+    __GPUBlock = mGlobals->getHostPtr();
+    const std::string &offsetStr =
+      module->findStringOfPrefix(".rsov.ExportedVars:");
+    const size_t colonPos = offsetStr.find(':');
+    splitOffsets(offsetStr.substr(colonPos + 1), ';', &mExportedVarOffsets);
+  }
+}
+
+RSoVScript::~RSoVScript() {
+  delete mCpuScript;
+  delete mME;
+}
+
+void RSoVScript::populateScript(Script *) {
+}
+
+void RSoVScript::invokeFunction(uint32_t slot, const void *params,
+                                size_t paramLength) {
+  getCpuScript()->invokeFunction(slot, params, paramLength);
+}
+
+int RSoVScript::invokeRoot() { return getCpuScript()->invokeRoot(); }
+
+void RSoVScript::invokeForEach(uint32_t slot, const Allocation **ains,
+                               uint32_t inLen, Allocation *aout,
+                               const void *usr, uint32_t usrLen,
+                               const RsScriptCall *sc) {
+  // TODO: Handle kernel without input Allocation
+  rsAssert(ains);
+  std::vector<RSoVAllocation *> inputAllocations(inLen);
+  for (uint32_t i = 0; i < inLen; ++i) {
+    inputAllocations[i] = static_cast<RSoVAllocation *>(ains[i]->mHal.drv);
+  }
+  RSoVAllocation *outputAllocation =
+      static_cast<RSoVAllocation *>(aout->mHal.drv);
+  runForEach(slot, inLen, inputAllocations, outputAllocation);
+}
+
+void RSoVScript::invokeReduce(uint32_t slot, const Allocation **ains,
+                              uint32_t inLen, Allocation *aout,
+                              const RsScriptCall *sc) {
+  getCpuScript()->invokeReduce(slot, ains, inLen, aout, sc);
+}
+
+void RSoVScript::invokeInit() {
+  getCpuScript()->invokeInit();
+}
+
+void RSoVScript::invokeFreeChildren() {
+  // TODO: implement this
+}
+
+void RSoVScript::setGlobalVar(uint32_t slot, const void *data,
+                              size_t dataLength) {
+  char *basePtr = mGlobals->getHostPtr();
+  rsAssert(basePtr != nullptr);
+  const uint32_t offset = GetExportedVarOffset(slot);
+  memcpy(basePtr + offset, data, dataLength);
+}
+
+void RSoVScript::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
+  const char *basePtr = mGlobals->getHostPtr();
+  rsAssert(basePtr != nullptr);
+  const uint32_t offset = GetExportedVarOffset(slot);
+  memcpy(data, basePtr + offset, dataLength);
+}
+
+void RSoVScript::setGlobalVarWithElemDims(uint32_t slot, const void *data,
+                                          size_t dataLength, const Element *elem,
+                                          const uint32_t *dims,
+                                          size_t dimLength) {
+  char *basePtr = mGlobals->getHostPtr();
+  rsAssert(basePtr != nullptr);
+  const uint32_t offset = GetExportedVarOffset(slot);
+  char *destPtr = basePtr + offset;
+
+  // We want to look at dimension in terms of integer components,
+  // but dimLength is given in terms of bytes.
+  dimLength /= sizeof(int);
+
+  // Only a single dimension is currently supported.
+  rsAssert(dimLength == 1);
+  if (dimLength != 1) {
+    return;
+  }
+
+  // First do the increment loop.
+  size_t stride = elem->getSizeBytes();
+  const char *cVal = reinterpret_cast<const char *>(data);
+  for (uint32_t i = 0; i < dims[0]; i++) {
+    elem->incRefs(cVal);
+    cVal += stride;
+  }
+
+  // Decrement loop comes after (to prevent race conditions).
+  char *oldVal = destPtr;
+  for (uint32_t i = 0; i < dims[0]; i++) {
+    elem->decRefs(oldVal);
+    oldVal += stride;
+  }
+
+  memcpy(destPtr, data, dataLength);
+}
+
+void RSoVScript::setGlobalBind(uint32_t slot, Allocation *data) {
+  ALOGV("%s succeeded.", __FUNCTION__);
+  // TODO: implement this
+}
+
+void RSoVScript::setGlobalObj(uint32_t slot, ObjectBase *obj) {
+  mCpuScript->setGlobalObj(slot, obj);
+  ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+Allocation *RSoVScript::getAllocationForPointer(const void *ptr) const {
+  // TODO: implement this
+  return nullptr;
+}
+
+int RSoVScript::getGlobalEntries() const {
+  // TODO: implement this
+  return 0;
+}
+
+const char *RSoVScript::getGlobalName(int i) const {
+  // TODO: implement this
+  return nullptr;
+}
+
+const void *RSoVScript::getGlobalAddress(int i) const {
+  // TODO: implement this
+  return nullptr;
+}
+
+size_t RSoVScript::getGlobalSize(int i) const {
+  // TODO: implement this
+  return 0;
+}
+
+uint32_t RSoVScript::getGlobalProperties(int i) const {
+  // TODO: implement this
+  return 0;
+}
+
+void RSoVScript::InitDescriptorAndPipelineLayouts(uint32_t inLen) {
+  // TODO: kernels with zero output allocations
+  std::vector<VkDescriptorSetLayoutBinding> bindings(
+      inLen + 3, {
+                     .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+                     .descriptorCount = 1,
+                     .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+                 });
+  for (uint32_t i = 0; i < inLen + 3; i++) {
+    bindings[i].binding = i;
+  }
+
+  VkDescriptorSetLayoutCreateInfo descriptor_layout = {
+      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+      .pNext = nullptr,
+      .flags = 0,
+      .bindingCount = inLen + 3,
+      .pBindings = bindings.data(),
+  };
+
+  VkResult res;
+
+  mDescLayout.resize(NUM_DESCRIPTOR_SETS);
+  res = vkCreateDescriptorSetLayout(mDevice, &descriptor_layout, NULL,
+                                    mDescLayout.data());
+  rsAssert(res == VK_SUCCESS);
+
+  /* Now use the descriptor layout to create a pipeline layout */
+  VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
+      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+      .pNext = nullptr,
+      .pushConstantRangeCount = 0,
+      .pPushConstantRanges = nullptr,
+      .setLayoutCount = NUM_DESCRIPTOR_SETS,
+      .pSetLayouts = mDescLayout.data(),
+  };
+
+  res = vkCreatePipelineLayout(mDevice, &pPipelineLayoutCreateInfo, NULL,
+                               &mPipelineLayout);
+  rsAssert(res == VK_SUCCESS);
+}
+
+void RSoVScript::InitShader(uint32_t slot) {
+  VkResult res;
+
+  mShaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+  mShaderStage.pNext = nullptr;
+  mShaderStage.pSpecializationInfo = nullptr;
+  mShaderStage.flags = 0;
+  mShaderStage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
+
+  const char **RSKernelNames = mME->getExportForEachNameList();
+  size_t RSKernelNum = mME->getExportForEachSignatureCount();
+  rsAssert(slot < RSKernelNum);
+  rsAssert(RSKernelNames);
+  rsAssert(RSKernelNames[slot]);
+  // ALOGV("slot = %d kernel name = %s", slot, RSKernelNames[slot]);
+  std::string entryName("entry_");
+  entryName.append(RSKernelNames[slot]);
+
+  mShaderStage.pName = strndup(entryName.c_str(), entryName.size());
+
+  VkShaderModuleCreateInfo moduleCreateInfo = {
+      .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+      .pNext = nullptr,
+      .flags = 0,
+      .codeSize = mSPIRVWords.size() * sizeof(unsigned int),
+      .pCode = mSPIRVWords.data(),
+  };
+  res = vkCreateShaderModule(mDevice, &moduleCreateInfo, NULL,
+                             &mShaderStage.module);
+  rsAssert(res == VK_SUCCESS);
+}
+
+void RSoVScript::InitDescriptorPool(uint32_t inLen) {
+  VkResult res;
+  // 1 global buffer, 1 global allocation metadata buffer, 1 output allocation,
+  // and inLen input allocations
+  VkDescriptorPoolSize type_count[] = {{
+      .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = inLen + 3,
+  }};
+
+  VkDescriptorPoolCreateInfo descriptor_pool = {
+      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+      .pNext = nullptr,
+      .maxSets = 1,
+      .poolSizeCount = NELEM(type_count),
+      .pPoolSizes = type_count,
+  };
+
+  res = vkCreateDescriptorPool(mDevice, &descriptor_pool, NULL, &mDescPool);
+  rsAssert(res == VK_SUCCESS);
+}
+
+// Iterate through a list of global allocations that are used inside the module
+// and marshal their type information to a dedicated Vulkan Buffer
+void RSoVScript::MarshalTypeInfo(void) {
+  // Marshal global allocation metadata to the device
+  auto *cs = getCpuScript();
+  int nr_globals = mGAMapping->size();
+  if (mGlobalAllocationMetadata == nullptr) {
+    mGlobalAllocationMetadata.reset(
+        new RSoVBuffer(mRSoV, sizeof(struct rsovTypeInfo) * nr_globals));
+  }
+  struct rsovTypeInfo *mappedMetadata =
+      (struct rsovTypeInfo *)mGlobalAllocationMetadata->getHostPtr();
+  for (int i = 0; i < nr_globals; ++i) {
+    if (getGlobalRsType(cs->getGlobalProperties(i)) ==
+        RsDataType::RS_TYPE_ALLOCATION) {
+      ALOGV("global variable %d is an allocation!", i);
+      const void *host_buf;
+      cs->getGlobalVar(i, (void *)&host_buf, sizeof(host_buf));
+      if (!host_buf) continue;
+      const android::renderscript::Allocation *GA =
+          static_cast<const android::renderscript::Allocation *>(host_buf);
+      const android::renderscript::Type *T = GA->getType();
+      rsAssert(T);
+
+      auto global_it = mGAMapping->find(cs->getGlobalName(i));
+      rsAssert(global_it != (*mGAMapping).end());
+      int id = global_it->second;
+      ALOGV("global allocation %s is mapped to ID %d", cs->getGlobalName(i),
+            id);
+      // TODO: marshal other properties
+      mappedMetadata[id].x_size = T->getDimX();
+      mappedMetadata[id].y_size = T->getDimY();
+      mappedMetadata[id].z_size = T->getDimZ();
+    }
+  }
+}
+
+void RSoVScript::InitDescriptorSet(
+    const std::vector<RSoVAllocation *> &inputAllocations,
+    RSoVAllocation *outputAllocation) {
+  VkResult res;
+
+  VkDescriptorSetAllocateInfo alloc_info = {
+      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+      .pNext = NULL,
+      .descriptorPool = mDescPool,
+      .descriptorSetCount = NUM_DESCRIPTOR_SETS,
+      .pSetLayouts = mDescLayout.data(),
+  };
+
+  mDescSet.resize(NUM_DESCRIPTOR_SETS);
+  res = vkAllocateDescriptorSets(mDevice, &alloc_info, mDescSet.data());
+  rsAssert(res == VK_SUCCESS);
+
+  std::vector<VkWriteDescriptorSet> writes{
+      // Global variables
+      {
+          .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+          .dstSet = mDescSet[0],
+          .dstBinding = 0,
+          .dstArrayElement = 0,
+          .descriptorCount = 1,
+          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+          .pBufferInfo = mGlobals->getBufferInfo(),
+      },
+      // Metadata for global Allocations
+      {
+          .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+          .dstSet = mDescSet[0],
+          .dstBinding = 1,
+          .dstArrayElement = 0,
+          .descriptorCount = 1,
+          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+          .pBufferInfo = mGlobalAllocationMetadata->getBufferInfo(),
+      },
+      // Output Allocation
+      {
+          .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+          .dstSet = mDescSet[0],
+          .dstBinding = 2,
+          .dstArrayElement = 0,
+          .descriptorCount = 1,
+          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+          .pBufferInfo = outputAllocation->getBuffer()->getBufferInfo(),
+      },
+  };
+
+  // Input Allocations
+  for (uint32_t i = 0; i < inputAllocations.size(); ++i) {
+    writes.push_back({
+        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+        .dstSet = mDescSet[0],
+        .dstBinding = 3 + i,  // input allocations start from binding #3
+        .dstArrayElement = 0,
+        .descriptorCount = 1,
+        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+        .pBufferInfo = inputAllocations[i]->getBuffer()->getBufferInfo(),
+    });
+  }
+
+  vkUpdateDescriptorSets(mDevice, writes.size(), writes.data(), 0, NULL);
+}
+
+void RSoVScript::InitPipeline() {
+  // DEPENDS on mShaderStage, i.e., InitShader()
+
+  VkResult res;
+
+  VkComputePipelineCreateInfo pipeline_info = {
+      .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+      .pNext = nullptr,
+      .layout = mPipelineLayout,
+      .basePipelineHandle = VK_NULL_HANDLE,
+      .basePipelineIndex = 0,
+      .flags = 0,
+      .stage = mShaderStage,
+  };
+  res = vkCreateComputePipelines(mDevice, VK_NULL_HANDLE, 1, &pipeline_info,
+                                 NULL, &mComputePipeline);
+  rsAssert(res == VK_SUCCESS);
+}
+
+void RSoVScript::runForEach(
+    uint32_t slot, uint32_t inLen,
+    const std::vector<RSoVAllocation *> &inputAllocations,
+    RSoVAllocation *outputAllocation) {
+  VkResult res;
+
+  InitShader(slot);
+  InitDescriptorPool(inLen);
+  InitDescriptorAndPipelineLayouts(inLen);
+  MarshalTypeInfo();
+  InitDescriptorSet(inputAllocations, outputAllocation);
+  // InitPipelineCache();
+  InitPipeline();
+
+  VkCommandBuffer cmd;
+
+  VkCommandBufferAllocateInfo cmd_info = {
+      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+      .pNext = nullptr,
+      .commandPool = mRSoV->getCmdPool(),
+      .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+      .commandBufferCount = 1,
+  };
+
+  res = vkAllocateCommandBuffers(mDevice, &cmd_info, &cmd);
+  rsAssert(res == VK_SUCCESS);
+
+  VkCommandBufferBeginInfo cmd_buf_info = {
+      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+      .pNext = nullptr,
+      .flags = 0,
+      .pInheritanceInfo = nullptr,
+  };
+
+  res = vkBeginCommandBuffer(cmd, &cmd_buf_info);
+  rsAssert(res == VK_SUCCESS);
+
+  vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, mComputePipeline);
+
+  vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, mPipelineLayout,
+                          0, mDescSet.size(), mDescSet.data(), 0, nullptr);
+  // Assuming all input allocations are of the same dimensionality
+  const uint32_t width = inputAllocations[0]->getWidth();
+  const uint32_t height = rsMax(inputAllocations[0]->getHeight(), 1U);
+  const uint32_t depth = rsMax(inputAllocations[0]->getDepth(), 1U);
+  vkCmdDispatch(cmd, width, height, depth);
+
+  res = vkEndCommandBuffer(cmd);
+  assert(res == VK_SUCCESS);
+
+  VkSubmitInfo submit_info = {
+      .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+      .commandBufferCount = 1,
+      .pCommandBuffers = &cmd,
+  };
+
+  VkFence fence;
+
+  VkFenceCreateInfo fenceInfo = {
+      .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+      .pNext = nullptr,
+      .flags = 0,
+  };
+
+  vkCreateFence(mDevice, &fenceInfo, NULL, &fence);
+
+  vkQueueSubmit(mRSoV->getQueue(), 1, &submit_info, fence);
+
+  // Make sure command buffer is finished
+  do {
+    res = vkWaitForFences(mDevice, 1, &fence, VK_TRUE, 100000);
+  } while (res == VK_TIMEOUT);
+
+  rsAssert(res == VK_SUCCESS);
+
+  vkDestroyFence(mDevice, fence, NULL);
+
+  // TODO: shall we reuse command buffers?
+  VkCommandBuffer cmd_bufs[] = {cmd};
+  vkFreeCommandBuffers(mDevice, mRSoV->getCmdPool(), 1, cmd_bufs);
+
+  vkDestroyPipeline(mDevice, mComputePipeline, nullptr);
+  for (int i = 0; i < NUM_DESCRIPTOR_SETS; i++)
+    vkDestroyDescriptorSetLayout(mDevice, mDescLayout[i], nullptr);
+  vkDestroyPipelineLayout(mDevice, mPipelineLayout, nullptr);
+  vkFreeDescriptorSets(mDevice, mDescPool, NUM_DESCRIPTOR_SETS,
+                       mDescSet.data());
+  vkDestroyDescriptorPool(mDevice, mDescPool, nullptr);
+  free((void *)mShaderStage.pName);
+  vkDestroyShaderModule(mDevice, mShaderStage.module, nullptr);
+}
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
+
+using android::renderscript::Allocation;
+using android::renderscript::Context;
+using android::renderscript::Element;
+using android::renderscript::ObjectBase;
+using android::renderscript::RsdCpuReference;
+using android::renderscript::Script;
+using android::renderscript::ScriptC;
+using android::renderscript::rs_script;
+using android::renderscript::rsov::RSoVContext;
+using android::renderscript::rsov::RSoVScript;
+using android::renderscript::rsov::compileBitcode;
+
+namespace {
+// A class to parse global allocation metadata; essentially a subset of JSON
+// it would look like {"__RSoV_GA": {"g":42}}
+// The result is stored in a refence to a map<string, int>
+class ParseMD {
+ public:
+  ParseMD(std::string s, std::map<std::string, int> &map)
+      : mString(s), mMapping(map) {}
+
+  bool parse(void) {
+    // remove outermose two pairs of braces
+    mString = removeBraces(mString);
+    if (mString.empty()) {
+      return false;
+    }
+
+    mString = removeBraces(mString);
+    if (mString.empty()) {
+      return false;
+    }
+
+    // Now we are supposed to have a comma-separated list that looks like:
+    // "foo":42, "bar":56
+    split<','>(mString, [&](auto s) {
+      split<':'>(s, nullptr, [&](auto pair) {
+        rsAssert(pair.size() == 2);
+        std::string ga_name = removeQuotes(pair[0]);
+        int id = atoi(pair[1].c_str());
+        ALOGV("ParseMD: global allocation %s has ID %d", ga_name.c_str(), id);
+        mMapping[ga_name] = id;
+      });
+    });
+    return true;
+  }
+
+ private:
+  template <char L, char R>
+  static std::string removeMatching(const std::string &s) {
+    auto leftCBrace = s.find(L);
+    if (leftCBrace == std::string::npos) {
+      return "";
+    }
+    leftCBrace++;
+    return s.substr(leftCBrace, s.rfind(R) - leftCBrace);
+  }
+
+  static std::string removeBraces(const std::string &s) {
+    return removeMatching<'{', '}'>(s);
+  }
+
+  static std::string removeQuotes(const std::string &s) {
+    return removeMatching<'"', '"'>(s);
+  }
+
+  // Splitting a string, and call "each" and/or "all" with individal elements
+  // and a vector of all tokenized elements
+  template <char D>
+  static void split(const std::string &s,
+                    std::function<void(const std::string &)> each,
+                    std::function<void(const std::vector<const std::string> &)>
+                        all = nullptr) {
+    std::vector<const std::string> result;
+    for (std::string::size_type pos = 0; pos < s.size(); pos++) {
+      std::string::size_type begin = pos;
+
+      while (pos <= s.size() && s[pos] != D) pos++;
+      std::string found = s.substr(begin, pos - begin);
+      if (each) each(found);
+      if (all) result.push_back(found);
+    }
+    if (all) all(result);
+  }
+
+  std::string mString;
+  std::map<std::string, int> &mMapping;
+};
+
+}  // namespace
+
+class ExtractRSoVMD : public android::spirit::DoNothingVisitor {
+ public:
+  ExtractRSoVMD() : mGAMapping(new std::map<std::string, int>) {}
+
+  void visit(android::spirit::StringInst *s) {
+    ALOGV("ExtractRSoVMD: string = %s", s->mOperand1.c_str());
+    std::map<std::string, int> mapping;
+    ParseMD p(s->mOperand1, mapping);
+    if (p.parse()) {
+      *mGAMapping = std::move(mapping);
+    }
+  }
+
+  std::map<std::string, int> *takeMapping(void) { return mGAMapping.release(); }
+
+ private:
+  std::unique_ptr<std::map<std::string, int> > mGAMapping;
+};
+
+bool rsovScriptInit(const Context *rsc, ScriptC *script, char const *resName,
+                    char const *cacheDir, uint8_t const *bitcode,
+                    size_t bitcodeSize, uint32_t flags) {
+  RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv);
+
+  std::unique_ptr<bcinfo::MetadataExtractor> bitcodeMetadata(
+      new bcinfo::MetadataExtractor((const char *)bitcode, bitcodeSize));
+  if (!bitcodeMetadata || !bitcodeMetadata->extract()) {
+    ALOGE("Could not extract metadata from bitcode from %s", resName);
+    return false;
+  }
+
+  std::vector<uint8_t> modifiedBitcode;
+  auto spvWords =
+    compileBitcode(resName, cacheDir, (const char *)bitcode, bitcodeSize, modifiedBitcode);
+  if (!spvWords.empty() && !modifiedBitcode.empty()) {
+    // Extract compiler metadata on allocation->binding mapping
+    android::spirit::Module *module =
+        android::spirit::Deserialize<android::spirit::Module>(spvWords);
+    rsAssert(module);
+    ExtractRSoVMD ga_md;
+    module->accept(&ga_md);
+
+    RSoVScript *rsovScript =
+        new RSoVScript(hal->mRSoV, std::move(spvWords),
+                       bitcodeMetadata.release(), ga_md.takeMapping());
+    if (rsovScript) {
+      std::string modifiedResName(resName);
+      modifiedResName.append("_modified");
+      RsdCpuReference::CpuScript *cs = hal->mCpuRef->createScript(
+          script, modifiedResName.c_str(), cacheDir, modifiedBitcode.data(),
+          modifiedBitcode.size(), flags);
+      if (cs != nullptr) {
+        cs->populateScript(script);
+        rsovScript->setCpuScript(cs);
+        RSoVScript::initScriptOnRSoV(script, rsovScript);
+        return true;
+      }
+    }
+  }
+
+  ALOGD("Failed creating an RSoV script for %s", resName);
+  // Fall back to CPU driver instead
+
+  std::unique_ptr<RsdCpuReference::CpuScript> cs(hal->mCpuRef->createScript(
+      script, resName, cacheDir, bitcode, bitcodeSize, flags));
+  if (cs == nullptr) {
+    ALOGE("Failed creating a CPU script %p for %s (%p)", cs.get(), resName,
+          script);
+    return false;
+  }
+  cs->populateScript(script);
+
+  RSoVScript::initScriptOnCpu(script, cs.release());
+
+  return true;
+}
+
+bool rsovInitIntrinsic(const Context *rsc, Script *s, RsScriptIntrinsicID iid,
+                       Element *e) {
+  RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+  RsdCpuReference::CpuScript *cs = dc->mCpuRef->createIntrinsic(s, iid, e);
+  if (cs == nullptr) {
+    return false;
+  }
+  s->mHal.drv = cs;
+  cs->populateScript(s);
+  return true;
+}
+
+void rsovScriptInvokeForEach(const Context *rsc, Script *s, uint32_t slot,
+                             const Allocation *ain, Allocation *aout,
+                             const void *usr, size_t usrLen,
+                             const RsScriptCall *sc) {
+  if (ain == nullptr) {
+    rsovScriptInvokeForEachMulti(rsc, s, slot, nullptr, 0, aout, usr, usrLen,
+                                 sc);
+  } else {
+    const Allocation *ains[1] = {ain};
+
+    rsovScriptInvokeForEachMulti(rsc, s, slot, ains, 1, aout, usr, usrLen, sc);
+  }
+}
+
+void rsovScriptInvokeForEachMulti(const Context *rsc, Script *s, uint32_t slot,
+                                  const Allocation **ains, size_t inLen,
+                                  Allocation *aout, const void *usr,
+                                  size_t usrLen, const RsScriptCall *sc) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->invokeForEach(slot, ains, inLen, aout, usr, usrLen, sc);
+}
+
+int rsovScriptInvokeRoot(const Context *dc, Script *s) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  return cs->invokeRoot();
+}
+
+void rsovScriptInvokeInit(const Context *dc, Script *s) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->invokeInit();
+}
+
+void rsovScriptInvokeFreeChildren(const Context *dc, Script *s) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->invokeFreeChildren();
+}
+
+void rsovScriptInvokeFunction(const Context *dc, Script *s, uint32_t slot,
+                              const void *params, size_t paramLength) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->invokeFunction(slot, params, paramLength);
+}
+
+void rsovScriptInvokeReduce(const Context *dc, Script *s, uint32_t slot,
+                            const Allocation **ains, size_t inLen,
+                            Allocation *aout, const RsScriptCall *sc) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->invokeReduce(slot, ains, inLen, aout, sc);
+}
+
+void rsovScriptSetGlobalVar(const Context *dc, const Script *s, uint32_t slot,
+                            void *data, size_t dataLength) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->setGlobalVar(slot, data, dataLength);
+}
+
+void rsovScriptGetGlobalVar(const Context *dc, const Script *s, uint32_t slot,
+                            void *data, size_t dataLength) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->getGlobalVar(slot, data, dataLength);
+}
+
+void rsovScriptSetGlobalVarWithElemDims(
+    const Context *dc, const Script *s, uint32_t slot, void *data,
+    size_t dataLength, const android::renderscript::Element *elem,
+    const uint32_t *dims, size_t dimLength) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->setGlobalVarWithElemDims(slot, data, dataLength, elem, dims, dimLength);
+}
+
+void rsovScriptSetGlobalBind(const Context *dc, const Script *s, uint32_t slot,
+                             Allocation *data) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->setGlobalBind(slot, data);
+}
+
+void rsovScriptSetGlobalObj(const Context *dc, const Script *s, uint32_t slot,
+                            ObjectBase *data) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  cs->setGlobalObj(slot, data);
+}
+
+void rsovScriptDestroy(const Context *dc, Script *s) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+  delete cs;
+  s->mHal.drv = nullptr;
+}
+
+Allocation *rsovScriptGetAllocationForPointer(
+    const android::renderscript::Context *dc,
+    const android::renderscript::Script *sc, const void *ptr) {
+  RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)sc->mHal.drv;
+  return cs->getAllocationForPointer(ptr);
+}
+
+void rsovScriptUpdateCachedObject(const Context *rsc, const Script *script,
+                                  rs_script *obj) {
+  obj->p = script;
+#ifdef __LP64__
+  obj->unused1 = nullptr;
+  obj->unused2 = nullptr;
+  obj->unused3 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovScript.h b/rsov/driver/rsovScript.h
new file mode 100644
index 0000000..1300621
--- /dev/null
+++ b/rsov/driver/rsovScript.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_SCRIPT_H
+#define RSOV_SCRIPT_H
+
+#include <vulkan/vulkan.h>
+
+#include <map>
+#include <vector>
+
+#include "bcinfo/MetadataExtractor.h"
+#include "rsDefines.h"
+#include "rs_hal.h"
+#include "rsd_cpu.h"
+
+namespace android {
+namespace renderscript {
+
+class Allocation;
+class Context;
+class Element;
+class Script;
+class ScriptC;
+
+namespace rsov {
+
+class RSoVAllocation;
+class RSoVBuffer;
+class RSoVContext;
+
+// TODO: CpuScript is a bad name for the base class. Fix with a refactoring.
+class RSoVScript : RsdCpuReference::CpuScript {
+ public:
+  RSoVScript(RSoVContext *context, std::vector<uint32_t> &&spvWords,
+             bcinfo::MetadataExtractor *ME,
+             std::map<std::string, int> *GAMapping);
+  RSoVScript(RSoVContext *context, const std::vector<uint32_t> &spvWords,
+             bcinfo::MetadataExtractor *ME,
+             std::map<std::string, int> *GAMapping) = delete;
+
+  virtual ~RSoVScript();
+
+  static bool isScriptCpuBacked(const Script *s);
+  static void initScriptOnCpu(Script *s, RsdCpuReference::CpuScript *cs);
+  static void initScriptOnRSoV(Script *s, RSoVScript *rsovScript);
+
+  void populateScript(Script *) override;
+  void invokeFunction(uint32_t slot, const void *params,
+                      size_t paramLength) override;
+  int invokeRoot() override;
+
+  void invokeForEach(uint32_t slot, const Allocation **ains, uint32_t inLen,
+                     Allocation *aout, const void *usr, uint32_t usrLen,
+                     const RsScriptCall *sc) override;
+
+  void invokeReduce(uint32_t slot, const Allocation **ains, uint32_t inLen,
+                    Allocation *aout, const RsScriptCall *sc) override;
+
+  void invokeInit() override;
+  void invokeFreeChildren() override;
+
+  void setGlobalVar(uint32_t slot, const void *data,
+                    size_t dataLength) override;
+  void getGlobalVar(uint32_t slot, void *data, size_t dataLength) override;
+  void setGlobalVarWithElemDims(uint32_t slot, const void *data,
+                                size_t dataLength, const Element *e,
+                                const uint32_t *dims,
+                                size_t dimLength) override;
+
+  void setGlobalBind(uint32_t slot, Allocation *data) override;
+  void setGlobalObj(uint32_t slot, ObjectBase *obj) override;
+
+  Allocation *getAllocationForPointer(const void *ptr) const override;
+
+  // Returns number of global variables in this Script (may be 0 if
+  // compiler is not configured to emit this information).
+  int getGlobalEntries() const override;
+  // Returns the name of the global variable at index i.
+  const char *getGlobalName(int i) const override;
+  // Returns the CPU address of the global variable at index i.
+  const void *getGlobalAddress(int i) const override;
+  // Returns the size (in bytes) of the global variable at index i.
+  size_t getGlobalSize(int i) const override;
+  // Returns the properties of the global variable at index i.
+  uint32_t getGlobalProperties(int i) const override;
+
+  void setCpuScript(RsdCpuReference::CpuScript *cs) { mCpuScript = cs; }
+
+  RsdCpuReference::CpuScript *getCpuScript() const { return mCpuScript; }
+
+ private:
+  void InitDescriptorAndPipelineLayouts(uint32_t inLen);
+  void InitShader(uint32_t slot);
+  void InitDescriptorPool(uint32_t inLen);
+  void InitDescriptorSet(const std::vector<RSoVAllocation *> &inputAllocations,
+                         RSoVAllocation *outputAllocation);
+  void InitPipelineCache();
+  void InitPipeline();
+  void MarshalTypeInfo();
+  void runForEach(uint32_t slot, uint32_t inLen,
+                  const std::vector<RSoVAllocation *> &input,
+                  RSoVAllocation *output);
+
+  // Gets the offset for the global variable with the given slot number in
+  // the global buffer
+  uint32_t GetExportedVarOffset(uint32_t slot) const {
+    // High-level Java or C++ API has verified that slot is in range
+    return mExportedVarOffsets[slot];
+  }
+
+  static constexpr int CPU_SCRIPT_MAGIC_NUMBER = 0x60000;
+
+  RSoVContext *mRSoV;
+  VkDevice mDevice;
+  std::vector<uint32_t> mSPIRVWords;
+  RsdCpuReference::CpuScript *mCpuScript;
+
+  static constexpr int NUM_DESCRIPTOR_SETS = 1;
+  std::vector<VkDescriptorSetLayout> mDescLayout;
+  VkPipelineLayout mPipelineLayout;
+  VkPipeline mComputePipeline;
+  // TODO: Multiple stages for multiple kernels
+  VkPipelineShaderStageCreateInfo mShaderStage;
+  VkDescriptorPool mDescPool;
+  std::vector<VkDescriptorSet> mDescSet;
+  // For kernel names
+  const bcinfo::MetadataExtractor *mME;
+  std::unique_ptr<RSoVBuffer> mGlobals;
+  std::vector<uint32_t> mExportedVarOffsets;
+  // Metadata of global allocations
+  std::unique_ptr<RSoVBuffer> mGlobalAllocationMetadata;
+  // Mapping of global allocation to rsov-assigned ID
+  std::unique_ptr<std::map<std::string, int> > mGAMapping;
+};
+
+}  // namespace rsov
+}  // namespace renderscript
+}  // namespace android
+
+extern bool rsovScriptInit(const android::renderscript::Context *rsc,
+                           android::renderscript::ScriptC *script,
+                           char const *resName, char const *cacheDir,
+                           uint8_t const *bitcode, size_t bitcodeSize,
+                           uint32_t flags);
+
+extern bool rsovInitIntrinsic(const android::renderscript::Context *rsc,
+                              android::renderscript::Script *s,
+                              RsScriptIntrinsicID iid,
+                              android::renderscript::Element *e);
+
+extern void rsovScriptInvokeFunction(const android::renderscript::Context *dc,
+                                     android::renderscript::Script *script,
+                                     uint32_t slot, const void *params,
+                                     size_t paramLength);
+
+extern void rsovScriptInvokeForEach(
+    const android::renderscript::Context *rsc, android::renderscript::Script *s,
+    uint32_t slot, const android::renderscript::Allocation *ain,
+    android::renderscript::Allocation *aout, const void *usr, size_t usrLen,
+    const RsScriptCall *sc);
+
+extern void rsovScriptInvokeReduce(
+    const android::renderscript::Context *rsc, android::renderscript::Script *s,
+    uint32_t slot, const android::renderscript::Allocation **ains, size_t inLen,
+    android::renderscript::Allocation *aout, const RsScriptCall *sc);
+
+extern void rsovScriptInvokeForEachMulti(
+    const android::renderscript::Context *rsc, android::renderscript::Script *s,
+    uint32_t slot, const android::renderscript::Allocation **ains, size_t inLen,
+    android::renderscript::Allocation *aout, const void *usr, size_t usrLen,
+    const RsScriptCall *sc);
+
+extern int rsovScriptInvokeRoot(const android::renderscript::Context *dc,
+                                android::renderscript::Script *script);
+
+extern void rsovScriptInvokeInit(const android::renderscript::Context *dc,
+                                 android::renderscript::Script *script);
+
+extern void rsovScriptInvokeFreeChildren(
+    const android::renderscript::Context *dc,
+    android::renderscript::Script *script);
+
+extern void rsovScriptSetGlobalVar(const android::renderscript::Context *,
+                                   const android::renderscript::Script *,
+                                   uint32_t slot, void *data, size_t dataLen);
+
+extern void rsovScriptGetGlobalVar(const android::renderscript::Context *,
+                                   const android::renderscript::Script *,
+                                   uint32_t slot, void *data, size_t dataLen);
+
+extern void rsovScriptSetGlobalVarWithElemDims(
+    const android::renderscript::Context *,
+    const android::renderscript::Script *, uint32_t slot, void *data,
+    size_t dataLength, const android::renderscript::Element *,
+    const uint32_t *dims, size_t dimLength);
+extern void rsovScriptSetGlobalBind(const android::renderscript::Context *,
+                                    const android::renderscript::Script *,
+                                    uint32_t slot,
+                                    android::renderscript::Allocation *data);
+
+extern void rsovScriptSetGlobalObj(const android::renderscript::Context *,
+                                   const android::renderscript::Script *,
+                                   uint32_t slot,
+                                   android::renderscript::ObjectBase *data);
+
+extern void rsovScriptSetGlobal(const android::renderscript::Context *dc,
+                                const android::renderscript::Script *script,
+                                uint32_t slot, void *data, size_t dataLength);
+extern void rsovScriptGetGlobal(const android::renderscript::Context *dc,
+                                const android::renderscript::Script *script,
+                                uint32_t slot, void *data, size_t dataLength);
+extern void rsovScriptDestroy(const android::renderscript::Context *dc,
+                              android::renderscript::Script *script);
+
+extern android::renderscript::Allocation *rsovScriptGetAllocationForPointer(
+    const android::renderscript::Context *dc,
+    const android::renderscript::Script *script, const void *);
+
+extern void rsovScriptUpdateCachedObject(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Script *script,
+    android::renderscript::rs_script *obj);
+
+#endif  // RSOV_SCRIPT_H
diff --git a/rsov/driver/rsovScriptGroup.cpp b/rsov/driver/rsovScriptGroup.cpp
new file mode 100644
index 0000000..3603c04
--- /dev/null
+++ b/rsov/driver/rsovScriptGroup.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovCore.h"
+
+#include "rsAllocation.h"
+#include "rsContext.h"
+#include "rsScript.h"
+#include "rsScriptGroup.h"
+#include "rsd_cpu.h"
+
+using android::renderscript::Allocation;
+using android::renderscript::Context;
+using android::renderscript::RsdCpuReference;
+using android::renderscript::ScriptGroup;
+using android::renderscript::ScriptGroupBase;
+using android::renderscript::ScriptKernelID;
+using android::renderscript::rs_script_group;
+
+bool rsovScriptGroupInit(const Context *rsc, ScriptGroupBase *sg) {
+  // Always falls back to CPU implmentation of ScriptGroup
+  RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+
+  sg->mHal.drv = dc->mCpuRef->createScriptGroup(sg);
+  return sg->mHal.drv != nullptr;
+}
+
+void rsovScriptGroupSetInput(const Context *rsc, const ScriptGroup *sg,
+                             const ScriptKernelID *kid, Allocation *) {}
+
+void rsovScriptGroupSetOutput(const Context *rsc, const ScriptGroup *sg,
+                              const ScriptKernelID *kid, Allocation *) {}
+
+void rsovScriptGroupExecute(const Context *rsc, const ScriptGroupBase *sg) {
+  RsdCpuReference::CpuScriptGroupBase *sgi =
+      (RsdCpuReference::CpuScriptGroupBase *)sg->mHal.drv;
+  sgi->execute();
+}
+
+void rsovScriptGroupDestroy(const Context *rsc, const ScriptGroupBase *sg) {
+  RsdCpuReference::CpuScriptGroupBase *sgi =
+      (RsdCpuReference::CpuScriptGroupBase *)sg->mHal.drv;
+  delete sgi;
+}
diff --git a/rsov/driver/rsovScriptGroup.h b/rsov/driver/rsovScriptGroup.h
new file mode 100644
index 0000000..1a16136
--- /dev/null
+++ b/rsov/driver/rsovScriptGroup.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_SCRIPT_GROUP_H
+#define RSOV_SCRIPT_GROUP_H
+
+#include "rs_hal.h"
+
+bool rsovScriptGroupInit(const android::renderscript::Context *rsc,
+                         android::renderscript::ScriptGroupBase *sg);
+void rsovScriptGroupSetInput(const android::renderscript::Context *rsc,
+                             const android::renderscript::ScriptGroup *sg,
+                             const android::renderscript::ScriptKernelID *kid,
+                             android::renderscript::Allocation *);
+void rsovScriptGroupSetOutput(const android::renderscript::Context *rsc,
+                              const android::renderscript::ScriptGroup *sg,
+                              const android::renderscript::ScriptKernelID *kid,
+                              android::renderscript::Allocation *);
+void rsovScriptGroupExecute(const android::renderscript::Context *rsc,
+                            const android::renderscript::ScriptGroupBase *sg);
+void rsovScriptGroupDestroy(const android::renderscript::Context *rsc,
+                            const android::renderscript::ScriptGroupBase *sg);
+
+#endif  // RSOV_SCRIPT_GROUP_H
diff --git a/rsov/driver/rsovType.cpp b/rsov/driver/rsovType.cpp
new file mode 100644
index 0000000..9930bb8
--- /dev/null
+++ b/rsov/driver/rsovType.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsType.h"
+
+using android::renderscript::Context;
+using android::renderscript::Type;
+using android::renderscript::rs_type;
+
+bool rsovTypeInit(const Context *, const Type *t) { return true; }
+
+void rsovTypeDestroy(const Context *rsc, const Type *t) {}
+
+void rsovTypeUpdateCachedObject(const Context *rsc, const Type *t,
+                                rs_type *obj) {
+  obj->p = t;
+#ifdef __LP64__
+  obj->unused1 = nullptr;
+  obj->unused2 = nullptr;
+  obj->unused3 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovType.h b/rsov/driver/rsovType.h
new file mode 100644
index 0000000..39f31dc
--- /dev/null
+++ b/rsov/driver/rsovType.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_TYPE_H
+#define RSOV_TYPE_H
+
+#include "rs_hal.h"
+
+extern bool rsovTypeInit(const android::renderscript::Context *rsc,
+                         const android::renderscript::Type *);
+
+extern void rsovTypeDestroy(const android::renderscript::Context *rsc,
+                            const android::renderscript::Type *);
+
+extern void rsovTypeUpdateCachedObject(
+    const android::renderscript::Context *rsc,
+    const android::renderscript::Type *, android::renderscript::rs_type *obj);
+
+#endif  // RSD_TYPE_H
diff --git a/rsov/tests/Android.mk b/rsov/tests/Android.mk
new file mode 100644
index 0000000..06657c2
--- /dev/null
+++ b/rsov/tests/Android.mk
@@ -0,0 +1,12 @@
+#=====================================================================
+# Include Subdirectories
+#=====================================================================
+
+# Not building RSoV tests in PDK builds.
+ifneq ($(TARGET_BUILD_PDK), true)
+
+LOCAL_PATH:=$(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+endif # TARGET_BUILD_PDK
diff --git a/rsov/tests/RSoVTest/Android.mk b/rsov/tests/RSoVTest/Android.mk
new file mode 100644
index 0000000..c89902f
--- /dev/null
+++ b/rsov/tests/RSoVTest/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_RENDERSCRIPT_FLAGS := -target-api 0
+
+LOCAL_PACKAGE_NAME := RSoVTest
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/rsov/tests/RSoVTest/AndroidManifest.xml b/rsov/tests/RSoVTest/AndroidManifest.xml
new file mode 100644
index 0000000..936dd9f
--- /dev/null
+++ b/rsov/tests/RSoVTest/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.rsov.test">
+    <application
+        android:largeHeap="true"
+        android:label="_RSoV_Test"
+        android:icon="@drawable/test_pattern">
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="RSoVTest"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.rs.rsov.test"/>
+</manifest>
diff --git a/rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.png b/rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 0000000..7b34438
--- /dev/null
+++ b/rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java
new file mode 100644
index 0000000..f9035d2
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+public class RSoVTest extends ListActivity {
+
+    private static final String LOG_TAG = "RSTest";
+    private static final boolean DEBUG = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private RenderScript mRS;
+    private RSoVTestCore RSTC;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mRS = RenderScript.create(this);
+
+        RSTC = new RSoVTestCore(this);
+        RSTC.init(mRS);
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java
new file mode 100644
index 0000000..634c1ad
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.app.ListActivity;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.widget.ArrayAdapter;
+
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class RSoVTestCore {
+    ListActivity mCtx;
+
+    public RSoVTestCore(ListActivity ctx) {
+        mCtx = ctx;
+    }
+
+    private RenderScript mRS;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    private ScriptField_ListAllocs_s mListAllocs;
+
+    private ArrayAdapter<UnitTest> testAdapter;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScript rs) {
+        mRS = rs;
+        stopTesting = false;
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_invert(this, mCtx));
+        unitTests.add(new UT_modulo(this, mCtx));
+        unitTests.add(new UT_multi_kernel(this, mCtx));
+        unitTests.add(new UT_multi_input(this, mCtx));
+        unitTests.add(new UT_global_query(this, mCtx));
+        unitTests.add(new UT_global(this, mCtx));
+
+        UnitTest[] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        /*
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].getResult();
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+        */
+        testAdapter = new ArrayAdapter<UnitTest>(mCtx, android.R.layout.simple_list_item_1, unitTests);
+        mCtx.setListAdapter(testAdapter);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        mCtx.runOnUiThread(new Runnable() {
+            public void run() {
+                if (testAdapter != null)
+                    testAdapter.notifyDataSetChanged();
+            }
+        });
+
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                } catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            } else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_global.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_global.java
new file mode 100644
index 0000000..fe8dacd
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_global.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_global extends UnitTest {
+    private static final String TAG = "global";
+
+    protected UT_global(RSoVTestCore rstc, Context ctx) {
+        super(rstc, "global", ctx);
+    }
+
+    private RenderScript RS;
+    private Allocation A;
+
+    private void test(Element elem, java.lang.Runnable action) {
+        A = Allocation.createSized(RS, elem, 128);
+        action.run();
+        waitForMessage();
+        A.destroy();
+    }
+
+    private void testIntTypes() {
+        ScriptC_global_int s = new ScriptC_global_int(RS);
+
+        test(Element.I32(RS), () -> {
+                int expected = 65536;
+                s.invoke_int_test_init(A);
+                s.set_g_int(expected);
+                s.invoke_int_test(A, expected);
+            });
+
+        test(Element.I32_2(RS), () -> {
+                Int2 expected = new Int2(65536, 65537);;
+                s.invoke_int2_test_init(A);
+                s.set_g_int2(expected);
+                s.invoke_int2_test(A, expected);
+            });
+
+        test(Element.I32_4(RS), () -> {
+                Int4 expected = new Int4(65536, 65537, 65538, 65539);
+                s.invoke_int4_test_init(A);
+                s.set_g_int4(expected);
+                s.invoke_int4_test(A, expected);
+            });
+
+        s.destroy();
+    }
+
+    private void testFloatTypes() {
+        ScriptC_global_float s = new ScriptC_global_float(RS);
+
+        test(Element.F32(RS), () -> {
+                float expected = 3.141593f;
+                s.invoke_float_test_init(A);
+                s.set_g_float(expected);
+                s.invoke_float_test(A, expected);
+            });
+
+        test(Element.F32_2(RS), () -> {
+                Float2 expected = new Float2(3.141593f, 3.141593f / 2);
+                s.invoke_float2_test_init(A);
+                s.set_g_float2(expected);
+                s.invoke_float2_test(A, expected);
+            });
+
+        test(Element.F32_4(RS), () -> {
+                Float4 expected = new Float4(3.141593f, 3.141593f / 2,
+                                             3.141593f / 3, 3.141593f / 4);
+                s.invoke_float4_test_init(A);
+                s.set_g_float4(expected);
+                s.invoke_float4_test(A, expected);
+            });
+
+        s.destroy();
+    }
+
+    public void run() {
+        RS = RenderScript.create(mCtx);
+        RS.setMessageHandler(mRsMessage);
+        RS.finish();
+
+        testIntTypes();
+        testFloatTypes();
+
+        RS.destroy();
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_global_query.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_global_query.java
new file mode 100644
index 0000000..821f9d2
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_global_query.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_global_query extends UnitTest {
+    protected UT_global_query(RSoVTestCore rstc, Context ctx) {
+        super(rstc, "global_query", ctx);
+    }
+
+    private boolean Test(int width, int height, int depth) {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_global_query s = new ScriptC_global_query(pRS);
+
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.I32(pRS));
+        typeBuilder.setX(width);
+        if (height > 0) {
+            typeBuilder.setY(height);
+            if (depth > 0) {
+                typeBuilder.setZ(depth);
+            }
+        }
+
+        if (depth < 1) {
+            depth = 1;
+        }
+
+        if (height < 1) {
+            height = 1;
+        }
+
+        Allocation G = Allocation.createTyped(pRS, typeBuilder.create());
+        Allocation dummy = Allocation.createTyped(pRS, typeBuilder.create());
+        Allocation R = Allocation.createTyped(pRS, typeBuilder.create());
+
+        int g[] = new int[width * height * depth];
+        int d[] = new int[width * height * depth];
+        int r[] = new int[width * height * depth];
+
+        java.util.Random rand = new java.util.Random();
+
+        for (int i = 0; i < width * height * depth; i++) {
+            g[i] = rand.nextInt(123456);
+            d[i] = rand.nextInt(123456);
+        }
+
+        G.copyFrom(g);
+        dummy.copyFrom(d);
+
+        s.set_g(G);
+
+        s.forEach_getDim(dummy, R);
+
+        R.copyTo(r);
+
+        R.destroy();
+        dummy.destroy();
+        G.destroy();
+
+        pRS.finish();
+        pRS.destroy();
+
+        boolean failed = false;
+        for (int i = 0; i < width * height * depth; i++) {
+            if (r[i] != width) {
+                Log.e(name, "expects " + width + " for element " + i +
+                      ". got " + r[i]);
+                failed = true;
+                break;
+            }
+        }
+
+        return !failed;
+    }
+
+    public void run() {
+        final int X = 96;
+
+        if (Test(X, 0, 0)) {
+            passTest();
+            return;
+        }
+
+        failTest();
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java
new file mode 100644
index 0000000..017aa06
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_invert extends UnitTest {
+    protected UT_invert(RSoVTestCore rstc, Context ctx) {
+        super(rstc, "invert", ctx);
+    }
+
+    private boolean Test(int width, int height, int depth) {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_invert s = new ScriptC_invert(pRS);
+
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.F32_4(pRS));
+        typeBuilder.setX(width);
+        if (height > 0) {
+            typeBuilder.setY(height);
+            if (depth > 0) {
+                typeBuilder.setZ(depth);
+            }
+        }
+
+        if (depth < 1) {
+            depth = 1;
+        }
+
+        if (height < 1) {
+            height = 1;
+        }
+
+        Allocation A = Allocation.createTyped(pRS, typeBuilder.create());
+        Allocation B = Allocation.createTyped(pRS, typeBuilder.create());
+
+        float a[] = new float[width * height * depth * 4];
+        float b[] = new float[width * height * depth * 4];
+
+        java.util.Random rand = new java.util.Random();
+
+        for (int i = 0; i < width * height * depth * 4; i++) {
+            a[i] = rand.nextFloat();
+        }
+
+        A.copyFrom(a);
+
+        s.forEach_invert(A, B);
+
+        B.copyTo(b);
+
+        B.destroy();
+        A.destroy();
+
+        pRS.finish();
+        pRS.destroy();
+
+        boolean failed = false;
+        for (int i = 0; i < width * height * depth * 4; i++) {
+            if (b[i] != 1.0f - a[i]) {
+                Log.e(name, "expects " + (1.0f - a[i]) + " for element " + i + 
+                      ". got " + b[i]);
+                failed = true;
+                break;
+            }
+        }
+
+        return !failed;
+    }
+
+    public void run() {
+        final int X = 96;
+        final int Y = 64;
+        final int Z = 32;
+
+        if (Test(X, 0, 0) && Test(X, Y, 0)) {
+            passTest();
+            return;
+        }
+
+        failTest();
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java
new file mode 100644
index 0000000..bb55612
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_modulo extends UnitTest {
+    private Allocation A;
+    private Allocation B;
+    private final int X = 96;
+    private final int Y = 64;
+
+    protected UT_modulo(RSoVTestCore rstc, Context ctx) {
+        super(rstc, "modulo", ctx);
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_modulo s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        typeBuilder.setX(X);
+        typeBuilder.setY(Y);
+
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_modulo s = new ScriptC_modulo(pRS);
+
+        initializeGlobals(pRS, s);
+
+        int a[] = new int[X*Y];
+        int b[] = new int[X*Y];
+
+        java.util.Random rand = new java.util.Random();
+
+        for (int i = 0; i < X * Y; i++) {
+            a[i] = rand.nextInt(65536);
+        }
+
+        A.copyFrom(a);
+
+        s.forEach_modulo(A, B);
+
+        B.copyTo(b);
+
+        pRS.finish();
+        pRS.destroy();
+
+        boolean failed = false;
+        for (int i = 0; i < X * Y; i++) {
+            int expected = a[i] % 256;
+            if (b[i] != expected) {
+                Log.e(name, "expects " + expected + " got " + b[i]);
+                failed = true;
+                break;
+            }
+        }
+
+        if (failed) {
+            failTest();
+        } else {
+            passTest();
+        }
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_multi_input.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_multi_input.java
new file mode 100644
index 0000000..ebb3853
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_multi_input.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_multi_input extends UnitTest {
+    private Allocation Ain0;
+    private Allocation Ain1;
+
+    private Allocation Out0;
+
+    private final int Xdim = 100;
+    private final float tolerance = 1e-6f;
+
+    protected UT_multi_input(RSoVTestCore rstc, Context ctx) {
+        super(rstc, "Foreach Multi-input", ctx);
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_multi_input s) {
+        Type.Builder floatBuilder = new Type.Builder(RS, Element.F32(RS));
+
+        floatBuilder.setX(Xdim);
+
+        Ain0 = Allocation.createTyped(RS, floatBuilder.create());
+        Ain1 = Allocation.createTyped(RS, floatBuilder.create());
+        Out0 = Allocation.createTyped(RS, floatBuilder.create());
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_multi_input s = new ScriptC_multi_input(pRS);
+
+        initializeGlobals(pRS, s);
+
+        float a[] = new float[Xdim];
+        float b[] = new float[Xdim];
+
+
+        java.util.Random rand = new java.util.Random();
+
+        for (int i = 0; i < Xdim; i++) {
+            a[i] = rand.nextFloat();
+            b[i] = rand.nextFloat();
+        }
+
+        Ain0.copyFrom(a);
+        Ain1.copyFrom(b);
+
+        s.forEach_sum2(Ain0, Ain1, Out0);
+
+        float out0[] = new float[Xdim];
+        float ain0[] = new float[Xdim];
+        float ain1[] = new float[Xdim];
+        Ain0.copyTo(ain0);
+        Ain1.copyTo(ain1);
+        Out0.copyTo(out0);
+
+        pRS.finish();
+        pRS.destroy();
+
+        boolean failed = false;
+        for (int i = 0; i < Xdim; i++) {
+            if (ain0[i] != a[i]) {
+                Log.e(name, "Ain0 was " + a[i] + " but changed to " + ain0[i]);
+                failed = true;
+                break;
+            }
+            if (ain1[i] != b[i]) {
+                Log.e(name, "Ain1 was " + b[i] + " but changed to " + ain1[i]);
+                failed = true;
+                break;
+            }
+            if ((a[i] + b[i] - out0[i]) > tolerance) {
+                float expected = a[i]+b[i];
+                Log.e(name, "expects " + expected + " got " + out0[i]);
+                failed = true;
+                break;
+            }
+        }
+
+        if (failed) {
+            failTest();
+        } else {
+            passTest();
+        }
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_multi_kernel.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_multi_kernel.java
new file mode 100644
index 0000000..980e6e5
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_multi_kernel.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_multi_kernel extends UnitTest {
+    protected UT_multi_kernel(RSoVTestCore rstc, Context ctx) {
+        super(rstc, "multi_kernel", ctx);
+    }
+
+    private boolean Test(int width, int height, int depth) {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_multi_kernel s = new ScriptC_multi_kernel(pRS);
+
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.F32_4(pRS));
+        typeBuilder.setX(width);
+        if (height > 0) {
+            typeBuilder.setY(height);
+            if (depth > 0) {
+                typeBuilder.setZ(depth);
+            }
+        }
+
+        if (depth < 1) {
+            depth = 1;
+        }
+
+        if (height < 1) {
+            height = 1;
+        }
+
+        Allocation A = Allocation.createTyped(pRS, typeBuilder.create());
+        Allocation B = Allocation.createTyped(pRS, typeBuilder.create());
+
+        float a[] = new float[width * height * depth * 4];
+        float b[] = new float[width * height * depth * 4];
+
+        java.util.Random rand = new java.util.Random(0xcafebabe);
+
+        for (int i = 0; i < width * height * depth * 4; i++) {
+            a[i] = rand.nextFloat();
+        }
+
+        A.copyFrom(a);
+
+        s.forEach_invert(A, B);
+        s.forEach_scalebytwo(B, A);
+        s.forEach_scalebythree(A, B);
+
+        B.copyTo(b);
+
+        B.destroy();
+        A.destroy();
+
+        pRS.finish();
+        pRS.destroy();
+
+        boolean failed = false;
+        for (int i = 0; i < width * height * depth * 4; i++) {
+            if (b[i] != 3.0f * 2.0f * (1.0f - a[i])) {
+                Log.e(name, "expects " + 3.0f * 2.0f * (1.0f - a[i]) + " for element "
+                      + i + ". got " + b[i]);
+                failed = true;
+                break;
+            }
+        }
+
+        return !failed;
+    }
+
+    public void run() {
+        final int X = 96;
+        final int Y = 64;
+        final int Z = 32;
+
+        if (Test(X, 0, 0) && Test(X, Y, 0)) {
+            passTest();
+            return;
+        }
+
+        failTest();
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java
new file mode 100644
index 0000000..f69a96a
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.util.Log;
+
+public class UnitTest extends Thread {
+    public String name;
+    private int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSoVTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+    public static final int TEST_PASSED = 1;
+    public static final int TEST_FAILED = -1;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSoVTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSoVTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSoVTestCore rstc, Context ctx) {
+        this(rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this(null, ctx);
+    }
+
+    protected void _RS_ASSERT(String message, boolean b) {
+        if (b == false) {
+            Log.e(name, message + " FAILED");
+            failTest();
+        }
+    }
+
+    private void updateUI() {
+        msgHandled = true;
+        if (mItem != null) {
+            mItem.result = result;
+            if (mRSTC != null) {
+                // Add null check for mRSTC, for instrumentation tests.
+                try {
+                    mRSTC.refreshTestResults();
+                } catch (IllegalStateException e) {
+                /* Ignore the case where our message receiver has been
+                   disconnected. This happens when we leave the application
+                   before it finishes running all of the unit tests. */
+                }
+            }
+        }
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = TEST_PASSED;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = TEST_FAILED;
+                        break;
+                    default:
+                        RSoVTest.log("Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            updateUI();
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public int getResult() {
+        return result;
+    }
+
+    public void failTest() {
+        result = TEST_FAILED;
+        updateUI();
+    }
+
+    public void passTest() {
+        if (result != TEST_FAILED) {
+            result = TEST_PASSED;
+        }
+        updateUI();
+    }
+
+    public String toString() {
+        String out = name;
+        if (result == TEST_PASSED) {
+            out += " - PASSED";
+        } else if (result == TEST_FAILED) {
+            out += " - FAILED";
+        }
+        return out;
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global.rsh b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global.rsh
new file mode 100644
index 0000000..6e799b5
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global.rsh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.rsh"
+
+#define DEFINE_TEST(T)                                      \
+  T g_##T=7, notUsed_##T;                                   \
+  /* Test Allocations in between other global variables */  \
+  rs_allocation allocNotUsed_##T;                           \
+  /* Test statics in between other global variables */      \
+  static T static_##T;                                      \
+  /* Test taking addresses of globals */                    \
+  static T *ptr1_##T;                                       \
+  static T *ptr2_##T;                                       \
+  T __attribute__((kernel)) T##_kernel1(T in) {             \
+    return g_##T;                                           \
+  }                                                         \
+  T __attribute__((kernel)) T##_kernel2(T in) {             \
+    return *ptr1_##T + *ptr2_##T;                           \
+  }                                                         \
+  void T##_test_init(rs_allocation a) {                     \
+    /* Test static local variable */                        \
+    rsForEach(T##_kernel1, a, a);                           \
+    T actual = get_##T(a, 19);                              \
+    if (!checkEq((T)(7), actual)) {                         \
+      rsDebug("failed "#T, actual);                         \
+      rsSendToClientBlocking(RS_MSG_TEST_FAILED);           \
+      return;                                               \
+    }                                                       \
+    rsDebug("succeeded "#T, actual);                        \
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);             \
+  }                                                         \
+  void T##_test(rs_allocation a, T expected) {              \
+    /* Test static local variable */                        \
+    static T localStatic;                                   \
+    localStatic = g_##T;                                    \
+    static_##T = localStatic;                               \
+    ptr1_##T = &g_##T;                                      \
+    ptr2_##T = &static_##T;                                 \
+    rsForEach(T##_kernel2, a, a);                           \
+    T actual = get_##T(a, 19);                              \
+    if (!checkEq(expected * 2, actual)) {                   \
+      rsDebug("failed "#T, actual);                         \
+      rsSendToClientBlocking(RS_MSG_TEST_FAILED);           \
+      return;                                               \
+    }                                                       \
+    rsDebug("succeeded "#T, actual);                        \
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);             \
+  }
+
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_float.rs
similarity index 83%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_float.rs
index b828ae0..3da31dc 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_float.rs
@@ -14,5 +14,10 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+#include "global.rsh"
+
+HANDLE_TYPE(float)
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_int.rs
similarity index 83%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_int.rs
index b828ae0..ce1ef3e 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_int.rs
@@ -14,5 +14,10 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+#include "global.rsh"
+
+HANDLE_TYPE(int)
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_query.rs
similarity index 77%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_query.rs
index b828ae0..c15a0b9 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/global_query.rs
@@ -14,5 +14,12 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+rs_allocation g;
+
+int32_t RS_KERNEL getDim(int32_t dummy) {
+    return rsAllocationGetDimX(g);
+}
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs
similarity index 74%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs
index b828ae0..eb89da2 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,5 +14,10 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+float4 RS_KERNEL invert(float4 a) {
+    return 1.0f - a;
+}
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs
similarity index 74%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs
index b828ae0..410dccf 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,5 +14,10 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+int RS_KERNEL modulo(int a) {
+    return a % 256;
+}
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/multi_input.rs
similarity index 78%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/multi_input.rs
index b828ae0..a05fa5b 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/multi_input.rs
@@ -14,5 +14,11 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+float RS_KERNEL sum2(float in0, float in1, uint32_t x) {
+    return in0 + in1;
+}
+
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/multi_kernel.rs
similarity index 63%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to rsov/tests/RSoVTest/src/com/android/rs/rsov/test/multi_kernel.rs
index b828ae0..93af5a6 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/multi_kernel.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,5 +14,18 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+float4 RS_KERNEL invert(float4 a) {
+    return 1.0f - a;
+}
+
+float4 RS_KERNEL scalebytwo(float4 a) {
+    return 2.0f * a;
+}
+
+float4 RS_KERNEL scalebythree(float4 a) {
+    return 3.0f * a;
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs
new file mode 100644
index 0000000..2d5fa59
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs
@@ -0,0 +1,25 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh
new file mode 100644
index 0000000..481e874
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh
@@ -0,0 +1,116 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static inline void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static inline float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+#define _RS_ASSERT_EQU(e1, e2) \
+  (((e1) != (e2)) ? (failed = true, rsDebug(#e1 " != " #e2, (e1), (e2)), false) : true)
+
+static const int iposinf = 0x7f800000;
+static const int ineginf = 0xff800000;
+
+static inline const float posinf() {
+    float f = *((float*)&iposinf);
+    return f;
+}
+
+static inline const float neginf() {
+    float f = *((float*)&ineginf);
+    return f;
+}
+
+static inline bool isposinf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == iposinf);
+}
+
+static inline bool isneginf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == ineginf);
+}
+
+static inline bool isnan(float f) {
+    int i = *((int*)(void*)&f);
+    return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff));
+}
+
+static inline bool isposzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x00000000);
+}
+
+static inline bool isnegzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x80000000);
+}
+
+static inline bool iszero(float f) {
+    return isposzero(f) || isnegzero(f);
+}
+
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static inline int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static inline bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/utils.rsh b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/utils.rsh
new file mode 100644
index 0000000..08be49c
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/utils.rsh
@@ -0,0 +1,45 @@
+#ifndef UTILS_RSH
+#define UTILS_RSH
+
+#define RS_MSG_TEST_PASSED 100
+#define RS_MSG_TEST_FAILED 101
+
+#define DEFINE_CHECK(T)                                                 \
+  static int __attribute__((overloadable))                              \
+  checkEq(T expected, T actual) {                                       \
+    return (expected == actual);                                        \
+  }
+
+#define DEFINE_CHECK2(T)                                                \
+  static int __attribute__((overloadable))                              \
+  checkEq(T##2 expected, T##2 actual) {                                 \
+    return (expected.x == actual.x && expected.y == actual.y);          \
+  }
+
+#define DEFINE_CHECK4(T)                                                \
+  static int __attribute__((overloadable))                              \
+  checkEq(T##4 expected, T##4 actual) {                                 \
+    return (expected.x == actual.x &&                                   \
+            expected.y == actual.y &&                                   \
+            expected.z == actual.z &&                                   \
+            expected.w == actual.w);                                    \
+  }
+
+#define DEFINE_GET(T)                           \
+  static T __attribute__((overloadable))        \
+  get_##T(rs_allocation a, int x) {             \
+    return rsGetElementAt_##T(a, x);            \
+  }
+
+#define HANDLE_TYPE(T)                                   \
+  DEFINE_GET(T)                                          \
+  DEFINE_CHECK(T)                                        \
+  DEFINE_TEST(T)                                         \
+  DEFINE_GET(T##2)                                       \
+  DEFINE_CHECK2(T)                                       \
+  DEFINE_TEST(T##2)                                      \
+  DEFINE_GET(T##4)                                       \
+  DEFINE_CHECK4(T)                                       \
+  DEFINE_TEST(T##4)                                      \
+
+#endif  // UTILS_RSH
diff --git a/script_api/generate.sh b/script_api/generate.sh
index 1a7fe34..9adc751 100755
--- a/script_api/generate.sh
+++ b/script_api/generate.sh
@@ -59,7 +59,7 @@
 
 for ((i=11; i<=RS_API_LEVEL; i++))
   do
-    mv slangtest/all$i.rscript ../../compile/slang/tests/P_all_api_$i
+    mv slangtest/all$i.rs ../../compile/slang/tests/P_all_api_$i
 done
 rm -rf slangtest
 
diff --git a/tests/cpp_api/cpp-globalguard/Android.mk b/tests/cpp_api/cpp-globalguard/Android.mk
index 0f98f77..b5929d8 100644
--- a/tests/cpp_api/cpp-globalguard/Android.mk
+++ b/tests/cpp_api/cpp-globalguard/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_NDK_STL_VARIANT := c++_static
 
 LOCAL_SRC_FILES:= \
-	multiply.rscript \
+	multiply.rs \
 	compute.cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/cpp_api/cpp-globalguard/multiply.rscript b/tests/cpp_api/cpp-globalguard/multiply.rs
similarity index 100%
rename from tests/cpp_api/cpp-globalguard/multiply.rscript
rename to tests/cpp_api/cpp-globalguard/multiply.rs
diff --git a/tests/cpp_api/cppallocation/Android.mk b/tests/cpp_api/cppallocation/Android.mk
index 3b7a7d7..d578679 100644
--- a/tests/cpp_api/cppallocation/Android.mk
+++ b/tests/cpp_api/cppallocation/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_NDK_STL_VARIANT := c++_static
 
 LOCAL_SRC_FILES:= \
-	multiply.rscript \
+	multiply.rs \
 	compute.cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/cpp_api/cppallocation/multiply.rscript b/tests/cpp_api/cppallocation/multiply.rs
similarity index 100%
rename from tests/cpp_api/cppallocation/multiply.rscript
rename to tests/cpp_api/cppallocation/multiply.rs
diff --git a/tests/cpp_api/cppbasic-getpointer/Android.mk b/tests/cpp_api/cppbasic-getpointer/Android.mk
index c50db0d..7ed2047 100644
--- a/tests/cpp_api/cppbasic-getpointer/Android.mk
+++ b/tests/cpp_api/cppbasic-getpointer/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_SRC_FILES:= \
-	mono.rscript \
+	mono.rs \
 	compute.cpp
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/tests/cpp_api/cppbasic-getpointer/mono.rscript b/tests/cpp_api/cppbasic-getpointer/mono.rs
similarity index 100%
rename from tests/cpp_api/cppbasic-getpointer/mono.rscript
rename to tests/cpp_api/cppbasic-getpointer/mono.rs
diff --git a/tests/cpp_api/cppbasic-shared/Android.mk b/tests/cpp_api/cppbasic-shared/Android.mk
index 3ec3035..3d19bfd 100644
--- a/tests/cpp_api/cppbasic-shared/Android.mk
+++ b/tests/cpp_api/cppbasic-shared/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_SRC_FILES:= \
-	mono.rscript \
+	mono.rs \
 	compute.cpp
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/tests/cpp_api/cppbasic-shared/mono.rscript b/tests/cpp_api/cppbasic-shared/mono.rs
similarity index 100%
rename from tests/cpp_api/cppbasic-shared/mono.rscript
rename to tests/cpp_api/cppbasic-shared/mono.rs
diff --git a/tests/cpp_api/cppbasic/Android.mk b/tests/cpp_api/cppbasic/Android.mk
index 979d364..0074e36 100644
--- a/tests/cpp_api/cppbasic/Android.mk
+++ b/tests/cpp_api/cppbasic/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_NDK_STL_VARIANT := c++_static
 
 LOCAL_SRC_FILES:= \
-	mono.rscript \
+	mono.rs \
 	compute.cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/cpp_api/cppbasic/mono.rscript b/tests/cpp_api/cppbasic/mono.rs
similarity index 100%
rename from tests/cpp_api/cppbasic/mono.rscript
rename to tests/cpp_api/cppbasic/mono.rs
diff --git a/tests/cpp_api/cppstrided/Android.mk b/tests/cpp_api/cppstrided/Android.mk
index e88f6cf..f9805ef 100644
--- a/tests/cpp_api/cppstrided/Android.mk
+++ b/tests/cpp_api/cppstrided/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_NDK_STL_VARIANT := c++_static
 
 LOCAL_SRC_FILES:= \
-	multiply.rscript \
+	multiply.rs \
 	compute.cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/cpp_api/cppstrided/multiply.rscript b/tests/cpp_api/cppstrided/multiply.rs
similarity index 100%
rename from tests/cpp_api/cppstrided/multiply.rscript
rename to tests/cpp_api/cppstrided/multiply.rs
diff --git a/tests/cpp_api/latency/Android.mk b/tests/cpp_api/latency/Android.mk
index 59d49f5..963363b 100644
--- a/tests/cpp_api/latency/Android.mk
+++ b/tests/cpp_api/latency/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_NDK_STL_VARIANT := c++_static
 
 LOCAL_SRC_FILES:= \
-	latency.rscript \
+	latency.rs \
 	latency.cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/cpp_api/latency/latency.rscript b/tests/cpp_api/latency/latency.rs
similarity index 100%
rename from tests/cpp_api/latency/latency.rscript
rename to tests/cpp_api/latency/latency.rs
diff --git a/tests/cpp_api/typecheck/Android.mk b/tests/cpp_api/typecheck/Android.mk
index 66ad645..1895ed0 100644
--- a/tests/cpp_api/typecheck/Android.mk
+++ b/tests/cpp_api/typecheck/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_NDK_STL_VARIANT := c++_static
 
 LOCAL_SRC_FILES:= \
-	kernels.rscript \
+	kernels.rs \
 	typecheck.cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/cpp_api/typecheck/kernels.rscript b/tests/cpp_api/typecheck/kernels.rs
similarity index 100%
rename from tests/cpp_api/typecheck/kernels.rscript
rename to tests/cpp_api/typecheck/kernels.rs
diff --git a/tests/java_api/Balls/src/com/example/android/rs/balls/ball_physics.rscript b/tests/java_api/Balls/src/com/example/android/rs/balls/ball_physics.rs
similarity index 100%
rename from tests/java_api/Balls/src/com/example/android/rs/balls/ball_physics.rscript
rename to tests/java_api/Balls/src/com/example/android/rs/balls/ball_physics.rs
diff --git a/tests/java_api/Balls/src/com/example/android/rs/balls/balls.rscript b/tests/java_api/Balls/src/com/example/android/rs/balls/balls.rs
similarity index 100%
rename from tests/java_api/Balls/src/com/example/android/rs/balls/balls.rscript
rename to tests/java_api/Balls/src/com/example/android/rs/balls/balls.rs
diff --git a/tests/java_api/CannyLive/src/com/android/example/cannylive/canny.rscript b/tests/java_api/CannyLive/src/com/android/example/cannylive/canny.rs
similarity index 100%
rename from tests/java_api/CannyLive/src/com/android/example/cannylive/canny.rscript
rename to tests/java_api/CannyLive/src/com/android/example/cannylive/canny.rs
diff --git a/tests/java_api/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rscript b/tests/java_api/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
similarity index 100%
rename from tests/java_api/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rscript
rename to tests/java_api/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
diff --git a/tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/launchtest.rscript b/tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/launchtest.rs
similarity index 100%
rename from tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/launchtest.rscript
rename to tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/launchtest.rs
diff --git a/tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rscript b/tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
similarity index 100%
rename from tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rscript
rename to tests/java_api/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
diff --git a/tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/find_region.rscript b/tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/find_region.rs
similarity index 100%
rename from tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/find_region.rscript
rename to tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/find_region.rs
diff --git a/tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/healing.rscript b/tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/healing.rs
similarity index 100%
rename from tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/healing.rscript
rename to tests/java_api/HealingBrush/src/rs/example/android/com/healingbrush/healing.rs
diff --git a/tests/java_api/HelloComputeNDK/libhellocomputendk/Android.mk b/tests/java_api/HelloComputeNDK/libhellocomputendk/Android.mk
index b9fab0b..9f72588 100644
--- a/tests/java_api/HelloComputeNDK/libhellocomputendk/Android.mk
+++ b/tests/java_api/HelloComputeNDK/libhellocomputendk/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_MODULE := libhellocomputendk
 LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := helloComputeNDK.cpp mono.rscript
+LOCAL_SRC_FILES := helloComputeNDK.cpp mono.rs
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
diff --git a/tests/java_api/HelloComputeNDK/libhellocomputendk/mono.rscript b/tests/java_api/HelloComputeNDK/libhellocomputendk/mono.rs
similarity index 100%
rename from tests/java_api/HelloComputeNDK/libhellocomputendk/mono.rscript
rename to tests/java_api/HelloComputeNDK/libhellocomputendk/mono.rs
diff --git a/tests/java_api/HelloComputeNDK/res/drawable-nodpi/data.jpg b/tests/java_api/HelloComputeNDK/res/drawable-nodpi/data.jpg
index b7a0cbd..81a87b1 100644
--- a/tests/java_api/HelloComputeNDK/res/drawable-nodpi/data.jpg
+++ b/tests/java_api/HelloComputeNDK/res/drawable-nodpi/data.jpg
Binary files differ
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/artistic1.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/artistic1.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/artistic1.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/artistic1.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/blend.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/blend.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/blend.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/blend.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/bwfilter.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/bwfilter.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/bwfilter.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/bwfilter.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/colorcube.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/colorcube.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/colorcube.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/colorcube.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/colormatrix.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/colormatrix.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/colormatrix.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/colormatrix.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/contrast.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/contrast.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/contrast.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/contrast.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/convolve3x3.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/convolve3x3.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/convolve3x3.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/convolve3x3.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/convolve5x5.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/convolve5x5.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/convolve5x5.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/convolve5x5.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/copy.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/copy.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/copy.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/copy.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/exposure.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/exposure.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/exposure.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/exposure.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_full.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_full.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/grain.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/grain.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/grain.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/grain.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/greyscale.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/greyscale.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/greyscale.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/greyscale.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/histogram.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/histogram.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/histogram.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/histogram.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/levels_full.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/levels_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/levels_full.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/levels_full.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/levels_relaxed.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/levels_relaxed.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/mandelbrot.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/mandelbrot.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/mirror.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/mirror.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/mirror.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/mirror.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/resize.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/resize.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/resize.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/resize.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/shadows.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/shadows.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/shadows.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/shadows.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/threshold.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/threshold.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/threshold.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/threshold.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/vibrance.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/vibrance.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/vibrance.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/vibrance.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_full.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_full.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_full.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rs
diff --git a/tests/java_api/ImageProcessing/src/com/android/rs/image/wbalance.rscript b/tests/java_api/ImageProcessing/src/com/android/rs/image/wbalance.rs
similarity index 100%
rename from tests/java_api/ImageProcessing/src/com/android/rs/image/wbalance.rscript
rename to tests/java_api/ImageProcessing/src/com/android/rs/image/wbalance.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/artistic1.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/artistic1.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/artistic1.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/artistic1.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/blend.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/blend.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/blend.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/blend.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/bwfilter.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/bwfilter.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/colorcube.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/colorcube.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/colorcube.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/colorcube.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/colormatrix.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/colormatrix.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/contrast.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/contrast.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/contrast.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/contrast.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve3x3.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve3x3.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve5x5.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve5x5.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/copy.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/copy.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/copy.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/copy.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/exposure.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/exposure.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/exposure.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/exposure.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_full.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_full.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/grain.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/grain.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/grain.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/grain.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/greyscale.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/greyscale.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/greyscale.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/greyscale.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_full.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_full.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_full.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/mandelbrot.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/mandelbrot.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/posterize.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/posterize.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/posterize.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/posterize.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/resize.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/resize.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/resize.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/resize.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/shadows.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/shadows.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/shadows.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/shadows.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/threshold.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/threshold.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/threshold.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/threshold.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/util.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/util.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/util.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/util.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/vibrance.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/vibrance.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/vibrance.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/vibrance.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_full.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_full.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
diff --git a/tests/java_api/ImageProcessing2/src/com/android/rs/image/wbalance.rscript b/tests/java_api/ImageProcessing2/src/com/android/rs/image/wbalance.rs
similarity index 100%
rename from tests/java_api/ImageProcessing2/src/com/android/rs/image/wbalance.rscript
rename to tests/java_api/ImageProcessing2/src/com/android/rs/image/wbalance.rs
diff --git a/tests/java_api/ImageProcessing_jb/res/drawable-nodpi/img3840x2160a.jpg b/tests/java_api/ImageProcessing_jb/res/drawable-nodpi/img3840x2160a.jpg
index 055972a..871b22c 100644
--- a/tests/java_api/ImageProcessing_jb/res/drawable-nodpi/img3840x2160a.jpg
+++ b/tests/java_api/ImageProcessing_jb/res/drawable-nodpi/img3840x2160a.jpg
Binary files differ
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/artistic1.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/artistic1.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/artistic1.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/artistic1.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/blend.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/blend.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/blend.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/blend.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colorcube.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colorcube.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colorcube.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colorcube.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/contrast.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/contrast.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/contrast.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/contrast.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/copy.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/copy.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/copy.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/copy.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/exposure.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/exposure.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/grain.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/grain.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/grain.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/grain.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/greyscale.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/greyscale.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/histogram.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/histogram.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/histogram.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/histogram.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_full.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_full.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/posterize.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/posterize.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/posterize.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/posterize.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/resize.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/resize.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/resize.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/resize.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/shadows.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/shadows.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/shadows.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/shadows.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold_half.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold_half.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold_half.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/threshold_half.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vibrance.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vibrance.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
diff --git a/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/wbalance.rscript b/tests/java_api/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs
similarity index 100%
rename from tests/java_api/ImageProcessing_jb/src/com/android/rs/image/wbalance.rscript
rename to tests/java_api/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs
diff --git a/tests/java_api/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rscript b/tests/java_api/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
similarity index 100%
rename from tests/java_api/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rscript
rename to tests/java_api/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
diff --git a/tests/java_api/LivePreview/src/com/android/rs/livepreview/yuv.rscript b/tests/java_api/LivePreview/src/com/android/rs/livepreview/yuv.rs
similarity index 100%
rename from tests/java_api/LivePreview/src/com/android/rs/livepreview/yuv.rscript
rename to tests/java_api/LivePreview/src/com/android/rs/livepreview/yuv.rs
diff --git a/tests/java_api/MathErr/src/com/example/android/rs/matherr/math_err.rscript b/tests/java_api/MathErr/src/com/example/android/rs/matherr/math_err.rs
similarity index 100%
rename from tests/java_api/MathErr/src/com/example/android/rs/matherr/math_err.rscript
rename to tests/java_api/MathErr/src/com/example/android/rs/matherr/math_err.rs
diff --git a/tests/java_api/RSTestBackward19/Android.mk b/tests/java_api/RSTestBackward19/Android.mk
index 15da2d5..a226b45 100644
--- a/tests/java_api/RSTestBackward19/Android.mk
+++ b/tests/java_api/RSTestBackward19/Android.mk
@@ -32,75 +32,75 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_reflection3264.java\
-    $(my_rs_unit_tests_path)/reflection3264.rscript\
+    $(my_rs_unit_tests_path)/reflection3264.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTestForward/21.1.2/Android.mk b/tests/java_api/RSTestForward/21.1.2/Android.mk
index f67fbbd..99bce0c 100644
--- a/tests/java_api/RSTestForward/21.1.2/Android.mk
+++ b/tests/java_api/RSTestForward/21.1.2/Android.mk
@@ -41,79 +41,79 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_foreach_multi.java\
-    $(my_rs_unit_tests_path)/foreach_multi.rscript\
+    $(my_rs_unit_tests_path)/foreach_multi.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_math_agree.java\
-    $(my_rs_unit_tests_path)/math_agree.rscript\
+    $(my_rs_unit_tests_path)/math_agree.rs\
     $(my_rs_unit_tests_path)/UT_math_conformance.java\
-    $(my_rs_unit_tests_path)/math_conformance.rscript\
+    $(my_rs_unit_tests_path)/math_conformance.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTestForward/22.0.1/Android.mk b/tests/java_api/RSTestForward/22.0.1/Android.mk
index 34ccb5f..cd49c74 100644
--- a/tests/java_api/RSTestForward/22.0.1/Android.mk
+++ b/tests/java_api/RSTestForward/22.0.1/Android.mk
@@ -41,79 +41,79 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_foreach_multi.java\
-    $(my_rs_unit_tests_path)/foreach_multi.rscript\
+    $(my_rs_unit_tests_path)/foreach_multi.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_math_agree.java\
-    $(my_rs_unit_tests_path)/math_agree.rscript\
+    $(my_rs_unit_tests_path)/math_agree.rs\
     $(my_rs_unit_tests_path)/UT_math_conformance.java\
-    $(my_rs_unit_tests_path)/math_conformance.rscript\
+    $(my_rs_unit_tests_path)/math_conformance.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTestForward/23.0.3/Android.mk b/tests/java_api/RSTestForward/23.0.3/Android.mk
index 861541b..6180f33 100644
--- a/tests/java_api/RSTestForward/23.0.3/Android.mk
+++ b/tests/java_api/RSTestForward/23.0.3/Android.mk
@@ -41,100 +41,100 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_alloc_copy.java\
     $(my_rs_unit_tests_path)/UT_alloc_copyPadded.java\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_ctxt_default.java\
-    $(my_rs_unit_tests_path)/ctxt_default.rscript\
+    $(my_rs_unit_tests_path)/ctxt_default.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_foreach_multi.java\
-    $(my_rs_unit_tests_path)/foreach_multi.rscript\
+    $(my_rs_unit_tests_path)/foreach_multi.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel2d.java\
-    $(my_rs_unit_tests_path)/kernel2d.rscript\
+    $(my_rs_unit_tests_path)/kernel2d.rs\
     $(my_rs_unit_tests_path)/UT_kernel2d_oldstyle.java\
-    $(my_rs_unit_tests_path)/kernel2d_oldstyle.rscript\
+    $(my_rs_unit_tests_path)/kernel2d_oldstyle.rs\
     $(my_rs_unit_tests_path)/UT_kernel3d.java\
-    $(my_rs_unit_tests_path)/kernel3d.rscript\
+    $(my_rs_unit_tests_path)/kernel3d.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_math_agree.java\
-    $(my_rs_unit_tests_path)/math_agree.rscript\
+    $(my_rs_unit_tests_path)/math_agree.rs\
     $(my_rs_unit_tests_path)/UT_math_conformance.java\
-    $(my_rs_unit_tests_path)/math_conformance.rscript\
+    $(my_rs_unit_tests_path)/math_conformance.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug_23.java\
-    $(my_rs_unit_tests_path)/rsdebug_23.rscript\
+    $(my_rs_unit_tests_path)/rsdebug_23.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_gatherscatter.java\
-    $(my_rs_unit_tests_path)/addup.rscript\
+    $(my_rs_unit_tests_path)/addup.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_nochain.java\
-    $(my_rs_unit_tests_path)/increment.rscript\
-    $(my_rs_unit_tests_path)/increment2.rscript\
-    $(my_rs_unit_tests_path)/double.rscript\
+    $(my_rs_unit_tests_path)/increment.rs\
+    $(my_rs_unit_tests_path)/increment2.rs\
+    $(my_rs_unit_tests_path)/double.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_pointwise.java\
-    $(my_rs_unit_tests_path)/increment.rscript\
-    $(my_rs_unit_tests_path)/double.rscript\
+    $(my_rs_unit_tests_path)/increment.rs\
+    $(my_rs_unit_tests_path)/double.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTestForward/24.0.3/Android.mk b/tests/java_api/RSTestForward/24.0.3/Android.mk
index 3e81caa..c6ebe09 100644
--- a/tests/java_api/RSTestForward/24.0.3/Android.mk
+++ b/tests/java_api/RSTestForward/24.0.3/Android.mk
@@ -41,124 +41,124 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_alloc_copy.java\
     $(my_rs_unit_tests_path)/UT_alloc_copyPadded.java\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_ctxt_default.java\
-    $(my_rs_unit_tests_path)/ctxt_default.rscript\
+    $(my_rs_unit_tests_path)/ctxt_default.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_foreach_multi.java\
-    $(my_rs_unit_tests_path)/foreach_multi.rscript\
+    $(my_rs_unit_tests_path)/foreach_multi.rs\
     $(my_rs_unit_tests_path)/UT_fp16.java\
-    $(my_rs_unit_tests_path)/fp16.rscript\
+    $(my_rs_unit_tests_path)/fp16.rs\
     $(my_rs_unit_tests_path)/UT_fp16_globals.java\
-    $(my_rs_unit_tests_path)/fp16_globals.rscript\
+    $(my_rs_unit_tests_path)/fp16_globals.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel2d.java\
-    $(my_rs_unit_tests_path)/kernel2d.rscript\
+    $(my_rs_unit_tests_path)/kernel2d.rs\
     $(my_rs_unit_tests_path)/UT_kernel2d_oldstyle.java\
-    $(my_rs_unit_tests_path)/kernel2d_oldstyle.rscript\
+    $(my_rs_unit_tests_path)/kernel2d_oldstyle.rs\
     $(my_rs_unit_tests_path)/UT_kernel3d.java\
-    $(my_rs_unit_tests_path)/kernel3d.rscript\
+    $(my_rs_unit_tests_path)/kernel3d.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_math_24.java\
-    $(my_rs_unit_tests_path)/math_24.rscript\
+    $(my_rs_unit_tests_path)/math_24.rs\
     $(my_rs_unit_tests_path)/UT_math_agree.java\
-    $(my_rs_unit_tests_path)/math_agree.rscript\
+    $(my_rs_unit_tests_path)/math_agree.rs\
     $(my_rs_unit_tests_path)/UT_math_conformance.java\
-    $(my_rs_unit_tests_path)/math_conformance.rscript\
+    $(my_rs_unit_tests_path)/math_conformance.rs\
     $(my_rs_unit_tests_path)/UT_math_fp16.java\
-    $(my_rs_unit_tests_path)/math_fp16.rscript\
+    $(my_rs_unit_tests_path)/math_fp16.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_reduce.java\
-    $(my_rs_unit_tests_path)/reduce.rscript\
+    $(my_rs_unit_tests_path)/reduce.rs\
     $(my_rs_unit_tests_path)/UT_reduce_backward.java\
-    $(my_rs_unit_tests_path)/reduce_backward.rscript\
+    $(my_rs_unit_tests_path)/reduce_backward.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug_23.java\
-    $(my_rs_unit_tests_path)/rsdebug_23.rscript\
+    $(my_rs_unit_tests_path)/rsdebug_23.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug_24.java\
-    $(my_rs_unit_tests_path)/rsdebug_24.rscript\
+    $(my_rs_unit_tests_path)/rsdebug_24.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_float.java\
-    $(my_rs_unit_tests_path)/float_test.rscript\
+    $(my_rs_unit_tests_path)/float_test.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_gatherscatter.java\
-    $(my_rs_unit_tests_path)/addup.rscript\
+    $(my_rs_unit_tests_path)/addup.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_nochain.java\
-    $(my_rs_unit_tests_path)/increment.rscript\
-    $(my_rs_unit_tests_path)/increment2.rscript\
-    $(my_rs_unit_tests_path)/double.rscript\
+    $(my_rs_unit_tests_path)/increment.rs\
+    $(my_rs_unit_tests_path)/increment2.rs\
+    $(my_rs_unit_tests_path)/double.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_pointwise.java\
-    $(my_rs_unit_tests_path)/increment.rscript\
-    $(my_rs_unit_tests_path)/double.rscript\
+    $(my_rs_unit_tests_path)/increment.rs\
+    $(my_rs_unit_tests_path)/double.rs\
     $(my_rs_unit_tests_path)/UT_single_source_alloc.java\
-    $(my_rs_unit_tests_path)/single_source_alloc.rscript\
+    $(my_rs_unit_tests_path)/single_source_alloc.rs\
     $(my_rs_unit_tests_path)/UT_single_source_ref_count.java\
-    $(my_rs_unit_tests_path)/single_source_ref_count.rscript\
+    $(my_rs_unit_tests_path)/single_source_ref_count.rs\
     $(my_rs_unit_tests_path)/UT_single_source_script.java\
-    $(my_rs_unit_tests_path)/single_source_script.rscript\
+    $(my_rs_unit_tests_path)/single_source_script.rs\
     $(my_rs_unit_tests_path)/UT_small_struct_2.java\
-    $(my_rs_unit_tests_path)/small_struct_2.rscript\
+    $(my_rs_unit_tests_path)/small_struct_2.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTestForward/25.0.2/Android.mk b/tests/java_api/RSTestForward/25.0.2/Android.mk
index 127f29d..a80624e 100644
--- a/tests/java_api/RSTestForward/25.0.2/Android.mk
+++ b/tests/java_api/RSTestForward/25.0.2/Android.mk
@@ -41,124 +41,124 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_alloc_copy.java\
     $(my_rs_unit_tests_path)/UT_alloc_copyPadded.java\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_ctxt_default.java\
-    $(my_rs_unit_tests_path)/ctxt_default.rscript\
+    $(my_rs_unit_tests_path)/ctxt_default.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_foreach_multi.java\
-    $(my_rs_unit_tests_path)/foreach_multi.rscript\
+    $(my_rs_unit_tests_path)/foreach_multi.rs\
     $(my_rs_unit_tests_path)/UT_fp16.java\
-    $(my_rs_unit_tests_path)/fp16.rscript\
+    $(my_rs_unit_tests_path)/fp16.rs\
     $(my_rs_unit_tests_path)/UT_fp16_globals.java\
-    $(my_rs_unit_tests_path)/fp16_globals.rscript\
+    $(my_rs_unit_tests_path)/fp16_globals.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel2d.java\
-    $(my_rs_unit_tests_path)/kernel2d.rscript\
+    $(my_rs_unit_tests_path)/kernel2d.rs\
     $(my_rs_unit_tests_path)/UT_kernel2d_oldstyle.java\
-    $(my_rs_unit_tests_path)/kernel2d_oldstyle.rscript\
+    $(my_rs_unit_tests_path)/kernel2d_oldstyle.rs\
     $(my_rs_unit_tests_path)/UT_kernel3d.java\
-    $(my_rs_unit_tests_path)/kernel3d.rscript\
+    $(my_rs_unit_tests_path)/kernel3d.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_math_24.java\
-    $(my_rs_unit_tests_path)/math_24.rscript\
+    $(my_rs_unit_tests_path)/math_24.rs\
     $(my_rs_unit_tests_path)/UT_math_agree.java\
-    $(my_rs_unit_tests_path)/math_agree.rscript\
+    $(my_rs_unit_tests_path)/math_agree.rs\
     $(my_rs_unit_tests_path)/UT_math_conformance.java\
-    $(my_rs_unit_tests_path)/math_conformance.rscript\
+    $(my_rs_unit_tests_path)/math_conformance.rs\
     $(my_rs_unit_tests_path)/UT_math_fp16.java\
-    $(my_rs_unit_tests_path)/math_fp16.rscript\
+    $(my_rs_unit_tests_path)/math_fp16.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_reduce.java\
-    $(my_rs_unit_tests_path)/reduce.rscript\
+    $(my_rs_unit_tests_path)/reduce.rs\
     $(my_rs_unit_tests_path)/UT_reduce_backward.java\
-    $(my_rs_unit_tests_path)/reduce_backward.rscript\
+    $(my_rs_unit_tests_path)/reduce_backward.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug_23.java\
-    $(my_rs_unit_tests_path)/rsdebug_23.rscript\
+    $(my_rs_unit_tests_path)/rsdebug_23.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug_24.java\
-    $(my_rs_unit_tests_path)/rsdebug_24.rscript\
+    $(my_rs_unit_tests_path)/rsdebug_24.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_float.java\
-    $(my_rs_unit_tests_path)/float_test.rscript\
+    $(my_rs_unit_tests_path)/float_test.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_gatherscatter.java\
-    $(my_rs_unit_tests_path)/addup.rscript\
+    $(my_rs_unit_tests_path)/addup.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_nochain.java\
-    $(my_rs_unit_tests_path)/increment.rscript\
-    $(my_rs_unit_tests_path)/increment2.rscript\
-    $(my_rs_unit_tests_path)/double.rscript\
+    $(my_rs_unit_tests_path)/increment.rs\
+    $(my_rs_unit_tests_path)/increment2.rs\
+    $(my_rs_unit_tests_path)/double.rs\
     $(my_rs_unit_tests_path)/UT_script_group2_pointwise.java\
-    $(my_rs_unit_tests_path)/increment.rscript\
-    $(my_rs_unit_tests_path)/double.rscript\
+    $(my_rs_unit_tests_path)/increment.rs\
+    $(my_rs_unit_tests_path)/double.rs\
     $(my_rs_unit_tests_path)/UT_single_source_alloc.java\
-    $(my_rs_unit_tests_path)/single_source_alloc.rscript\
+    $(my_rs_unit_tests_path)/single_source_alloc.rs\
     $(my_rs_unit_tests_path)/UT_single_source_ref_count.java\
-    $(my_rs_unit_tests_path)/single_source_ref_count.rscript\
+    $(my_rs_unit_tests_path)/single_source_ref_count.rs\
     $(my_rs_unit_tests_path)/UT_single_source_script.java\
-    $(my_rs_unit_tests_path)/single_source_script.rscript\
+    $(my_rs_unit_tests_path)/single_source_script.rs\
     $(my_rs_unit_tests_path)/UT_small_struct_2.java\
-    $(my_rs_unit_tests_path)/small_struct_2.rscript\
+    $(my_rs_unit_tests_path)/small_struct_2.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTest_CompatLib19/Android.mk b/tests/java_api/RSTest_CompatLib19/Android.mk
index 80596d0..84e71f1 100644
--- a/tests/java_api/RSTest_CompatLib19/Android.mk
+++ b/tests/java_api/RSTest_CompatLib19/Android.mk
@@ -38,75 +38,75 @@
     $(call all-java-files-under,src)\
     $(my_rs_unit_tests_path)/UnitTest.java\
     $(my_rs_unit_tests_path)/UT_alloc.java\
-    $(my_rs_unit_tests_path)/alloc.rscript\
+    $(my_rs_unit_tests_path)/alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_alloc.java\
-    $(my_rs_unit_tests_path)/array_alloc.rscript\
+    $(my_rs_unit_tests_path)/array_alloc.rs\
     $(my_rs_unit_tests_path)/UT_array_init.java\
-    $(my_rs_unit_tests_path)/array_init.rscript\
+    $(my_rs_unit_tests_path)/array_init.rs\
     $(my_rs_unit_tests_path)/UT_atomic.java\
-    $(my_rs_unit_tests_path)/atomic.rscript\
+    $(my_rs_unit_tests_path)/atomic.rs\
     $(my_rs_unit_tests_path)/UT_bitfield.java\
-    $(my_rs_unit_tests_path)/bitfield.rscript\
+    $(my_rs_unit_tests_path)/bitfield.rs\
     $(my_rs_unit_tests_path)/UT_bug_char.java\
-    $(my_rs_unit_tests_path)/bug_char.rscript\
+    $(my_rs_unit_tests_path)/bug_char.rs\
     $(my_rs_unit_tests_path)/UT_check_dims.java\
-    $(my_rs_unit_tests_path)/check_dims.rscript\
+    $(my_rs_unit_tests_path)/check_dims.rs\
     $(my_rs_unit_tests_path)/UT_clamp.java\
-    $(my_rs_unit_tests_path)/clamp.rscript\
+    $(my_rs_unit_tests_path)/clamp.rs\
     $(my_rs_unit_tests_path)/UT_clamp_relaxed.java\
-    $(my_rs_unit_tests_path)/clamp_relaxed.rscript\
+    $(my_rs_unit_tests_path)/clamp_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_constant.java\
-    $(my_rs_unit_tests_path)/constant.rscript\
+    $(my_rs_unit_tests_path)/constant.rs\
     $(my_rs_unit_tests_path)/UT_convert.java\
-    $(my_rs_unit_tests_path)/convert.rscript\
+    $(my_rs_unit_tests_path)/convert.rs\
     $(my_rs_unit_tests_path)/UT_convert_relaxed.java\
-    $(my_rs_unit_tests_path)/convert_relaxed.rscript\
+    $(my_rs_unit_tests_path)/convert_relaxed.rs\
     $(my_rs_unit_tests_path)/UT_copy_test.java\
-    $(my_rs_unit_tests_path)/copy_test.rscript\
+    $(my_rs_unit_tests_path)/copy_test.rs\
     $(my_rs_unit_tests_path)/UT_element.java\
-    $(my_rs_unit_tests_path)/element.rscript\
+    $(my_rs_unit_tests_path)/element.rs\
     $(my_rs_unit_tests_path)/UT_foreach.java\
-    $(my_rs_unit_tests_path)/foreach.rscript\
+    $(my_rs_unit_tests_path)/foreach.rs\
     $(my_rs_unit_tests_path)/UT_foreach_bounds.java\
-    $(my_rs_unit_tests_path)/foreach_bounds.rscript\
+    $(my_rs_unit_tests_path)/foreach_bounds.rs\
     $(my_rs_unit_tests_path)/UT_fp_mad.java\
-    $(my_rs_unit_tests_path)/fp_mad.rscript\
+    $(my_rs_unit_tests_path)/fp_mad.rs\
     $(my_rs_unit_tests_path)/UT_instance.java\
-    $(my_rs_unit_tests_path)/instance.rscript\
+    $(my_rs_unit_tests_path)/instance.rs\
     $(my_rs_unit_tests_path)/UT_int4.java\
-    $(my_rs_unit_tests_path)/int4.rscript\
+    $(my_rs_unit_tests_path)/int4.rs\
     $(my_rs_unit_tests_path)/UT_kernel.java\
-    $(my_rs_unit_tests_path)/kernel.rscript\
+    $(my_rs_unit_tests_path)/kernel.rs\
     $(my_rs_unit_tests_path)/UT_kernel_struct.java\
-    $(my_rs_unit_tests_path)/kernel_struct.rscript\
+    $(my_rs_unit_tests_path)/kernel_struct.rs\
     $(my_rs_unit_tests_path)/UT_math.java\
-    $(my_rs_unit_tests_path)/math.rscript\
+    $(my_rs_unit_tests_path)/math.rs\
     $(my_rs_unit_tests_path)/UT_min.java\
-    $(my_rs_unit_tests_path)/min.rscript\
+    $(my_rs_unit_tests_path)/min.rs\
     $(my_rs_unit_tests_path)/UT_noroot.java\
-    $(my_rs_unit_tests_path)/noroot.rscript\
+    $(my_rs_unit_tests_path)/noroot.rs\
     $(my_rs_unit_tests_path)/UT_primitives.java\
-    $(my_rs_unit_tests_path)/primitives.rscript\
+    $(my_rs_unit_tests_path)/primitives.rs\
     $(my_rs_unit_tests_path)/UT_refcount.java\
-    $(my_rs_unit_tests_path)/refcount.rscript\
+    $(my_rs_unit_tests_path)/refcount.rs\
     $(my_rs_unit_tests_path)/UT_reflection3264.java\
-    $(my_rs_unit_tests_path)/reflection3264.rscript\
+    $(my_rs_unit_tests_path)/reflection3264.rs\
     $(my_rs_unit_tests_path)/UT_rsdebug.java\
-    $(my_rs_unit_tests_path)/rsdebug.rscript\
+    $(my_rs_unit_tests_path)/rsdebug.rs\
     $(my_rs_unit_tests_path)/UT_rstime.java\
-    $(my_rs_unit_tests_path)/rstime.rscript\
+    $(my_rs_unit_tests_path)/rstime.rs\
     $(my_rs_unit_tests_path)/UT_rstypes.java\
-    $(my_rs_unit_tests_path)/rstypes.rscript\
+    $(my_rs_unit_tests_path)/rstypes.rs\
     $(my_rs_unit_tests_path)/UT_sampler.java\
-    $(my_rs_unit_tests_path)/sampler.rscript\
+    $(my_rs_unit_tests_path)/sampler.rs\
     $(my_rs_unit_tests_path)/UT_static_globals.java\
-    $(my_rs_unit_tests_path)/static_globals.rscript\
+    $(my_rs_unit_tests_path)/static_globals.rs\
     $(my_rs_unit_tests_path)/UT_struct.java\
-    $(my_rs_unit_tests_path)/struct.rscript\
+    $(my_rs_unit_tests_path)/struct.rs\
     $(my_rs_unit_tests_path)/UT_unsigned.java\
-    $(my_rs_unit_tests_path)/unsigned.rscript\
+    $(my_rs_unit_tests_path)/unsigned.rs\
     $(my_rs_unit_tests_path)/UT_vector.java\
-    $(my_rs_unit_tests_path)/vector.rscript\
+    $(my_rs_unit_tests_path)/vector.rs\
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/alloc.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/alloc.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/alloc.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/alloc.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/apitest.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/apitest.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/apitest.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/apitest.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_alloc.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_alloc.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_alloc.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_alloc.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_init.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_init.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_init.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/array_init.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/atomic.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/atomic.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/atomic.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/atomic.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/bug_char.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/bug_char.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/bug_char.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/bug_char.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp_relaxed.rs b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp_relaxed.rs
new file mode 100644
index 0000000..71c65ae
--- /dev/null
+++ b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp_relaxed.rs
@@ -0,0 +1,2 @@
+#include "clamp.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp_relaxed.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp_relaxed.rscript
deleted file mode 100644
index a9514c3..0000000
--- a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/clamp_relaxed.rscript
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/constant.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/constant.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/constant.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/constant.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert_relaxed.rs b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert_relaxed.rs
new file mode 100644
index 0000000..81abb9b
--- /dev/null
+++ b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert_relaxed.rs
@@ -0,0 +1,2 @@
+#include "convert.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert_relaxed.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert_relaxed.rscript
deleted file mode 100644
index ad41780..0000000
--- a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/convert_relaxed.rscript
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "convert.rscript"
-#pragma rs_fp_relaxed
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/copy_test.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/copy_test.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/copy_test.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/copy_test.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/element.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/element.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/element.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/element.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach_bounds.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach_bounds.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach_bounds.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/foreach_bounds.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/fp_mad.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/fp_mad.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/fp_mad.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/fp_mad.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/instance.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/instance.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/instance.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/instance.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/int4.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/int4.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/int4.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/int4.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel_struct.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel_struct.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel_struct.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/kernel_struct.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_agree.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_agree.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_agree.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_agree.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_conformance.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_conformance.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_conformance.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/math_conformance.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/min.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/min.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/min.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/min.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/noroot.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/noroot.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/noroot.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/noroot.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/primitives.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/primitives.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/primitives.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/primitives.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/refcount.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/refcount.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/refcount.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/refcount.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rsdebug.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rsdebug.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rsdebug.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rsdebug.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rslist.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rslist.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rslist.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rslist.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstime.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstime.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstime.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstime.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstypes.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstypes.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstypes.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/rstypes.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/sampler.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/sampler.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/sampler.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/sampler.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/struct.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/struct.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/struct.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/struct.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/unsigned.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/unsigned.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/unsigned.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/unsigned.rs
diff --git a/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/vector.rscript b/tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/vector.rs
similarity index 100%
rename from tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/vector.rscript
rename to tests/java_api/RSTest_CompatLibLegacy/src/com/android/rs/test/vector.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/UT_script_group2_gatherscatter.java b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/UT_script_group2_gatherscatter.java
index 69e9e02..567afbe 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/UT_script_group2_gatherscatter.java
+++ b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/UT_script_group2_gatherscatter.java
@@ -48,7 +48,7 @@
     // on global allocations that are passed across kernels in a script group.
     // The test sums up all elements in the input int4 array of size ARRAY_SIZE.
     // To do so, it adds up the second half of the array to its first half using
-    // kernel function add() in addsup.rscript, and then repeatedly applies the same
+    // kernel function add() in addsup.rs, and then repeatedly applies the same
     // kernel function to the shrinking result arrays until the result is a
     // single int4 value.
     // These steps are created as a script group by repeatedly adding the
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/addup.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/addup.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/addup.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/addup.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/alloc.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/alloc.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/alloc.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/alloc.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_alloc.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_alloc.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_alloc.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_alloc.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_init.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_init.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_init.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/array_init.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/atomic.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/atomic.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/atomic.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/atomic.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/bitfield.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/bitfield.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/bitfield.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/bitfield.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/bug_char.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/bug_char.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/bug_char.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/bug_char.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/check_dims.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/check_dims.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/check_dims.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/check_dims.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rs
similarity index 95%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rs
index b828ae0..9cc597f 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rs
@@ -14,5 +14,5 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
+#include "clamp.rs"
 #pragma rs_fp_relaxed
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/constant.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/constant.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/constant.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/constant.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert_relaxed.rs
similarity index 95%
copy from tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
copy to tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert_relaxed.rs
index b828ae0..93fd7cb 100644
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/clamp_relaxed.rscript
+++ b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert_relaxed.rs
@@ -14,5 +14,5 @@
  * limitations under the License.
  */
 
-#include "clamp.rscript"
+#include "convert.rs"
 #pragma rs_fp_relaxed
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert_relaxed.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert_relaxed.rscript
deleted file mode 100644
index 915143a..0000000
--- a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/convert_relaxed.rscript
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "convert.rscript"
-#pragma rs_fp_relaxed
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/copy_test.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/copy_test.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/copy_test.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/copy_test.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/ctxt_default.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/ctxt_default.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/ctxt_default.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/ctxt_default.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/double.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/double.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/double.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/double.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/element.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/element.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/element.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/element.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/float_test.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/float_test.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/float_test.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/float_test.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_bounds.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_bounds.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_bounds.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_bounds.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_multi.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_multi.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_multi.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/foreach_multi.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16_globals.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16_globals.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16_globals.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp16_globals.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp_mad.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp_mad.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp_mad.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/fp_mad.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment2.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment2.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment2.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/increment2.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/instance.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/instance.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/instance.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/instance.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/int4.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/int4.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/int4.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/int4.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d_oldstyle.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d_oldstyle.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d_oldstyle.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel2d_oldstyle.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel3d.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel3d.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel3d.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel3d.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel_struct.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel_struct.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel_struct.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/kernel_struct.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/math.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/math.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_24.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_24.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_24.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_24.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_agree.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_agree.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_agree.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_agree.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_conformance.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_conformance.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_conformance.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_conformance.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_fp16.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_fp16.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_fp16.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/math_fp16.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/min.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/min.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/min.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/min.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/noroot.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/noroot.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/noroot.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/noroot.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/primitives.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/primitives.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/primitives.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/primitives.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce_backward.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce_backward.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce_backward.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/reduce_backward.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/refcount.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/refcount.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/refcount.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/refcount.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/reflection3264.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/reflection3264.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/reflection3264.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/reflection3264.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_23.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_23.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_23.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_23.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_24.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_24.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_24.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/rsdebug_24.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstime.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstime.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstime.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstime.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstypes.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstypes.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstypes.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/rstypes.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/sampler.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/sampler.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/sampler.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/sampler.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_alloc.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_alloc.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_alloc.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_alloc.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_ref_count.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_ref_count.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_ref_count.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_ref_count.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_script.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_script.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_script.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/single_source_script.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct_2.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct_2.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct_2.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/small_struct_2.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/static_globals.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/static_globals.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/static_globals.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/static_globals.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field_simple.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field_simple.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field_simple.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/struct_field_simple.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/unsigned.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/unsigned.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/unsigned.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/unsigned.rs
diff --git a/tests/java_api/RSUnitTests/src/com/android/rs/unittest/vector.rscript b/tests/java_api/RSUnitTests/src/com/android/rs/unittest/vector.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/src/com/android/rs/unittest/vector.rscript
rename to tests/java_api/RSUnitTests/src/com/android/rs/unittest/vector.rs
diff --git a/tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/alloc_supportlib.rscript b/tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/alloc_supportlib.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/alloc_supportlib.rscript
rename to tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/alloc_supportlib.rs
diff --git a/tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/apitest.rscript b/tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/apitest.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/apitest.rscript
rename to tests/java_api/RSUnitTests/supportlibonlysrc/com/android/rs/unittest/apitest.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/UT_script_group2_gatherscatter.java b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/UT_script_group2_gatherscatter.java
index 8d8605d..9146872 100644
--- a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/UT_script_group2_gatherscatter.java
+++ b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/UT_script_group2_gatherscatter.java
@@ -50,7 +50,7 @@
     // on global allocations that are passed across kernels in a script group.
     // The test sums up all elements in the input int4 array of size ARRAY_SIZE.
     // To do so, it adds up the second half of the array to its first half using
-    // kernel function add() in addsup.rscript, and then repeatedly applies the same
+    // kernel function add() in addsup.rs, and then repeatedly applies the same
     // kernel function to the shrinking result arrays until the result is a
     // single int4 value.
     // These steps are created as a script group by repeatedly adding the
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/addup.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/addup.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/addup.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/addup.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc_supportlib.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc_supportlib.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc_supportlib.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/alloc_supportlib.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/apitest.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/apitest.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/apitest.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/apitest.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_alloc.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_alloc.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_alloc.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_alloc.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_init.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_init.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_init.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/array_init.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/atomic.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/atomic.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/atomic.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/atomic.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bitfield.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bitfield.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bitfield.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bitfield.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bug_char.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bug_char.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bug_char.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/bug_char.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/check_dims.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/check_dims.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/check_dims.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/check_dims.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp_relaxed.rs
similarity index 96%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp_relaxed.rs
index 48b61c4..f391d62 100644
--- a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rscript
+++ b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp_relaxed.rs
@@ -16,5 +16,5 @@
  * limitations under the License.
  */
 
-#include "convert.rscript"
+#include "clamp.rs"
 #pragma rs_fp_relaxed
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp_relaxed.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp_relaxed.rscript
deleted file mode 100644
index 72ae631..0000000
--- a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/clamp_relaxed.rscript
+++ /dev/null
@@ -1,20 +0,0 @@
-// This file is automatically generated from
-// frameworks/rs/tests/java_api/RSUnitTests/RSUnitTests.py
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "clamp.rscript"
-#pragma rs_fp_relaxed
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/constant.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/constant.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/constant.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/constant.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rs
similarity index 96%
copy from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rscript
copy to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rs
index 48b61c4..05de3c3 100644
--- a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rscript
+++ b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/convert_relaxed.rs
@@ -16,5 +16,5 @@
  * limitations under the License.
  */
 
-#include "convert.rscript"
+#include "convert.rs"
 #pragma rs_fp_relaxed
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/copy_test.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/copy_test.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/copy_test.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/copy_test.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/ctxt_default.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/ctxt_default.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/ctxt_default.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/ctxt_default.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/double.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/double.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/double.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/double.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/element.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/element.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/element.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/element.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/float_test.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/float_test.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/float_test.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/float_test.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_bounds.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_bounds.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_bounds.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_bounds.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_multi.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_multi.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_multi.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/foreach_multi.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/fp_mad.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/fp_mad.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/fp_mad.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/fp_mad.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment2.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment2.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment2.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/increment2.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/instance.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/instance.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/instance.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/instance.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/int4.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/int4.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/int4.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/int4.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d_oldstyle.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d_oldstyle.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d_oldstyle.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel2d_oldstyle.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel3d.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel3d.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel3d.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel3d.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel_struct.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel_struct.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel_struct.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/kernel_struct.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_24.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_24.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_24.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_24.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_agree.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_agree.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_agree.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_agree.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_conformance.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_conformance.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_conformance.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/math_conformance.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/min.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/min.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/min.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/min.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/noroot.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/noroot.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/noroot.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/noroot.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/primitives.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/primitives.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/primitives.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/primitives.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce_backward.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce_backward.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce_backward.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reduce_backward.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/refcount.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/refcount.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/refcount.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/refcount.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reflection3264.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reflection3264.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reflection3264.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/reflection3264.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_23.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_23.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_23.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_23.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_24.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_24.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_24.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rsdebug_24.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstime.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstime.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstime.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstime.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstypes.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstypes.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstypes.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/rstypes.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/sampler.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/sampler.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/sampler.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/sampler.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_alloc.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_alloc.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_alloc.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_alloc.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_ref_count.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_ref_count.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_ref_count.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_ref_count.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_script.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_script.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_script.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/single_source_script.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct_2.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct_2.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct_2.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/small_struct_2.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/static_globals.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/static_globals.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/static_globals.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/static_globals.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field_simple.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field_simple.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field_simple.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/struct_field_simple.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/unsigned.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/unsigned.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/unsigned.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/unsigned.rs
diff --git a/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/vector.rscript b/tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/vector.rs
similarity index 100%
rename from tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/vector.rscript
rename to tests/java_api/RSUnitTests/supportlibsrc_gen/com/android/rs/unittest/vector.rs
diff --git a/tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_d1new.rscript b/tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_d1new.rs
similarity index 100%
rename from tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_d1new.rscript
rename to tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_d1new.rs
diff --git a/tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_f32.rscript b/tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_f32.rs
similarity index 100%
rename from tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_f32.rscript
rename to tests/java_api/Refocus/src/com/android/rs/test/layered_filter_fast_f32.rs
diff --git a/tests/java_api/RsCameraDemo/src/com/android/example/rscamera/focus_peak.rscript b/tests/java_api/RsCameraDemo/src/com/android/example/rscamera/focus_peak.rs
similarity index 100%
rename from tests/java_api/RsCameraDemo/src/com/android/example/rscamera/focus_peak.rscript
rename to tests/java_api/RsCameraDemo/src/com/android/example/rscamera/focus_peak.rs
diff --git a/tests/java_api/RsNbody/src/com/example/android/rs/nbody_gl/nbody.rscript b/tests/java_api/RsNbody/src/com/example/android/rs/nbody_gl/nbody.rs
similarity index 100%
rename from tests/java_api/RsNbody/src/com/example/android/rs/nbody_gl/nbody.rscript
rename to tests/java_api/RsNbody/src/com/example/android/rs/nbody_gl/nbody.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/fp_mad.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/fp_mad.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/fp_mad.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/fp_mad.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/math.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/math.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/math.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/math.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/primitives.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/primitives.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/primitives.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/primitives.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/rsdebug.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/rsdebug.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/rsdebug.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/rsdebug.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/rslist.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/rslist.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/rslist.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/rslist.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/rstime.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/rstime.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/rstime.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/rstime.rs
diff --git a/tests/java_api/RsTest_11/src/com/android/rs/test/rstypes.rscript b/tests/java_api/RsTest_11/src/com/android/rs/test/rstypes.rs
similarity index 100%
rename from tests/java_api/RsTest_11/src/com/android/rs/test/rstypes.rscript
rename to tests/java_api/RsTest_11/src/com/android/rs/test/rstypes.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/alloc.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/alloc.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/alloc.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/alloc.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/foreach.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/foreach.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/foreach.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/foreach.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/fp_mad.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/fp_mad.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/fp_mad.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/fp_mad.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/math.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/math.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/math.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/math.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/primitives.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/primitives.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/primitives.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/primitives.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/refcount.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/refcount.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/refcount.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/refcount.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/rsdebug.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/rsdebug.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/rsdebug.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/rsdebug.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/rslist.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/rslist.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/rslist.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/rslist.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/rstime.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/rstime.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/rstime.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/rstime.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/rstypes.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/rstypes.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/rstypes.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/rstypes.rs
diff --git a/tests/java_api/RsTest_14/src/com/android/rs/test/vector.rscript b/tests/java_api/RsTest_14/src/com/android/rs/test/vector.rs
similarity index 100%
rename from tests/java_api/RsTest_14/src/com/android/rs/test/vector.rscript
rename to tests/java_api/RsTest_14/src/com/android/rs/test/vector.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/alloc.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/alloc.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/alloc.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/alloc.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/foreach.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/foreach.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/foreach.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/foreach.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/fp_mad.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/fp_mad.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/fp_mad.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/fp_mad.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/math.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/math.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/math.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/math.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/primitives.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/primitives.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/primitives.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/primitives.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/refcount.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/refcount.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/refcount.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/refcount.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/rsdebug.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/rsdebug.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/rsdebug.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/rsdebug.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/rslist.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/rslist.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/rslist.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/rslist.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/rstime.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/rstime.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/rstime.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/rstime.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/rstypes.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/rstypes.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/rstypes.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/rstypes.rs
diff --git a/tests/java_api/RsTest_16/src/com/android/rs/test/vector.rscript b/tests/java_api/RsTest_16/src/com/android/rs/test/vector.rs
similarity index 100%
rename from tests/java_api/RsTest_16/src/com/android/rs/test/vector.rscript
rename to tests/java_api/RsTest_16/src/com/android/rs/test/vector.rs
diff --git a/tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/find_region.rscript b/tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/find_region.rs
similarity index 100%
rename from tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/find_region.rscript
rename to tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/find_region.rs
diff --git a/tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/healing.rscript b/tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/healing.rs
similarity index 100%
rename from tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/healing.rscript
rename to tests/java_api/SSHealingBrush/src/rs/example/android/com/healingbrush/healing.rs
diff --git a/tests/java_api/SampleTest/src/com/android/rs/sample/sample.rscript b/tests/java_api/SampleTest/src/com/android/rs/sample/sample.rs
similarity index 100%
rename from tests/java_api/SampleTest/src/com/android/rs/sample/sample.rscript
rename to tests/java_api/SampleTest/src/com/android/rs/sample/sample.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/colormatrix_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/colormatrix_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/colormatrix_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/colormatrix_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/contrast_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/contrast_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/contrast_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/contrast_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/exposure_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/exposure_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/exposure_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/exposure_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/f4touc4.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/f4touc4.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/f4touc4.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/f4touc4.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/fisheye_approx_relaxed_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/fisheye_approx_relaxed_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/fisheye_approx_relaxed_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/fisheye_approx_relaxed_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/greyscale_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/greyscale_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/greyscale_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/greyscale_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/levels_relaxed_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/levels_relaxed_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/levels_relaxed_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/levels_relaxed_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/shadows_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/shadows_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/shadows_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/shadows_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/uc4tof4.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/uc4tof4.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/uc4tof4.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/uc4tof4.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vibrance_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vibrance_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vibrance_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vibrance_f.rs
diff --git a/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vignette_approx_relaxed_f.rscript b/tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vignette_approx_relaxed_f.rs
similarity index 100%
rename from tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vignette_approx_relaxed_f.rscript
rename to tests/java_api/ScriptGroupTest/src/com/android/rs/sgtest/vignette_approx_relaxed_f.rs
diff --git a/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bricked.rscript b/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bricked.rs
similarity index 100%
rename from tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bricked.rscript
rename to tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bricked.rs
diff --git a/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bugdroid.rscript b/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bugdroid.rs
similarity index 100%
rename from tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bugdroid.rscript
rename to tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/bugdroid.rs
diff --git a/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/mandelbulb.rscript b/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/mandelbulb.rs
similarity index 100%
rename from tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/mandelbulb.rscript
rename to tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/mandelbulb.rs
diff --git a/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/rasterize.rscript b/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/rasterize.rs
similarity index 100%
rename from tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/rasterize.rscript
rename to tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/rasterize.rs
diff --git a/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/vr.rscript b/tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/vr.rs
similarity index 100%
rename from tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/vr.rscript
rename to tests/java_api/VrDemo/src/com/example/android/rs/vr/engine/vr.rs
diff --git a/tests/lldb/cpp/Allocations/Android.mk b/tests/lldb/cpp/Allocations/Android.mk
index 11b484f..16ed1b2 100644
--- a/tests/lldb/cpp/Allocations/Android.mk
+++ b/tests/lldb/cpp/Allocations/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_SRC_FILES := \
 	Allocations.cpp \
-	allocs.rscript
+	allocs.rs
 
 LOCAL_STATIC_LIBRARIES := libcompiler_rt
 
diff --git a/tests/lldb/cpp/Allocations/allocs.rscript b/tests/lldb/cpp/Allocations/allocs.rs
similarity index 100%
rename from tests/lldb/cpp/Allocations/allocs.rscript
rename to tests/lldb/cpp/Allocations/allocs.rs
diff --git a/tests/lldb/cpp/BranchingFunCalls/Android.mk b/tests/lldb/cpp/BranchingFunCalls/Android.mk
index 12a3e32..56bd152 100644
--- a/tests/lldb/cpp/BranchingFunCalls/Android.mk
+++ b/tests/lldb/cpp/BranchingFunCalls/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_SRC_FILES := \
 	BranchingFunCalls.cpp \
-	scalars.rscript
+	scalars.rs
 
 include frameworks/rs/tests/lldb/cpp/common.mk
 include $(BUILD_EXECUTABLE)
diff --git a/tests/lldb/cpp/BranchingFunCalls/scalars.rscript b/tests/lldb/cpp/BranchingFunCalls/scalars.rs
similarity index 100%
rename from tests/lldb/cpp/BranchingFunCalls/scalars.rscript
rename to tests/lldb/cpp/BranchingFunCalls/scalars.rs
diff --git a/tests/lldb/cpp/InfiniteLoop/Android.mk b/tests/lldb/cpp/InfiniteLoop/Android.mk
index f0895ec..bfcb13a 100644
--- a/tests/lldb/cpp/InfiniteLoop/Android.mk
+++ b/tests/lldb/cpp/InfiniteLoop/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_SRC_FILES := \
 	InfiniteLoop.cpp \
-	infiniteloop.rscript
+	infiniteloop.rs
 
 include frameworks/rs/tests/lldb/cpp/common.mk
 include $(BUILD_EXECUTABLE)
diff --git a/tests/lldb/cpp/InfiniteLoop/infiniteloop.rscript b/tests/lldb/cpp/InfiniteLoop/infiniteloop.rs
similarity index 100%
rename from tests/lldb/cpp/InfiniteLoop/infiniteloop.rscript
rename to tests/lldb/cpp/InfiniteLoop/infiniteloop.rs
diff --git a/tests/lldb/cpp/KernelVariables/Android.mk b/tests/lldb/cpp/KernelVariables/Android.mk
index b9f9102..2d40475 100644
--- a/tests/lldb/cpp/KernelVariables/Android.mk
+++ b/tests/lldb/cpp/KernelVariables/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_SRC_FILES := \
 	KernelVariables.cpp \
-	simple.rscript
+	simple.rs
 
 include frameworks/rs/tests/lldb/cpp/common.mk
 include $(BUILD_EXECUTABLE)
diff --git a/tests/lldb/cpp/KernelVariables/simple.rscript b/tests/lldb/cpp/KernelVariables/simple.rs
similarity index 100%
rename from tests/lldb/cpp/KernelVariables/simple.rscript
rename to tests/lldb/cpp/KernelVariables/simple.rs
diff --git a/tests/lldb/cpp/MultipleRSFiles/Android.mk b/tests/lldb/cpp/MultipleRSFiles/Android.mk
index 4c224b8..334f030 100644
--- a/tests/lldb/cpp/MultipleRSFiles/Android.mk
+++ b/tests/lldb/cpp/MultipleRSFiles/Android.mk
@@ -5,8 +5,8 @@
 
 LOCAL_SRC_FILES := \
 	MultipleRSFiles.cpp \
-	first.rscript \
-	second.rscript
+	first.rs \
+	second.rs
 
 include frameworks/rs/tests/lldb/cpp/common.mk
 include $(BUILD_EXECUTABLE)
diff --git a/tests/lldb/cpp/MultipleRSFiles/first.rscript b/tests/lldb/cpp/MultipleRSFiles/first.rs
similarity index 100%
rename from tests/lldb/cpp/MultipleRSFiles/first.rscript
rename to tests/lldb/cpp/MultipleRSFiles/first.rs
diff --git a/tests/lldb/cpp/MultipleRSFiles/second.rscript b/tests/lldb/cpp/MultipleRSFiles/second.rs
similarity index 100%
rename from tests/lldb/cpp/MultipleRSFiles/second.rscript
rename to tests/lldb/cpp/MultipleRSFiles/second.rs
diff --git a/tests/lldb/cpp/WaitAttach/Android.mk b/tests/lldb/cpp/WaitAttach/Android.mk
index 2c4f18c..0214305 100644
--- a/tests/lldb/cpp/WaitAttach/Android.mk
+++ b/tests/lldb/cpp/WaitAttach/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_SRC_FILES := \
 	WaitAttach.cpp \
-	simple.rscript
+	simple.rs
 
 include frameworks/rs/tests/lldb/cpp/common.mk
 include $(BUILD_EXECUTABLE)
@@ -16,7 +16,7 @@
 
 LOCAL_SRC_FILES := \
 	WaitAttach.cpp \
-	simple.rscript
+	simple.rs
 
 include frameworks/rs/tests/lldb/cpp/common.mk
 LOCAL_RENDERSCRIPT_FLAGS := $(filter-out -g,$(LOCAL_RENDERSCRIPT_FLAGS))
diff --git a/tests/lldb/cpp/WaitAttach/simple.rscript b/tests/lldb/cpp/WaitAttach/simple.rs
similarity index 100%
rename from tests/lldb/cpp/WaitAttach/simple.rscript
rename to tests/lldb/cpp/WaitAttach/simple.rs
diff --git a/tests/lldb/java/Allocations/src/rs/allocs.rscript b/tests/lldb/java/Allocations/src/rs/allocs.rs
similarity index 100%
rename from tests/lldb/java/Allocations/src/rs/allocs.rscript
rename to tests/lldb/java/Allocations/src/rs/allocs.rs
diff --git a/tests/lldb/java/BranchingFunCalls/src/rs/scalars.rscript b/tests/lldb/java/BranchingFunCalls/src/rs/scalars.rs
similarity index 100%
rename from tests/lldb/java/BranchingFunCalls/src/rs/scalars.rscript
rename to tests/lldb/java/BranchingFunCalls/src/rs/scalars.rs
diff --git a/tests/lldb/java/DebugWaitAttach/src/rs/simple.rscript b/tests/lldb/java/DebugWaitAttach/src/rs/simple.rs
similarity index 100%
rename from tests/lldb/java/DebugWaitAttach/src/rs/simple.rscript
rename to tests/lldb/java/DebugWaitAttach/src/rs/simple.rs
diff --git a/tests/lldb/java/InfiniteLoop/src/com/android/rs/infiniteloop/infiniteloop.rscript b/tests/lldb/java/InfiniteLoop/src/com/android/rs/infiniteloop/infiniteloop.rs
similarity index 100%
rename from tests/lldb/java/InfiniteLoop/src/com/android/rs/infiniteloop/infiniteloop.rscript
rename to tests/lldb/java/InfiniteLoop/src/com/android/rs/infiniteloop/infiniteloop.rs
diff --git a/tests/lldb/java/KernelVariables/src/rs/simple.rscript b/tests/lldb/java/KernelVariables/src/rs/simple.rs
similarity index 100%
rename from tests/lldb/java/KernelVariables/src/rs/simple.rscript
rename to tests/lldb/java/KernelVariables/src/rs/simple.rs
diff --git a/tests/lldb/java/MultipleRSFiles/src/rs/first.rscript b/tests/lldb/java/MultipleRSFiles/src/rs/first.rs
similarity index 100%
rename from tests/lldb/java/MultipleRSFiles/src/rs/first.rscript
rename to tests/lldb/java/MultipleRSFiles/src/rs/first.rs
diff --git a/tests/lldb/java/MultipleRSFiles/src/rs/second.rscript b/tests/lldb/java/MultipleRSFiles/src/rs/second.rs
similarity index 100%
rename from tests/lldb/java/MultipleRSFiles/src/rs/second.rscript
rename to tests/lldb/java/MultipleRSFiles/src/rs/second.rs
diff --git a/tests/lldb/java/NoDebugWaitAttach/src/rs/simple.rscript b/tests/lldb/java/NoDebugWaitAttach/src/rs/simple.rs
similarity index 100%
rename from tests/lldb/java/NoDebugWaitAttach/src/rs/simple.rscript
rename to tests/lldb/java/NoDebugWaitAttach/src/rs/simple.rs
diff --git a/tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce.rscript b/tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce.rs
similarity index 100%
rename from tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce.rscript
rename to tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce.rs
diff --git a/tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce_auto_comb.rscript b/tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce_auto_comb.rs
similarity index 100%
rename from tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce_auto_comb.rscript
rename to tests/lldb/java/Reduction/src/com/android/rs/lldbreductiontest/reduce_auto_comb.rs
diff --git a/tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rscript b/tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rs
similarity index 100%
rename from tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rscript
rename to tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rs
diff --git a/tests/lldb/java/SingleSource/src/rs/rs_single_source.rscript b/tests/lldb/java/SingleSource/src/rs/rs_single_source.rs
similarity index 100%
rename from tests/lldb/java/SingleSource/src/rs/rs_single_source.rscript
rename to tests/lldb/java/SingleSource/src/rs/rs_single_source.rs
diff --git a/tests/lldb/jni/Allocations/jniallocations/Android.mk b/tests/lldb/jni/Allocations/jniallocations/Android.mk
index e5c2863..2493be1 100644
--- a/tests/lldb/jni/Allocations/jniallocations/Android.mk
+++ b/tests/lldb/jni/Allocations/jniallocations/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjniallocations
 
-LOCAL_SRC_FILES := jniallocations.cpp allocs.rscript
+LOCAL_SRC_FILES := jniallocations.cpp allocs.rs
 
 LOCAL_RENDERSCRIPT_FLAGS := -g
 
diff --git a/tests/lldb/jni/Allocations/jniallocations/allocs.rscript b/tests/lldb/jni/Allocations/jniallocations/allocs.rs
similarity index 100%
rename from tests/lldb/jni/Allocations/jniallocations/allocs.rscript
rename to tests/lldb/jni/Allocations/jniallocations/allocs.rs
diff --git a/tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/Android.mk b/tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/Android.mk
index 34dd1ad..c04cc19 100644
--- a/tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/Android.mk
+++ b/tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjnibranchingfuncalls
 
-LOCAL_SRC_FILES := jnibranchingfuncalls.cpp scalars.rscript
+LOCAL_SRC_FILES := jnibranchingfuncalls.cpp scalars.rs
 
 LOCAL_RENDERSCRIPT_FLAGS := -g
 
diff --git a/tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/scalars.rscript b/tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/scalars.rs
similarity index 100%
rename from tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/scalars.rscript
rename to tests/lldb/jni/BranchingFunCalls/jnibranchingfuncalls/scalars.rs
diff --git a/tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/Android.mk b/tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/Android.mk
index edb348f..c1df28c 100644
--- a/tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/Android.mk
+++ b/tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjnidebugwaitattach
 
-LOCAL_SRC_FILES := jnidebugwaitattach.cpp simple.rscript
+LOCAL_SRC_FILES := jnidebugwaitattach.cpp simple.rs
 
 LOCAL_RENDERSCRIPT_FLAGS := -g
 
diff --git a/tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/simple.rscript b/tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/simple.rs
similarity index 100%
rename from tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/simple.rscript
rename to tests/lldb/jni/DebugWaitAttach/jnidebugwaitattach/simple.rs
diff --git a/tests/lldb/jni/InfiniteLoop/jniinfiniteloop/Android.mk b/tests/lldb/jni/InfiniteLoop/jniinfiniteloop/Android.mk
index 31001d0..dfc1207 100644
--- a/tests/lldb/jni/InfiniteLoop/jniinfiniteloop/Android.mk
+++ b/tests/lldb/jni/InfiniteLoop/jniinfiniteloop/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjniinfiniteloop
 
-LOCAL_SRC_FILES := jniinfiniteloop.cpp infiniteloop.rscript
+LOCAL_SRC_FILES := jniinfiniteloop.cpp infiniteloop.rs
 
 LOCAL_RENDERSCRIPT_FLAGS := -g
 
diff --git a/tests/lldb/jni/InfiniteLoop/jniinfiniteloop/infiniteloop.rscript b/tests/lldb/jni/InfiniteLoop/jniinfiniteloop/infiniteloop.rs
similarity index 100%
rename from tests/lldb/jni/InfiniteLoop/jniinfiniteloop/infiniteloop.rscript
rename to tests/lldb/jni/InfiniteLoop/jniinfiniteloop/infiniteloop.rs
diff --git a/tests/lldb/jni/KernelVariables/jnikernelvariables/Android.mk b/tests/lldb/jni/KernelVariables/jnikernelvariables/Android.mk
index fe372a7..9088f7e 100644
--- a/tests/lldb/jni/KernelVariables/jnikernelvariables/Android.mk
+++ b/tests/lldb/jni/KernelVariables/jnikernelvariables/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjnikernelvariables
 
-LOCAL_SRC_FILES := jnikernelvariables.cpp simple.rscript
+LOCAL_SRC_FILES := jnikernelvariables.cpp simple.rs
 
 LOCAL_RENDERSCRIPT_FLAGS := -g
 
diff --git a/tests/lldb/jni/KernelVariables/jnikernelvariables/simple.rscript b/tests/lldb/jni/KernelVariables/jnikernelvariables/simple.rs
similarity index 100%
rename from tests/lldb/jni/KernelVariables/jnikernelvariables/simple.rscript
rename to tests/lldb/jni/KernelVariables/jnikernelvariables/simple.rs
diff --git a/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/Android.mk b/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/Android.mk
index 6fd4b10..8d6125e 100644
--- a/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/Android.mk
+++ b/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjnimultiplersfiles
 
-LOCAL_SRC_FILES := jnimultiplersfiles.cpp first.rscript second.rscript
+LOCAL_SRC_FILES := jnimultiplersfiles.cpp first.rs second.rs
 
 LOCAL_RENDERSCRIPT_FLAGS := -g
 
diff --git a/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/first.rscript b/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/first.rs
similarity index 100%
rename from tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/first.rscript
rename to tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/first.rs
diff --git a/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/second.rscript b/tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/second.rs
similarity index 100%
rename from tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/second.rscript
rename to tests/lldb/jni/MultipleRSFiles/jnimultiplersfiles/second.rs
diff --git a/tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/Android.mk b/tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/Android.mk
index fda6fcf..91313d5 100644
--- a/tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/Android.mk
+++ b/tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE := libjninodebugwaitattach
 
-LOCAL_SRC_FILES := jninodebugwaitattach.cpp simple.rscript
+LOCAL_SRC_FILES := jninodebugwaitattach.cpp simple.rs
 
 include frameworks/rs/tests/lldb/jni/common.mk
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/simple.rscript b/tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/simple.rs
similarity index 100%
rename from tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/simple.rscript
rename to tests/lldb/jni/NoDebugWaitAttach/jninodebugwaitattach/simple.rs