release-request-ce5644bf-c7ec-4125-96f7-5f9bba4fe5ad-for-git_oc-dr1-release-4249716 snap-temp-L41100000089724307

Change-Id: Ib0c018c657715458e55257bc1fa5ec6a67c7b1c9
diff --git a/Android.bp b/Android.bp
index 72c5acf..c01ce93 100644
--- a/Android.bp
+++ b/Android.bp
@@ -171,6 +171,7 @@
         "slang_rs_object_ref_count.cpp",
         "slang_rs_reflection.cpp",
         "slang_rs_reflection_cpp.cpp",
+        "slang_rs_reflection_state.cpp",
         "slang_rs_reflect_utils.cpp",
         "slang_rs_special_func.cpp",
         "slang_rs_special_kernel_param.cpp",
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index 2a2e486..7870fe5 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -42,6 +42,7 @@
 #include "slang_assert.h"
 #include "slang_diagnostic_buffer.h"
 #include "slang_rs_reflect_utils.h"
+#include "slang_rs_reflection_state.h"
 
 #include <list>
 #include <set>
@@ -267,6 +268,8 @@
 
   llvm::install_fatal_error_handler(LLVMErrorHandler, &DiagEngine);
 
+  slang::ReflectionState Reflection;
+
   // Compile the 32 bit version
   NamePairList IOFiles32;
   NamePairList DepFiles32;
@@ -280,7 +283,7 @@
       std::unique_ptr<slang::Slang> Compiler(
           new slang::Slang(32, &DiagEngine, &DiagsBuffer));
       CompileFailed =
-          !Compiler->compile(IOFiles32, IOFiles32, DepFiles32, Opts, *DiagOpts);
+          !Compiler->compile(IOFiles32, IOFiles32, DepFiles32, Opts, *DiagOpts, &Reflection);
   }
 
   // Handle the 64-bit case too!
@@ -294,7 +297,7 @@
     std::unique_ptr<slang::Slang> Compiler(
         new slang::Slang(64, &DiagEngine, &DiagsBuffer));
     CompileFailed =
-        !Compiler->compile(IOFiles64, IOFiles32, DepFiles64, Opts, *DiagOpts);
+        !Compiler->compile(IOFiles64, IOFiles32, DepFiles64, Opts, *DiagOpts, &Reflection);
   }
 
   llvm::errs() << DiagsBuffer.str();
diff --git a/slang.cpp b/slang.cpp
index aaac196..5b6aff7 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -82,7 +82,7 @@
 
 #include "slang_rs_reflection.h"
 #include "slang_rs_reflection_cpp.h"
-
+#include "slang_rs_reflection_state.h"
 
 namespace {
 
@@ -574,7 +574,8 @@
     const std::list<std::pair<const char*, const char*> > &IOFiles32,
     const std::list<std::pair<const char*, const char*> > &DepFiles,
     const RSCCOptions &Opts,
-    clang::DiagnosticOptions &DiagOpts) {
+    clang::DiagnosticOptions &DiagOpts,
+    ReflectionState *RState) {
   if (IOFiles32.empty())
     return true;
 
@@ -632,11 +633,28 @@
   // a single pass over the input file.
   bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);
 
+  bool doReflection = true;
+  if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
+    // Skip reflection on the 32-bit path if we are going to emit it on the
+    // 64-bit path.
+    doReflection = false;
+  }
+
   std::list<std::pair<const char*, const char*> >::const_iterator
       IOFile64Iter = IOFiles64.begin(),
       IOFile32Iter = IOFiles32.begin(),
       DepFileIter = DepFiles.begin();
 
+  ReflectionState::Tentative TentativeRState(RState);
+  if (Opts.mEmit3264) {
+    if (Opts.mBitWidth == 32)
+      RState->openJava32(IOFiles32.size());
+    else {
+      slangAssert(Opts.mBitWidth == 64);
+      RState->openJava64();
+    }
+  }
+
   for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
     InputFile = IOFile64Iter->first;
     Output64File = IOFile64Iter->second;
@@ -665,21 +683,17 @@
     const std::string &RealPackageName =
         mRSContext->getReflectJavaPackageName();
 
-    bool doReflection = true;
-    if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
-      // Skip reflection on the 32-bit path if we are going to emit it on the
-      // 64-bit path.
-      doReflection = false;
-    }
-    if (Opts.mOutputType != Slang::OT_Dependency && doReflection) {
+    if (Opts.mOutputType != Slang::OT_Dependency) {
 
       if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
-        const std::string &outputFileName = (Opts.mBitWidth == 64) ?
-                                            mOutputFileName : mOutput32FileName;
-        RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
-                          getInputFileName(), outputFileName);
-        if (!R.reflect()) {
+        if (doReflection) {
+          const std::string &outputFileName = (Opts.mBitWidth == 64) ?
+              mOutputFileName : mOutput32FileName;
+          RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
+                            getInputFileName(), outputFileName);
+          if (!R.reflect()) {
             return false;
+          }
         }
       } else {
         if (!Opts.mRSPackageName.empty()) {
@@ -690,7 +704,8 @@
         RSReflectionJava R(mRSContext, &generatedFileNames,
                            Opts.mJavaReflectionPathBase, getInputFileName(),
                            mOutputFileName,
-                           Opts.mBitcodeStorage == BCST_JAVA_CODE);
+                           Opts.mBitcodeStorage == BCST_JAVA_CODE,
+                           RState);
         if (!R.reflect()) {
           // TODO Is this needed or will the error message have been printed
           // already? and why not for the C++ case?
@@ -700,22 +715,24 @@
           return false;
         }
 
-        for (std::vector<std::string>::const_iterator
-                 I = generatedFileNames.begin(), E = generatedFileNames.end();
-             I != E;
-             I++) {
-          std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
-              Opts.mJavaReflectionPathBase.c_str(),
-              (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
-          appendGeneratedFileName(ReflectedName + ".java");
-        }
+        if (doReflection) {
+          for (std::vector<std::string>::const_iterator
+                   I = generatedFileNames.begin(), E = generatedFileNames.end();
+               I != E;
+               I++) {
+            std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
+                Opts.mJavaReflectionPathBase.c_str(),
+                (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
+            appendGeneratedFileName(ReflectedName + ".java");
+          }
 
-        if ((Opts.mOutputType == Slang::OT_Bitcode) &&
-            (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
-            !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
-                                         RealPackageName.c_str(),
-                                         mRSContext->getLicenseNote())) {
-          return false;
+          if ((Opts.mOutputType == Slang::OT_Bitcode) &&
+              (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
+              !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
+                                           RealPackageName.c_str(),
+                                           mRSContext->getLicenseNote())) {
+            return false;
+          }
         }
       }
     }
@@ -747,6 +764,17 @@
     IOFile64Iter++;
     IOFile32Iter++;
   }
+
+  if (Opts.mEmit3264) {
+    if (Opts.mBitWidth == 32)
+      RState->closeJava32();
+    else {
+      slangAssert(Opts.mBitWidth == 64);
+      RState->closeJava64();
+    }
+  }
+  TentativeRState.ok();
+
   return true;
 }
 
diff --git a/slang.h b/slang.h
index fcff79a..55a9ec2 100644
--- a/slang.h
+++ b/slang.h
@@ -68,6 +68,7 @@
 
 namespace slang {
 
+class ReflectionState;
 class RSCCOptions;
 class RSContext;
 class RSExportRecordType;
@@ -275,12 +276,15 @@
   //             with the same number of pairs given in @IOFiles.
   //
   // @Opts - Selection of options defined from invoking llvm-rs-cc
+  //
+  // @Reflection - Carries reflection information from 32-bit compile to 64-bit compile.
   bool
   compile(const std::list<std::pair<const char *, const char *>> &IOFiles64,
           const std::list<std::pair<const char *, const char *>> &IOFiles32,
           const std::list<std::pair<const char *, const char *>> &DepFiles,
           const RSCCOptions &Opts,
-          clang::DiagnosticOptions &DiagOpts);
+          clang::DiagnosticOptions &DiagOpts,
+          ReflectionState *Reflection);
 
   clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc,
                                      clang::ModuleIdPath Path,
diff --git a/slang_rs_context.cpp b/slang_rs_context.cpp
index 53da2ef..b58c7a8 100644
--- a/slang_rs_context.cpp
+++ b/slang_rs_context.cpp
@@ -64,7 +64,8 @@
       version(0),
       mMangleCtx(Ctx.createMangleContext()),
       mIs64Bit(Target.getPointerWidth(0) == 64),
-      mNextSlot(1) {
+      mNextSlot(1),
+      mNextForEachOrdinal(0) {
 
   AddPragmaHandlers(PP, this);
 
diff --git a/slang_rs_context.h b/slang_rs_context.h
index ff6cdac..a1017d1 100644
--- a/slang_rs_context.h
+++ b/slang_rs_context.h
@@ -111,6 +111,11 @@
   int getForEachSlotNumber(const clang::StringRef& funcName);
   unsigned mNextSlot;
 
+  // For diagnostic purposes, we record the order in which we parse
+  // foreach kernels -- which is not necessarily the same order in
+  // which they appear in mExportForEach.
+  unsigned mNextForEachOrdinal;
+
   ExportVarList mExportVars;
   ExportFuncList mExportFuncs;
   std::map<llvm::StringRef, unsigned> mExportForEachMap;
@@ -198,6 +203,7 @@
   }
 
   bool addForEach(const clang::FunctionDecl* FD);
+
   bool processExports();
   inline void newExportable(RSExportable *E) {
     if (E != nullptr)
@@ -221,6 +227,9 @@
   inline bool hasExportVar() const {
     return !mExportVars.empty();
   }
+  size_t export_vars_size() const {
+    return mExportVars.size();
+  }
 
   typedef ExportFuncList::const_iterator const_export_func_iterator;
   const_export_func_iterator export_funcs_begin() const {
@@ -230,6 +239,9 @@
     return mExportFuncs.end();
   }
   inline bool hasExportFunc() const { return !mExportFuncs.empty(); }
+  size_t export_funcs_size() const {
+    return mExportFuncs.size();
+  }
 
   typedef ExportForEachVector::const_iterator const_export_foreach_iterator;
   const_export_foreach_iterator export_foreach_begin() const {
@@ -241,6 +253,10 @@
   inline bool hasExportForEach() const { return !mExportForEach.empty(); }
   int getForEachSlotNumber(const clang::FunctionDecl* FD);
 
+  // count up from zero
+  unsigned getNextForEachOrdinal() { return mNextForEachOrdinal++; }
+  unsigned getNumAssignedForEachOrdinals() const { return mNextForEachOrdinal; }
+
   typedef ExportReduceList::const_iterator const_export_reduce_iterator;
   const_export_reduce_iterator export_reduce_begin() const {
     return mExportReduce.begin();
@@ -248,6 +264,9 @@
   const_export_reduce_iterator export_reduce_end() const {
     return mExportReduce.end();
   }
+  size_t export_reduce_size() const {
+    return mExportReduce.size();
+  }
   inline bool hasExportReduce() const { return !mExportReduce.empty(); }
   void addExportReduce(RSExportReduce *Reduce) {
     mExportReduce.push_back(Reduce);
@@ -315,7 +334,7 @@
   // Report an error or a warning to the user.
   template <unsigned N>
   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
-                                             const char (&Message)[N]) {
+                                             const char (&Message)[N]) const {
   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
   return DiagEngine->Report(DiagEngine->getCustomDiagID(Level, Message));
   }
@@ -323,7 +342,7 @@
   template <unsigned N>
   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
                                              const clang::SourceLocation Loc,
-                                             const char (&Message)[N]) {
+                                             const char (&Message)[N]) const {
   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
   const clang::SourceManager *SM = getSourceManager();
   return DiagEngine->Report(clang::FullSourceLoc(Loc, *SM),
@@ -333,24 +352,24 @@
   // Utility functions to report errors and warnings to make the calling code
   // easier to read.
   template <unsigned N>
-  clang::DiagnosticBuilder ReportError(const char (&Message)[N]) {
+  clang::DiagnosticBuilder ReportError(const char (&Message)[N]) const {
     return Report<N>(clang::DiagnosticsEngine::Error, Message);
   }
 
   template <unsigned N>
   clang::DiagnosticBuilder ReportError(const clang::SourceLocation Loc,
-                                       const char (&Message)[N]) {
+                                       const char (&Message)[N]) const {
     return Report<N>(clang::DiagnosticsEngine::Error, Loc, Message);
   }
 
   template <unsigned N>
-  clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) {
+  clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) const {
     return Report<N>(clang::DiagnosticsEngine::Warning, Message);
   }
 
   template <unsigned N>
   clang::DiagnosticBuilder ReportWarning(const clang::SourceLocation Loc,
-                                         const char (&Message)[N]) {
+                                         const char (&Message)[N]) const {
     return Report<N>(clang::DiagnosticsEngine::Warning, Loc, Message);
   }
 
diff --git a/slang_rs_export_foreach.cpp b/slang_rs_export_foreach.cpp
index 619bd7a..8fc693b 100644
--- a/slang_rs_export_foreach.cpp
+++ b/slang_rs_export_foreach.cpp
@@ -314,7 +314,8 @@
 
   slangAssert(!Name.empty() && "Function must have a name");
 
-  FE = new RSExportForEach(Context, Name);
+  FE = new RSExportForEach(Context, Name, FD->getLocation());
+  FE->mOrdinal = Context->getNextForEachOrdinal();
 
   if (!FE->validateAndConstructParams(Context, FD)) {
     return nullptr;
@@ -391,6 +392,7 @@
 
       // It is not an error if we don't export an input type for legacy
       // kernel arguments. This can happen in the case of a void pointer.
+      // See ReflectionState::addForEachIn().
       if (FE->mIsKernelStyle && !InExportType) {
         TypeExportError = true;
       }
@@ -424,7 +426,7 @@
 RSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) {
   slangAssert(Context);
   llvm::StringRef Name = "root";
-  RSExportForEach *FE = new RSExportForEach(Context, Name);
+  RSExportForEach *FE = new RSExportForEach(Context, Name, clang::SourceLocation());
   FE->mDummyRoot = true;
   return FE;
 }
diff --git a/slang_rs_export_foreach.h b/slang_rs_export_foreach.h
index 67b3a5c..4622e24 100644
--- a/slang_rs_export_foreach.h
+++ b/slang_rs_export_foreach.h
@@ -34,8 +34,7 @@
 
 namespace slang {
 
-// Base class for reflecting control-side forEach (currently for root()
-// functions that fit appropriate criteria)
+// Base class for reflecting control-side forEach
 class RSExportForEach : public RSExportable {
  public:
 
@@ -47,6 +46,11 @@
 
  private:
   std::string mName;
+
+  // For diagnostic purposes, we record the order in which we parse
+  // foreach kernels.  Does not apply to a dummy root.
+  unsigned mOrdinal;
+
   RSExportRecordType *mParamPacketType;
   llvm::SmallVector<const RSExportType*, 16> mInTypes;
   RSExportType *mOutType;
@@ -68,9 +72,10 @@
   bool mDummyRoot;
 
   // TODO(all): Add support for LOD/face when we have them
-  RSExportForEach(RSContext *Context, const llvm::StringRef &Name)
-    : RSExportable(Context, RSExportable::EX_FOREACH),
-      mName(Name.data(), Name.size()), mParamPacketType(nullptr),
+  RSExportForEach(RSContext *Context, const llvm::StringRef &Name, clang::SourceLocation Loc)
+    : RSExportable(Context, RSExportable::EX_FOREACH, Loc),
+      mName(Name.data(), Name.size()), mOrdinal(~unsigned(0)),
+      mParamPacketType(nullptr),
       mOutType(nullptr), numParams(0), mSignatureMetadata(0),
       mOut(nullptr), mUsrData(nullptr), mSpecialParameterSignatureMetadata(0),
       mResultType(clang::QualType()), mHasReturnType(false),
@@ -102,6 +107,11 @@
     return mName;
   }
 
+  inline unsigned getOrdinal() const {
+    slangAssert(!mDummyRoot);
+    return mOrdinal;
+  }
+
   inline size_t getNumParameters() const {
     return numParams;
   }
@@ -146,6 +156,11 @@
     return mDummyRoot;
   }
 
+  // is this a pass-by-value kernel?
+  inline bool isKernelStyle() const {
+    return mIsKernelStyle;
+  }
+
   typedef RSExportRecordType::const_field_iterator const_param_iterator;
 
   inline const_param_iterator params_begin() const {
@@ -159,6 +174,9 @@
                 "Get parameter from export foreach having no parameter!");
     return mParamPacketType->fields_end();
   }
+  inline size_t params_count() const {
+    return (mParamPacketType ? mParamPacketType->fields_size() : 0);
+  }
 
   static bool isRSForEachFunc(unsigned int targetAPI,
                               const clang::FunctionDecl *FD);
diff --git a/slang_rs_export_func.h b/slang_rs_export_func.h
index 3c0804d..b6c4f01 100644
--- a/slang_rs_export_func.h
+++ b/slang_rs_export_func.h
@@ -33,10 +33,6 @@
   class StructType;
 }
 
-namespace clang {
-  class FunctionDecl;
-}   // namespace clang
-
 namespace slang {
 
 class RSContext;
@@ -52,7 +48,7 @@
 
   RSExportFunc(RSContext *Context, const llvm::StringRef &Name,
                const clang::FunctionDecl *FD)
-    : RSExportable(Context, RSExportable::EX_FUNC),
+    : RSExportable(Context, RSExportable::EX_FUNC, FD->getLocation()),
       mName(Name.data(), Name.size()),
       mMangledName(),
       mShouldMangle(false),
diff --git a/slang_rs_export_reduce.h b/slang_rs_export_reduce.h
index 491bf19..ea00b63 100644
--- a/slang_rs_export_reduce.h
+++ b/slang_rs_export_reduce.h
@@ -85,7 +85,7 @@
                  const llvm::StringRef &NameCombiner,
                  const llvm::StringRef &NameOutConverter,
                  const llvm::StringRef &NameHalter)
-    : RSExportable(Context, RSExportable::EX_REDUCE),
+    : RSExportable(Context, RSExportable::EX_REDUCE, Location),
       mLocation(Location),
       mNameReduce(NameReduce),
       mNameInitializer(NameInitializer),
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
index fb307a9..afeb6c5 100644
--- a/slang_rs_export_type.cpp
+++ b/slang_rs_export_type.cpp
@@ -83,18 +83,18 @@
 
 // RS object types are 32 bits in 32-bit RS, but 256 bits in 64-bit RS.
 // This is handled specially by the GetElementSizeInBits() method.
-{ObjectDataType, _,          "RS_ELEMENT",          "ELEMENT", 32,         "Element",         "Element", _, _, _, false},
-{ObjectDataType, _,             "RS_TYPE",             "TYPE", 32,            "Type",            "Type", _, _, _, false},
-{ObjectDataType, _,       "RS_ALLOCATION",       "ALLOCATION", 32,      "Allocation",      "Allocation", _, _, _, false},
-{ObjectDataType, _,          "RS_SAMPLER",          "SAMPLER", 32,         "Sampler",         "Sampler", _, _, _, false},
-{ObjectDataType, _,           "RS_SCRIPT",           "SCRIPT", 32,          "Script",          "Script", _, _, _, false},
-{ObjectDataType, _,             "RS_MESH",             "MESH", 32,            "Mesh",            "Mesh", _, _, _, false},
-{ObjectDataType, _,             "RS_PATH",             "PATH", 32,            "Path",            "Path", _, _, _, false},
-{ObjectDataType, _, "RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", _, _, _, false},
-{ObjectDataType, _,   "RS_PROGRAM_VERTEX",   "PROGRAM_VERTEX", 32,   "ProgramVertex",   "ProgramVertex", _, _, _, false},
-{ObjectDataType, _,   "RS_PROGRAM_RASTER",   "PROGRAM_RASTER", 32,   "ProgramRaster",   "ProgramRaster", _, _, _, false},
-{ObjectDataType, _,    "RS_PROGRAM_STORE",    "PROGRAM_STORE", 32,    "ProgramStore",    "ProgramStore", _, _, _, false},
-{ObjectDataType, _,             "RS_FONT",             "FONT", 32,            "Font",            "Font", _, _, _, false},
+{ObjectDataType,          "rs_element",          "RS_ELEMENT",          "ELEMENT", 32,         "Element",         "Element", _, _, _, false},
+{ObjectDataType,             "rs_type",             "RS_TYPE",             "TYPE", 32,            "Type",            "Type", _, _, _, false},
+{ObjectDataType,       "rs_allocation",       "RS_ALLOCATION",       "ALLOCATION", 32,      "Allocation",      "Allocation", _, _, _, false},
+{ObjectDataType,          "rs_sampler",          "RS_SAMPLER",          "SAMPLER", 32,         "Sampler",         "Sampler", _, _, _, false},
+{ObjectDataType,           "rs_script",           "RS_SCRIPT",           "SCRIPT", 32,          "Script",          "Script", _, _, _, false},
+{ObjectDataType,             "rs_mesh",             "RS_MESH",             "MESH", 32,            "Mesh",            "Mesh", _, _, _, false},
+{ObjectDataType,             "rs_path",             "RS_PATH",             "PATH", 32,            "Path",            "Path", _, _, _, false},
+{ObjectDataType, "rs_program_fragment", "RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", _, _, _, false},
+{ObjectDataType,   "rs_program_vertex",   "RS_PROGRAM_VERTEX",   "PROGRAM_VERTEX", 32,   "ProgramVertex",   "ProgramVertex", _, _, _, false},
+{ObjectDataType,   "rs_program_raster",   "RS_PROGRAM_RASTER",   "PROGRAM_RASTER", 32,   "ProgramRaster",   "ProgramRaster", _, _, _, false},
+{ObjectDataType,    "rs_program_store",    "RS_PROGRAM_STORE",    "PROGRAM_STORE", 32,    "ProgramStore",    "ProgramStore", _, _, _, false},
+{ObjectDataType,             "rs_font",             "RS_FONT",             "FONT", 32,            "Font",            "Font", _, _, _, false},
 #undef _
 };
 
@@ -944,8 +944,8 @@
 
 RSExportType::RSExportType(RSContext *Context,
                            ExportClass Class,
-                           const llvm::StringRef &Name)
-    : RSExportable(Context, RSExportable::EX_TYPE),
+                           const llvm::StringRef &Name, clang::SourceLocation Loc)
+    : RSExportable(Context, RSExportable::EX_TYPE, Loc),
       mClass(Class),
       // Make a copy on Name since memory stored @Name is either allocated in
       // ASTContext or allocated in GetTypeName which will be destroyed later.
@@ -1506,6 +1506,7 @@
   RSExportRecordType *ERT =
       new RSExportRecordType(Context,
                              TypeName,
+                             RD->getLocation(),
                              RD->hasAttr<clang::PackedAttr>(),
                              mIsArtificial,
                              RL->getDataSize().getQuantity(),
diff --git a/slang_rs_export_type.h b/slang_rs_export_type.h
index fcdd9cd..f55afcc 100644
--- a/slang_rs_export_type.h
+++ b/slang_rs_export_type.h
@@ -217,7 +217,8 @@
  protected:
   RSExportType(RSContext *Context,
                ExportClass Class,
-               const llvm::StringRef &Name);
+               const llvm::StringRef &Name,
+               clang::SourceLocation Loc = clang::SourceLocation());
 
   // Let's make it private since there're some prerequisites to call this
   // function.
@@ -626,6 +627,9 @@
   inline const_field_iterator fields_end() const {
     return this->mFields.end();
   }
+  inline size_t fields_size() const {
+    return this->mFields.size();
+  }
 
  private:
   std::list<const Field*> mFields;
@@ -638,11 +642,12 @@
 
   RSExportRecordType(RSContext *Context,
                      const llvm::StringRef &Name,
+                     clang::SourceLocation Loc,
                      bool IsPacked,
                      bool IsArtificial,
                      size_t StoreSize,
                      size_t AllocSize)
-      : RSExportType(Context, ExportClassRecord, Name),
+      : RSExportType(Context, ExportClassRecord, Name, Loc),
         mIsPacked(IsPacked),
         mIsArtificial(IsArtificial),
         mStoreSize(StoreSize),
diff --git a/slang_rs_export_var.cpp b/slang_rs_export_var.cpp
index 2da2baf..a2b4c68 100644
--- a/slang_rs_export_var.cpp
+++ b/slang_rs_export_var.cpp
@@ -29,7 +29,7 @@
 RSExportVar::RSExportVar(RSContext *Context,
                          const clang::VarDecl *VD,
                          const RSExportType *ET)
-    : RSExportable(Context, RSExportable::EX_VAR),
+    : RSExportable(Context, RSExportable::EX_VAR, VD->getLocation()),
       mName(VD->getName().data(), VD->getName().size()),
       mET(ET),
       mIsConst(false),
diff --git a/slang_rs_exportable.h b/slang_rs_exportable.h
index f6d97a7..7ea982b 100644
--- a/slang_rs_exportable.h
+++ b/slang_rs_exportable.h
@@ -17,6 +17,7 @@
 #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORTABLE_H_  // NOLINT
 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORTABLE_H_
 
+#include "clang/Basic/SourceLocation.h"
 #include "slang_rs_context.h"
 
 namespace slang {
@@ -36,24 +37,29 @@
 
   Kind mK;
 
+  clang::SourceLocation mLoc;
+
  protected:
-  RSExportable(RSContext *Context, RSExportable::Kind K)
+  RSExportable(RSContext *Context, RSExportable::Kind K, clang::SourceLocation Loc)
       : mContext(Context),
-        mK(K) {
+        mK(K),
+        mLoc(Loc) {
     Context->newExportable(this);
   }
 
  public:
-  inline Kind getKind() const { return mK; }
+  Kind getKind() const { return mK; }
+
+  clang::SourceLocation getLocation() const { return mLoc; }
 
   // When keep() is invoked, mKeep will set to true and the associated RSContext
   // won't free this RSExportable object in its destructor. The deallocation
   // responsibility is then transferred to the object who invoked this function.
   // Return false if the exportable is kept or failed to keep.
   virtual bool keep();
-  inline bool isKeep() const { return (mContext == nullptr); }
+  bool isKeep() const { return (mContext == nullptr); }
 
-  inline RSContext *getRSContext() const { return mContext; }
+  RSContext *getRSContext() const { return mContext; }
 
   virtual ~RSExportable() { }
 };
diff --git a/slang_rs_reflection.cpp b/slang_rs_reflection.cpp
index 2c48c24..b2d226b 100644
--- a/slang_rs_reflection.cpp
+++ b/slang_rs_reflection.cpp
@@ -36,6 +36,7 @@
 #include "slang_rs_export_func.h"
 #include "slang_rs_export_reduce.h"
 #include "slang_rs_reflect_utils.h"
+#include "slang_rs_reflection_state.h"
 #include "slang_version.h"
 
 #define RS_SCRIPT_CLASS_NAME_PREFIX "ScriptC_"
@@ -75,27 +76,37 @@
 
 namespace slang {
 
+static void genCheck64BitInternal(const RSContext *Context, ReflectionState *State,
+                                  GeneratedFile &Out, bool Parens);
+
 class RSReflectionJavaElementBuilder {
 public:
   RSReflectionJavaElementBuilder(const char *ElementBuilderName,
                                  const RSExportRecordType *ERT,
                                  const char *RenderScriptVar,
                                  GeneratedFile *Out, const RSContext *RSContext,
-                                 RSReflectionJava *Reflection);
+                                 RSReflectionJava *Reflection,
+                                 ReflectionState *RState);
   void generate();
 
 private:
   void genAddElement(const RSExportType *ET, const std::string &VarName,
                      unsigned ArraySize);
   void genAddStatementStart();
-  void genAddStatementEnd(const std::string &VarName, unsigned ArraySize);
-  void genAddPadding(int PaddingSize);
+  void genAddStatementEnd(const std::string &VarName, unsigned ArraySize,
+                          unsigned Which = RSReflectionJava::FieldIndex | RSReflectionJava::Field32Index);
+  void genAddPadding(int PaddingSize, unsigned Which);  // Which: See RSReflectionJava::incFieldIndex()
+  void genAddPadding(int PaddingSize, ReflectionState::Val32 Field32PaddingSize);
   // TODO Will remove later due to field name information is not necessary for
   // C-reflect-to-Java
   std::string createPaddingField() {
     return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++);
   }
 
+  void genCheck64Bit(bool Parens) {
+    genCheck64BitInternal(mRSContext, mState, *mOut, Parens);
+  }
+
   const char *mElementBuilderName;
   const RSExportRecordType *mERT;
   const char *mRenderScriptVar;
@@ -104,17 +115,19 @@
   int mPaddingFieldIndex;
   const RSContext *mRSContext;
   RSReflectionJava *mReflection;
+  ReflectionState *mState;
 };
 
-static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
-  static const char *MatrixTypeJavaNameMap[] = {/* 2x2 */ "Matrix2f",
-                                                /* 3x3 */ "Matrix3f",
-                                                /* 4x4 */ "Matrix4f",
+enum MatrixLanguage { ML_Java, ML_Script };
+static const char *GetMatrixTypeName(const RSExportMatrixType *EMT, MatrixLanguage lang) {
+  static const char *MatrixTypeJavaNameMap[3][2] = {/* 2x2 */ { "Matrix2f", "rs_matrix2x2" },
+                                                    /* 3x3 */ { "Matrix3f", "rs_matrix3x3" },
+                                                    /* 4x4 */ { "Matrix4f", "rs_matrix4x4" }
   };
   unsigned Dim = EMT->getDim();
 
   if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char *)))
-    return MatrixTypeJavaNameMap[EMT->getDim() - 2];
+    return MatrixTypeJavaNameMap[EMT->getDim() - 2][lang];
 
   slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
   return nullptr;
@@ -177,82 +190,25 @@
 
 namespace {
 
-enum {
-  TypeNameWithConstantArrayBrackets = 0x01,
-  TypeNameWithRecordElementName     = 0x02,
-  TypeNameC                         = 0x04, // else Java
-  TypeNameDefault                   = TypeNameWithConstantArrayBrackets|TypeNameWithRecordElementName
-};
-
-std::string GetTypeName(const RSExportType *ET, unsigned Style = TypeNameDefault) {
-  switch (ET->getClass()) {
-  case RSExportType::ExportClassPrimitive: {
-    const auto ReflectionType =
-        RSExportPrimitiveType::getRSReflectionType(static_cast<const RSExportPrimitiveType *>(ET));
-    return (Style & TypeNameC ? ReflectionType->s_name : ReflectionType->java_name);
-  }
-  case RSExportType::ExportClassPointer: {
-    slangAssert(!(Style & TypeNameC) &&
-                "No need to support C type names for pointer types yet");
-    const RSExportType *PointeeType =
-        static_cast<const RSExportPointerType *>(ET)->getPointeeType();
-
-    if (PointeeType->getClass() != RSExportType::ExportClassRecord)
-      return "Allocation";
-    else
-      return PointeeType->getElementName();
-  }
-  case RSExportType::ExportClassVector: {
-    const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
-    const auto ReflectionType = EVT->getRSReflectionType(EVT);
-    std::stringstream VecName;
-    VecName << (Style & TypeNameC ? ReflectionType->s_name : ReflectionType->rs_java_vector_prefix)
-            << EVT->getNumElement();
-    return VecName.str();
-  }
-  case RSExportType::ExportClassMatrix: {
-    slangAssert(!(Style & TypeNameC) &&
-                "No need to support C type names for matrix types yet");
-    return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
-  }
-  case RSExportType::ExportClassConstantArray: {
-    const RSExportConstantArrayType *CAT =
-        static_cast<const RSExportConstantArrayType *>(ET);
-    std::string ElementTypeName = GetTypeName(CAT->getElementType(), Style);
-    if (Style & TypeNameWithConstantArrayBrackets) {
-      slangAssert(!(Style & TypeNameC) &&
-                  "No need to support C type names for array types with brackets yet");
-      ElementTypeName.append("[]");
-    }
-    return ElementTypeName;
-  }
-  case RSExportType::ExportClassRecord: {
-    slangAssert(!(Style & TypeNameC) &&
-                "No need to support C type names for record types yet");
-    if (Style & TypeNameWithRecordElementName)
-      return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
-    else
-      return ET->getName();
-  }
-  default: { slangAssert(false && "Unknown class of type"); }
-  }
-
-  return "";
-}
-
 std::string GetReduceResultTypeName(const RSExportType *ET) {
   switch (ET->getClass()) {
     case RSExportType::ExportClassConstantArray: {
       const RSExportConstantArrayType *const CAT = static_cast<const RSExportConstantArrayType *>(ET);
       return "resultArray" + std::to_string(CAT->getNumElement()) + "_" +
-          GetTypeName(CAT->getElementType(),
-                      (TypeNameDefault & ~TypeNameWithRecordElementName) | TypeNameC);
+          RSReflectionJava::GetTypeName(
+              CAT->getElementType(),
+              (RSReflectionJava::TypeNameDefault & ~RSReflectionJava::TypeNameWithRecordElementName) |
+              RSReflectionJava::TypeNameC);
     }
     case RSExportType::ExportClassRecord:
-      return "resultStruct_" + GetTypeName(ET,
-                                           (TypeNameDefault & ~TypeNameWithRecordElementName) | TypeNameC);
+      return "resultStruct_" +
+          RSReflectionJava::GetTypeName(
+              ET,
+              (RSReflectionJava::TypeNameDefault & ~RSReflectionJava::TypeNameWithRecordElementName) |
+              RSReflectionJava::TypeNameC);
     default:
-      return "result_" + GetTypeName(ET, TypeNameDefault | TypeNameC);
+      return "result_" +
+          RSReflectionJava::GetTypeName(ET, RSReflectionJava::TypeNameDefault | RSReflectionJava::TypeNameC);
   }
 }
 
@@ -376,14 +332,173 @@
   return "((" + DestIntegerType + ") ((" + Value + ") & " + Mask + "))";
 }
 
+std::string RSReflectionJava::GetTypeName(const RSExportType *ET, unsigned Style) {
+  slangAssert((Style & (TypeNameC|TypeNamePseudoC)) != (TypeNameC|TypeNamePseudoC));
+  slangAssert(!(Style & TypeNamePseudoC) || (Style == TypeNamePseudoC));
+
+  const bool CLike = Style & (TypeNameC|TypeNamePseudoC);
+
+  switch (ET->getClass()) {
+  case RSExportType::ExportClassPrimitive: {
+    const auto ReflectionType =
+        RSExportPrimitiveType::getRSReflectionType(static_cast<const RSExportPrimitiveType *>(ET));
+    return (CLike ? ReflectionType->s_name : ReflectionType->java_name);
+  }
+  case RSExportType::ExportClassPointer: {
+    slangAssert(!(Style & TypeNameC) &&
+                "No need to support C type names for pointer types yet");
+    const RSExportType *PointeeType =
+        static_cast<const RSExportPointerType *>(ET)->getPointeeType();
+
+    if (Style & TypeNamePseudoC)
+      return GetTypeName(PointeeType, Style) + "*";
+    else if (PointeeType->getClass() != RSExportType::ExportClassRecord)
+      return "Allocation";
+    else
+      return PointeeType->getElementName();
+  }
+  case RSExportType::ExportClassVector: {
+    const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
+    const auto ReflectionType = EVT->getRSReflectionType(EVT);
+    std::stringstream VecName;
+    VecName << (CLike ? ReflectionType->s_name : ReflectionType->rs_java_vector_prefix)
+            << EVT->getNumElement();
+    return VecName.str();
+  }
+  case RSExportType::ExportClassMatrix: {
+    return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET), CLike ? ML_Script : ML_Java);
+  }
+  case RSExportType::ExportClassConstantArray: {
+    const RSExportConstantArrayType *CAT =
+        static_cast<const RSExportConstantArrayType *>(ET);
+    std::string ElementTypeName = GetTypeName(CAT->getElementType(), Style);
+    if (Style & TypeNamePseudoC) {
+      std::stringstream ArrayName;
+      ArrayName << ElementTypeName << '[' << CAT->getNumElement() << ']';
+      return ArrayName.str();
+    }
+    else if (Style & TypeNameWithConstantArrayBrackets) {
+      slangAssert(!(Style & TypeNameC) &&
+                  "No need to support C type names for array types with brackets yet");
+      ElementTypeName.append("[]");
+    }
+    return ElementTypeName;
+  }
+  case RSExportType::ExportClassRecord: {
+    slangAssert(!(Style & TypeNameC) &&
+                "No need to support C type names for record types yet");
+    if (Style & TypeNamePseudoC)
+      return "struct " + ET->getName();
+    else if (Style & TypeNameWithRecordElementName)
+      return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
+    else
+      return ET->getName();
+  }
+  default: { slangAssert(false && "Unknown class of type"); }
+  }
+
+  return "";
+}
+
+void RSReflectionJava::genConditionalVal(const std::string &Prefix, bool Parens,
+                                         size_t Val, ReflectionState::Val32 Val32) {
+  if (Prefix.empty() || (Val != 0) || (Val32.first && (Val32.second != 0 ))) {
+    mOut << Prefix;
+
+    if (!Val32.first || (Val == Val32.second)) {
+      // Either we're ignoring the 32-bit case, or 32-bit and 64-bit
+      // values are the same.
+      mOut << Val;
+    } else {
+      // We cannot ignore the 32-bit case, and 32-bit and 64-bit
+      // values differ.
+      if (Parens)
+        mOut << '(';
+      genCheck64Bit(true);
+      mOut << " ? " << Val << " : " << Val32.second;
+      if (Parens)
+        mOut << ')';
+    }
+  }
+}
+
+static void genCheck64BitInternal(const RSContext *Context, ReflectionState *State,
+                                  GeneratedFile &Out, bool Parens) {
+  State->setOutputClassDivergent();
+  if (Context->isCompatLib()) {
+    if (Parens)
+      Out << '(';
+    Out << "RenderScript.getPointerSize() == 8";
+    if (Parens)
+      Out << ')';
+  }
+  else
+    Out << "sIs64Bit";
+}
+
+void RSReflectionJava::genCheck64Bit(bool Parens) {
+  genCheck64BitInternal(mRSContext, mState, mOut, Parens);
+}
+
+void RSReflectionJava::genCompute64Bit() {
+  if (mRSContext->isCompatLib()) {
+    // We can rely on RenderScript class in lockstep with llvm-rs-cc
+    // and hence in lockstep with the generated code, so we don't need
+    // any complicated logic to determine pointer size.
+    return;
+  }
+
+  // Note that Android L is the first release to support 64-bit
+  // targets.  When RenderScript is compiled with "-target-api $v"
+  // with "$v < 21" (L is API level 21), we only compile for 32-bit,
+  // and we reflect during that compile, so there are no divergent
+  // structs, and we will not get here.
+
+  slangAssert(mRSContext->getTargetAPI() >= SLANG_L_TARGET_API);
+
+  mOut.indent() << "private static boolean sIs64Bit;\n\n";
+  mOut.indent() << "static";
+  mOut.startBlock();
+  mOut.indent() << "if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)";
+  mOut.startBlock();
+  mOut.indent() << "sIs64Bit = Process.is64Bit();\n";
+  mOut.endBlock();
+  mOut.indent() << "else";
+  mOut.startBlock();
+  mOut.indent() << "try";
+  mOut.startBlock();
+  mOut.indent() << "Field f = RenderScript.class.getDeclaredField(\"sPointerSize\");\n";
+  mOut.indent() << "f.setAccessible(true);\n";
+  mOut.indent() << "sIs64Bit = (f.getInt(null) == 8);\n";
+  mOut.endBlock();
+
+  // If reflection fails, assume we're on a 32-bit-only device
+  // (64-bit-only is not allowed).  This should only happen if the
+  // device is L-or-later but has been customized in some way so that
+  // the field "sPointerSize" -- introduced in L -- is not present.
+  //
+  // Alternatively, we could treat this as 64-bit (reverting to the
+  // behavior prior to the fix for http://b/32780232) or we could
+  // decide we have no idea what's going on and throw an exception.
+  mOut.indent() << "catch (Throwable e)";
+  mOut.startBlock();
+  mOut.indent() << "sIs64Bit = false;\n";
+  mOut.endBlock();
+
+  mOut.endBlock();
+  mOut.endBlock();
+}
+
 /********************** Methods to generate script class **********************/
 RSReflectionJava::RSReflectionJava(const RSContext *Context,
                                    std::vector<std::string> *GeneratedFileNames,
                                    const std::string &OutputBaseDirectory,
                                    const std::string &RSSourceFileName,
                                    const std::string &BitCodeFileName,
-                                   bool EmbedBitcodeInJava)
-    : mRSContext(Context), mPackageName(Context->getReflectJavaPackageName()),
+                                   bool EmbedBitcodeInJava,
+                                   ReflectionState *RState)
+    : mRSContext(Context), mState(RState), mCollecting(RState->isCollecting()),
+      mPackageName(Context->getReflectJavaPackageName()),
       mRSPackageName(Context->getRSPackageName()),
       mOutputBaseDirectory(OutputBaseDirectory),
       mRSSourceFileName(RSSourceFileName), mBitCodeFileName(BitCodeFileName),
@@ -395,7 +510,7 @@
       mEmbedBitcodeInJava(EmbedBitcodeInJava), mNextExportVarSlot(0),
       mNextExportFuncSlot(0), mNextExportForEachSlot(0),
       mNextExportReduceSlot(0), mLastError(""),
-      mGeneratedFileNames(GeneratedFileNames), mFieldIndex(0) {
+  mGeneratedFileNames(GeneratedFileNames), mFieldIndex(0), mField32Index(0) {
   slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames");
   slangAssert(!mPackageName.empty() && mPackageName != "-");
 
@@ -409,52 +524,74 @@
   } else {
       mItemSizeof = RS_TYPE_ITEM_SIZEOF_LEGACY;
   }
+
+  mState->nextFile(mRSContext, mPackageName, mRSSourceFileName);
 }
 
 bool RSReflectionJava::genScriptClass(const std::string &ClassName,
                                       std::string &ErrorMsg) {
-  if (!startClass(AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
-                  ErrorMsg))
-    return false;
+  if (!mCollecting) {
+    if (!startClass(AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
+                    ErrorMsg))
+      return false;
 
-  genScriptClassConstructor();
+    mState->beginOutputClass();
+    genScriptClassConstructor();
+  }
 
   // Reflect exported variables
+  mState->beginVariables(mRSContext->export_vars_size());
   for (auto I = mRSContext->export_vars_begin(),
             E = mRSContext->export_vars_end();
        I != E; I++)
     genExportVariable(*I);
+  mState->endVariables();
 
   // Reflect exported forEach functions (only available on ICS+)
   if (mRSContext->getTargetAPI() >= SLANG_ICS_TARGET_API) {
+    mState->beginForEaches(mRSContext->getNumAssignedForEachOrdinals());
     for (auto I = mRSContext->export_foreach_begin(),
               E = mRSContext->export_foreach_end();
          I != E; I++) {
       genExportForEach(*I);
     }
+    mState->endForEaches();
   }
 
-  // Reflect exported new-style reduce functions
-  for (const RSExportType *ResultType : mRSContext->getReduceResultTypes(
-           // FilterIn
-           exportableReduce,
+  // Reflect exported reduce functions
+  if (!mCollecting) {
+    for (const RSExportType *ResultType : mRSContext->getReduceResultTypes(
+             // FilterIn
+             exportableReduce,
 
-           // Compare
-           [](const RSExportType *A, const RSExportType *B)
-           { return GetReduceResultTypeName(A) < GetReduceResultTypeName(B); }))
-    genExportReduceResultType(ResultType);
+             // Compare
+             [](const RSExportType *A, const RSExportType *B)
+             { return GetReduceResultTypeName(A) < GetReduceResultTypeName(B); }))
+      genExportReduceResultType(ResultType);
+  }
+  mState->beginReduces(mRSContext->export_reduce_size());
   for (auto I = mRSContext->export_reduce_begin(),
             E = mRSContext->export_reduce_end();
        I != E; ++I)
     genExportReduce(*I);
+  mState->endReduces();
 
   // Reflect exported functions (invokable)
+  mState->beginInvokables(mRSContext->export_funcs_size());
   for (auto I = mRSContext->export_funcs_begin(),
             E = mRSContext->export_funcs_end();
        I != E; ++I)
     genExportFunction(*I);
+  mState->endInvokables();
 
-  endClass();
+  if (!mCollecting) {
+    if (mState->endOutputClass())
+      genCompute64Bit();
+
+    endClass();
+
+    mGeneratedFileNames->push_back(mScriptClassName);
+  }
 
   return true;
 }
@@ -500,7 +637,8 @@
     mOut.indent() << "super(rs, resources, id);\n";
   }
 
-  // If an exported variable has initial value, reflect it
+  // If an exported variable has initial value, reflect it.
+  // Keep this in sync with initialization handling in ReflectionState::declareVariable().
 
   for (auto I = mRSContext->export_vars_begin(),
             E = mRSContext->export_vars_end();
@@ -722,6 +860,12 @@
 void RSReflectionJava::genExportVariable(const RSExportVar *EV) {
   const RSExportType *ET = EV->getType();
 
+  const ReflectionState::Val32
+      AllocSize32 = mState->declareVariable(EV);
+
+  if (mCollecting)
+    return;
+
   mOut.indent() << "private final static int " << RS_EXPORT_VAR_INDEX_PREFIX
                 << EV->getName() << " = " << getNextExportVarSlot() << ";\n";
 
@@ -743,69 +887,83 @@
     break;
   }
   case RSExportType::ExportClassConstantArray: {
-    genConstantArrayTypeExportVariable(EV);
+    genConstantArrayTypeExportVariable(EV, AllocSize32);
     break;
   }
   case RSExportType::ExportClassRecord: {
-    genRecordTypeExportVariable(EV);
+    genRecordTypeExportVariable(EV, AllocSize32);
     break;
   }
   default: { slangAssert(false && "Unknown class of type"); }
   }
 }
 
+// Keep this in sync with Invokable analysis in ReflectionState::declareInvokable().
 void RSReflectionJava::genExportFunction(const RSExportFunc *EF) {
-  mOut.indent() << "private final static int " << RS_EXPORT_FUNC_INDEX_PREFIX
-                << EF->getName() << " = " << getNextExportFuncSlot() << ";\n";
+  mState->declareInvokable(EF);
+
+  if (!mCollecting) {
+    mOut.indent() << "private final static int " << RS_EXPORT_FUNC_INDEX_PREFIX
+                  << EF->getName() << " = " << getNextExportFuncSlot() << ";\n";
+  }
 
   // invoke_*()
   ArgTy Args;
 
-  if (EF->hasParam()) {
-    for (RSExportFunc::const_param_iterator I = EF->params_begin(),
-                                            E = EF->params_end();
-         I != E; I++) {
-      Args.push_back(
-          std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
+  if (!mCollecting) {
+    if (EF->hasParam()) {
+      for (RSExportFunc::const_param_iterator I = EF->params_begin(),
+                                              E = EF->params_end();
+           I != E; I++) {
+        Args.push_back(
+            std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
+      }
     }
+
+    if (mRSContext->getTargetAPI() >= SLANG_M_TARGET_API) {
+      startFunction(AM_Public, false, "Script.InvokeID",
+                    "getInvokeID_" + EF->getName(), 0);
+
+      mOut.indent() << "return createInvokeID(" << RS_EXPORT_FUNC_INDEX_PREFIX
+                    << EF->getName() << ");\n";
+
+      endFunction();
+    }
+
+    startFunction(AM_Public, false, "void",
+                  "invoke_" + EF->getName(/*Mangle=*/false),
+                  // We are using un-mangled name since Java
+                  // supports method overloading.
+                  Args);
   }
 
-  if (mRSContext->getTargetAPI() >= SLANG_M_TARGET_API) {
-    startFunction(AM_Public, false, "Script.InvokeID",
-                  "getInvokeID_" + EF->getName(), 0);
-
-    mOut.indent() << "return createInvokeID(" << RS_EXPORT_FUNC_INDEX_PREFIX
-                  << EF->getName() << ");\n";
-
-    endFunction();
-  }
-
-  startFunction(AM_Public, false, "void",
-                "invoke_" + EF->getName(/*Mangle=*/false),
-                // We are using un-mangled name since Java
-                // supports method overloading.
-                Args);
-
   if (!EF->hasParam()) {
-    mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
-                  << ");\n";
+    if (!mCollecting)
+      mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
+                    << ");\n";
   } else {
     const RSExportRecordType *ERT = EF->getParamPacketType();
+
+    // NOTE: This type isn't on the RSContext::export_types* list.
+    mState->declareRecord(ERT, false);
+
     std::string FieldPackerName = EF->getName() + "_fp";
 
-    if (genCreateFieldPacker(ERT, FieldPackerName.c_str()))
+    if (genCreateFieldPacker(ERT, FieldPackerName.c_str(),
+                             mState->getRecord32(ERT).getRecordAllocSize()))
       genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
 
-    mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
-                  << ", " << FieldPackerName << ");\n";
+    if (!mCollecting)
+      mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
+                    << ", " << FieldPackerName << ");\n";
   }
 
-  endFunction();
+  if (!mCollecting)
+    endFunction();
 }
 
 void RSReflectionJava::genPairwiseDimCheck(const std::string &name0,
                                            const std::string &name1) {
-
   mOut.indent() << "// Verify dimensions\n";
   mOut.indent() << "t0 = " << name0 << ".getType();\n";
   mOut.indent() << "t1 = " << name1 << ".getType();\n";
@@ -840,19 +998,28 @@
   mOut.indent() << "}\n";
 }
 
+// Keep this in sync with ForEach analysis in ReflectionState::beginForEach()
+// and other ReflectionState::*ForEach*() methods.
 void RSReflectionJava::genExportForEach(const RSExportForEach *EF) {
   if (EF->isDummyRoot()) {
-    // Skip reflection for dummy root() kernels. Note that we have to
-    // advance the next slot number for ForEach, however.
-    mOut.indent() << "//private final static int "
-                  << RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName() << " = "
-                  << getNextExportForEachSlot() << ";\n";
+    mState->declareForEachDummyRoot(EF);
+
+    if (!mCollecting) {
+      // Skip reflection for dummy root() kernels. Note that we have to
+      // advance the next slot number for ForEach, however.
+      mOut.indent() << "//private final static int "
+                    << RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName() << " = "
+                    << getNextExportForEachSlot() << ";\n";
+    }
+
     return;
   }
 
-  mOut.indent() << "private final static int " << RS_EXPORT_FOREACH_INDEX_PREFIX
-                << EF->getName() << " = " << getNextExportForEachSlot()
-                << ";\n";
+  if (!mCollecting) {
+    mOut.indent() << "private final static int " << RS_EXPORT_FOREACH_INDEX_PREFIX
+                  << EF->getName() << " = " << getNextExportForEachSlot()
+                  << ";\n";
+  }
 
   // forEach_*()
   ArgTy Args;
@@ -861,130 +1028,159 @@
   const RSExportForEach::InVec     &Ins     = EF->getIns();
   const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
   const RSExportType               *OET     = EF->getOutType();
+  const RSExportRecordType         *ERT     = EF->getParamPacketType();
+
+  mState->beginForEach(EF);
+
+  for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
+       BI != EI; BI++) {
+    mState->addForEachIn(EF, *BI);
+  }
 
   if (Ins.size() == 1) {
     HasAllocation = true;
-    Args.push_back(std::make_pair("Allocation", "ain"));
-
+    if (!mCollecting)
+      Args.push_back(std::make_pair("Allocation", "ain"));
   } else if (Ins.size() > 1) {
     HasAllocation = true;
-    for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
-         BI++) {
-
-      Args.push_back(std::make_pair("Allocation",
-                                    "ain_" + (*BI)->getName().str()));
+    if (!mCollecting) {
+      for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
+           BI++) {
+        Args.push_back(std::make_pair("Allocation",
+                                      "ain_" + (*BI)->getName().str()));
+      }
     }
   }
 
   if (EF->hasOut() || EF->hasReturn()) {
     HasAllocation = true;
-    Args.push_back(std::make_pair("Allocation", "aout"));
+    if (!mCollecting)
+      Args.push_back(std::make_pair("Allocation", "aout"));
   }
 
-  const RSExportRecordType *ERT = EF->getParamPacketType();
   if (ERT) {
     for (RSExportForEach::const_param_iterator I = EF->params_begin(),
                                                E = EF->params_end();
          I != E; I++) {
-      Args.push_back(
-          std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
+      mState->addForEachParam(EF, (*I)->getType());
+      if (!mCollecting)
+        Args.push_back(
+            std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
     }
   }
 
   if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
-    startFunction(AM_Public, false, "Script.KernelID",
-                  "getKernelID_" + EF->getName(), 0);
+    mState->addForEachSignatureMetadata(EF, EF->getSignatureMetadata());
 
-    // TODO: add element checking
-    mOut.indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX
-                  << EF->getName() << ", " << EF->getSignatureMetadata()
-                  << ", null, null);\n";
+    if (!mCollecting) {
+      startFunction(AM_Public, false, "Script.KernelID",
+                    "getKernelID_" + EF->getName(), 0);
 
-    endFunction();
-  }
-
-  if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) {
-    if (HasAllocation) {
-      startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
-
-      mOut.indent() << "forEach_" << EF->getName();
-      mOut << "(";
-
-      if (Ins.size() == 1) {
-        mOut << "ain, ";
-
-      } else if (Ins.size() > 1) {
-        for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
-             BI++) {
-
-          mOut << "ain_" << (*BI)->getName().str() << ", ";
-        }
-      }
-
-      if (EF->hasOut() || EF->hasReturn()) {
-        mOut << "aout, ";
-      }
-
-      if (EF->hasUsrData()) {
-        mOut << Args.back().second << ", ";
-      }
-
-      // No clipped bounds to pass in.
-      mOut << "null);\n";
+      // TODO: add element checking
+      mOut.indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX
+                    << EF->getName() << ", " << EF->getSignatureMetadata()
+                    << ", null, null);\n";
 
       endFunction();
     }
-
-    // Add the clipped kernel parameters to the Args list.
-    Args.push_back(std::make_pair("Script.LaunchOptions", "sc"));
   }
 
-  startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
+  if (!mCollecting) {
+    if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) {
+      if (HasAllocation) {
+        startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
 
-  if (InTypes.size() == 1) {
-    if (InTypes.front() != nullptr) {
-      genTypeCheck(InTypes.front(), "ain");
+        mOut.indent() << "forEach_" << EF->getName();
+        mOut << "(";
+
+        if (Ins.size() == 1) {
+          mOut << "ain, ";
+
+        } else if (Ins.size() > 1) {
+          for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
+               BI++) {
+
+            mOut << "ain_" << (*BI)->getName().str() << ", ";
+          }
+        }
+
+        if (EF->hasOut() || EF->hasReturn()) {
+          mOut << "aout, ";
+        }
+
+        if (EF->hasUsrData()) {
+          mOut << Args.back().second << ", ";
+        }
+
+        // No clipped bounds to pass in.
+        mOut << "null);\n";
+
+        endFunction();
+      }
+
+      // Add the clipped kernel parameters to the Args list.
+      Args.push_back(std::make_pair("Script.LaunchOptions", "sc"));
     }
+  }
 
-  } else if (InTypes.size() > 1) {
-    size_t Index = 0;
-    for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
-         BI != EI; BI++, ++Index) {
+  if (!mCollecting) {
+    startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
 
-      if (*BI != nullptr) {
-        genTypeCheck(*BI, ("ain_" + Ins[Index]->getName()).str().c_str());
+    if (InTypes.size() == 1) {
+      if (InTypes.front() != nullptr) {
+        genTypeCheck(InTypes.front(), "ain");
+      }
+
+    } else if (InTypes.size() > 1) {
+      size_t Index = 0;
+      for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
+           BI != EI; BI++, ++Index) {
+
+        if (*BI != nullptr) {
+          genTypeCheck(*BI, ("ain_" + Ins[Index]->getName()).str().c_str());
+        }
       }
     }
-  }
 
-  if (OET) {
-    genTypeCheck(OET, "aout");
-  }
-
-  if (Ins.size() == 1 && (EF->hasOut() || EF->hasReturn())) {
-    mOut.indent() << "Type t0, t1;";
-    genPairwiseDimCheck("ain", "aout");
-
-  } else if (Ins.size() > 1) {
-    mOut.indent() << "Type t0, t1;";
-
-    std::string In0Name = "ain_" + Ins[0]->getName().str();
-
-    for (size_t index = 1; index < Ins.size(); ++index) {
-      genPairwiseDimCheck(In0Name, "ain_" + Ins[index]->getName().str());
+    if (OET) {
+      genTypeCheck(OET, "aout");
     }
 
-    if (EF->hasOut() || EF->hasReturn()) {
-      genPairwiseDimCheck(In0Name, "aout");
+    if (Ins.size() == 1 && (EF->hasOut() || EF->hasReturn())) {
+      mOut.indent() << "Type t0, t1;";
+      genPairwiseDimCheck("ain", "aout");
+
+    } else if (Ins.size() > 1) {
+      mOut.indent() << "Type t0, t1;";
+
+      std::string In0Name = "ain_" + Ins[0]->getName().str();
+
+      for (size_t index = 1; index < Ins.size(); ++index) {
+        genPairwiseDimCheck(In0Name, "ain_" + Ins[index]->getName().str());
+      }
+
+      if (EF->hasOut() || EF->hasReturn()) {
+        genPairwiseDimCheck(In0Name, "aout");
+      }
     }
   }
 
   std::string FieldPackerName = EF->getName() + "_fp";
   if (ERT) {
-    if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
+    // NOTE: This type isn't on the RSContext::export_types* list.
+    mState->declareRecord(ERT, false);
+
+    if (genCreateFieldPacker(ERT, FieldPackerName.c_str(),
+                             mState->getRecord32(ERT).getRecordAllocSize())) {
       genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
     }
   }
+
+  mState->endForEach();
+
+  if (mCollecting)
+    return;
+
   mOut.indent() << "forEach(" << RS_EXPORT_FOREACH_INDEX_PREFIX
                 << EF->getName();
 
@@ -1075,8 +1271,17 @@
 
 } // end anonymous namespace
 
+// Keep this in sync with Reduce analysis in ReflectionState::declareReduce().
 void RSReflectionJava::genExportReduce(const RSExportReduce *ER) {
-  if (!exportableReduce(ER->getResultType()))
+  const bool IsExportable = exportableReduce(ER->getResultType());
+
+  // Need to track even a non-exportable reduce, both so that we get
+  // the count of reduction kernels correct, and so that we can
+  // intelligently diagnose cases where 32-bit and 64-bit compiles
+  // disagree as to whether a reduction kernel is exportable.
+  mState->declareReduce(ER, IsExportable);
+
+  if (!IsExportable || mCollecting)
     return;
 
   // Generate the reflected function index.
@@ -1817,7 +2022,7 @@
                   TypeName.c_str(), "v");
     mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
 
-    if (genCreateFieldPacker(ET, FieldPackerName))
+    if (genCreateFieldPacker(ET, FieldPackerName, ReflectionState::NoVal32()))
       genPackVarOfType(ET, "v", FieldPackerName);
     mOut.indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", "
                   << FieldPackerName << ");\n";
@@ -1830,7 +2035,8 @@
 }
 
 void
-RSReflectionJava::genConstantArrayTypeExportVariable(const RSExportVar *EV) {
+RSReflectionJava::genConstantArrayTypeExportVariable(const RSExportVar *EV,
+                                                     ReflectionState::Val32 AllocSize32) {
   const RSExportType *const ET = EV->getType();
   slangAssert(
       (ET->getClass() == RSExportType::ExportClassConstantArray) &&
@@ -1840,12 +2046,15 @@
   std::string VarName = EV->getName();
 
   genPrivateExportVariable(TypeName, VarName);
-  genSetExportVariable(TypeName, EV, static_cast<const RSExportConstantArrayType *>(ET)->getNumElement());
+  genSetExportVariable(TypeName, EV,
+                       static_cast<const RSExportConstantArrayType *>(ET)->getNumElement(),
+                       AllocSize32);
   genGetExportVariable(TypeName, VarName);
   genGetFieldID(VarName);
 }
 
-void RSReflectionJava::genRecordTypeExportVariable(const RSExportVar *EV) {
+void RSReflectionJava::genRecordTypeExportVariable(const RSExportVar *EV,
+                                                   ReflectionState::Val32 AllocSize32) {
   slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
               "Variable should be type of struct here");
 
@@ -1853,7 +2062,7 @@
   std::string VarName = EV->getName();
 
   genPrivateExportVariable(TypeName, VarName);
-  genSetExportVariable(TypeName, EV, 1);
+  genSetExportVariable(TypeName, EV, 1, AllocSize32);
   genGetExportVariable(TypeName, VarName);
   genGetFieldID(VarName);
 }
@@ -1867,7 +2076,8 @@
 // Dimension = array element count; otherwise, 1.
 void RSReflectionJava::genSetExportVariable(const std::string &TypeName,
                                             const RSExportVar *EV,
-                                            unsigned Dimension) {
+                                            unsigned Dimension,
+                                            ReflectionState::Val32 AllocSize32) {
   if (!EV->isConst()) {
     const char *FieldPackerName = "fp";
     const std::string &VarName = EV->getName();
@@ -1876,7 +2086,7 @@
                   TypeName.c_str(), "v");
     mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
 
-    if (genCreateFieldPacker(ET, FieldPackerName))
+    if (genCreateFieldPacker(ET, FieldPackerName, AllocSize32))
       genPackVarOfType(ET, "v", FieldPackerName);
 
     if (mRSContext->getTargetAPI() < SLANG_JB_TARGET_API) {
@@ -1922,11 +2132,17 @@
 /******************* Methods to generate script class /end *******************/
 
 bool RSReflectionJava::genCreateFieldPacker(const RSExportType *ET,
-                                            const char *FieldPackerName) {
+                                            const char *FieldPackerName,
+                                            ReflectionState::Val32 AllocSize32) {
   size_t AllocSize = ET->getAllocSize();
-  if (AllocSize > 0)
-    mOut.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
-                  << AllocSize << ");\n";
+  slangAssert(!AllocSize32.first || ((AllocSize == 0) == (AllocSize32.second == 0)));
+  if (AllocSize > 0) {
+    if (!mCollecting) {
+      mOut.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(";
+      genConditionalVal("", false, AllocSize, AllocSize32);
+      mOut << ");\n";
+    }
+  }
   else
     return false;
   return true;
@@ -1935,6 +2151,9 @@
 void RSReflectionJava::genPackVarOfType(const RSExportType *ET,
                                         const char *VarName,
                                         const char *FieldPackerName) {
+  if (mCollecting)
+    return;
+
   switch (ET->getClass()) {
   case RSExportType::ExportClassPrimitive:
   case RSExportType::ExportClassVector: {
@@ -1994,13 +2213,33 @@
     break;
   }
   case RSExportType::ExportClassRecord: {
+    // Keep struct/field layout in sync with ReflectionState::declareRecord()
+
     const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
+    const ReflectionState::Record32 Record32 = mState->getRecord32(ERT);
+
+    auto emitSkip = [this, &FieldPackerName](size_t At, size_t Need,
+                                             ReflectionState::Val32 Padding32) {
+      if ((Need > At) || (Padding32.first && (Padding32.second != 0))) {
+        size_t Padding = Need - At;
+        mOut.indent() << FieldPackerName << ".skip(";
+        if (!Padding32.first || (Padding == Padding32.second))
+          mOut << Padding;
+        else {
+          genCheck64Bit(true);
+          mOut << " ? " << Padding << " : " << Padding32.second;
+        }
+        mOut << ");\n";
+      }
+    };
+
     // Relative pos from now on in field packer
     unsigned Pos = 0;
 
+    unsigned FieldNum = 0;
     for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
                                                   E = ERT->fields_end();
-         I != E; I++) {
+         I != E; I++, FieldNum++) {
       const RSExportRecordType::Field *F = *I;
       std::string FieldName;
       size_t FieldOffset = F->getOffsetInParent();
@@ -2008,32 +2247,25 @@
       size_t FieldStoreSize = T->getStoreSize();
       size_t FieldAllocSize = T->getAllocSize();
 
+      const auto Field32PreAndPostPadding = Record32.getFieldPreAndPostPadding(FieldNum);
+
       if (VarName != nullptr)
         FieldName = VarName + ("." + F->getName());
       else
         FieldName = F->getName();
 
-      if (FieldOffset > Pos) {
-        mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
-                      << ");\n";
-      }
+      emitSkip(Pos, FieldOffset, Field32PreAndPostPadding.first /* pre */);
 
       genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
 
-      // There is padding in the field type
-      if (FieldAllocSize > FieldStoreSize) {
-        mOut.indent() << FieldPackerName << ".skip("
-                      << (FieldAllocSize - FieldStoreSize) << ");\n";
-      }
+      // There is padding in the field type?
+      emitSkip(FieldStoreSize, FieldAllocSize, Field32PreAndPostPadding.second /* post */);
 
       Pos = FieldOffset + FieldAllocSize;
     }
 
     // There maybe some padding after the struct
-    if (ERT->getAllocSize() > Pos) {
-      mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
-                    << ");\n";
-    }
+    emitSkip(Pos, ERT->getAllocSize(), Record32.getRecordPostPadding());
     break;
   }
   default: { slangAssert(false && "Unknown class of type"); }
@@ -2110,6 +2342,10 @@
 /********************** Methods to generate type class  **********************/
 bool RSReflectionJava::genTypeClass(const RSExportRecordType *ERT,
                                     std::string &ErrorMsg) {
+  mState->declareRecord(ERT);
+  if (mCollecting)
+    return true;
+
   std::string ClassName = ERT->getElementName();
   std::string superClassName = getRSPackageName();
   superClassName += RS_TYPE_CLASS_SUPER_CLASS_NAME;
@@ -2120,6 +2356,8 @@
 
   mGeneratedFileNames->push_back(ClassName);
 
+  mState->beginOutputClass();
+
   genTypeItemClass(ERT);
 
   // Declare item buffer and item buffer packer
@@ -2144,6 +2382,9 @@
     genTypeClassResize();
   }
 
+  if (mState->endOutputClass())
+    genCompute64Bit();
+
   endClass();
 
   resetFieldIndex();
@@ -2201,7 +2442,7 @@
   //            << ".get();\n";
   // mOut.indent() << "if (e != null) return e;\n";
   RSReflectionJavaElementBuilder builder("eb", ERT, RenderScriptVar, &mOut,
-                                         mRSContext, this);
+                                         mRSContext, this, mState);
   builder.generate();
 
   mOut.indent() << "return eb.create();\n";
@@ -2360,13 +2601,18 @@
 
 void
 RSReflectionJava::genTypeClassComponentSetter(const RSExportRecordType *ERT) {
+  const ReflectionState::Record32 Record32 = mState->getRecord32(ERT);
+
+  unsigned FieldNum = 0;
   for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
                                                 FE = ERT->fields_end();
-       FI != FE; FI++) {
+       FI != FE; FI++, FieldNum++) {
     const RSExportRecordType::Field *F = *FI;
     size_t FieldOffset = F->getOffsetInParent();
     size_t FieldStoreSize = F->getType()->getStoreSize();
-    unsigned FieldIndex = getFieldIndex(F);
+    std::pair<unsigned, unsigned> FieldIndex = getFieldIndex(F);
+
+    const auto Field32OffsetAndStoreSize = Record32.getFieldOffsetAndStoreSize(FieldNum);
 
     startFunction(AM_PublicSynchronized, false, "void", "set_" + F->getName(),
                   3, "int", "index", GetTypeName(F->getType()).c_str(), "v",
@@ -2379,21 +2625,22 @@
     mOut.indent() << "if (copyNow) ";
     mOut.startBlock();
 
-    if (FieldOffset > 0) {
-      mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
-                    << mItemSizeof << " + " << FieldOffset
-                    << ");\n";
-    } else {
-      mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
-                    << mItemSizeof << ");\n";
-    }
+    mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
+                  << mItemSizeof;
+    genConditionalVal(" + ", true, FieldOffset, Field32OffsetAndStoreSize.first /* offset */);
+    mOut << ");\n";
+
     genPackVarOfType(F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
 
-    mOut.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize
-                  << ");\n";
+    mOut.indent() << "FieldPacker fp = new FieldPacker(";
+    genConditionalVal("", false, FieldStoreSize, Field32OffsetAndStoreSize.second /* size */);
+    mOut << ");\n";
+
     genPackVarOfType(F->getType(), "v", "fp");
-    mOut.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex
-                  << ", fp);\n";
+    mOut.indent() << "mAllocation.setFromFieldPacker(index, ";
+    genConditionalVal("", false, FieldIndex.first,
+                      ReflectionState::Val32(Field32OffsetAndStoreSize.first.first, FieldIndex.second));
+    mOut << ", fp);\n";
 
     // End of if (copyNow)
     mOut.endBlock();
@@ -2461,10 +2708,10 @@
 RSReflectionJavaElementBuilder::RSReflectionJavaElementBuilder(
     const char *ElementBuilderName, const RSExportRecordType *ERT,
     const char *RenderScriptVar, GeneratedFile *Out, const RSContext *RSContext,
-    RSReflectionJava *Reflection)
+    RSReflectionJava *Reflection, ReflectionState *RState)
     : mElementBuilderName(ElementBuilderName), mERT(ERT),
       mRenderScriptVar(RenderScriptVar), mOut(Out), mPaddingFieldIndex(1),
-      mRSContext(RSContext), mReflection(Reflection) {
+      mRSContext(RSContext), mReflection(Reflection), mState(RState) {
   if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
     mPaddingPrefix = "#padding_";
   } else {
@@ -2544,18 +2791,26 @@
       //
       // TODO(zonr): Generalize these two function such that there's no
       //             duplicated codes.
+
+      // Keep struct/field layout in sync with ReflectionState::declareRecord()
+
       const RSExportRecordType *ERT =
           static_cast<const RSExportRecordType *>(ET);
+      const ReflectionState::Record32 Record32 = mState->getRecord32(ERT);
+
       int Pos = 0; // relative pos from now on
 
+      unsigned FieldNum = 0;
       for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
                                                     E = ERT->fields_end();
-           I != E; I++) {
+           I != E; I++, FieldNum++) {
         const RSExportRecordType::Field *F = *I;
-        int FieldOffset = F->getOffsetInParent();
+        size_t FieldOffset = F->getOffsetInParent();
         const RSExportType *T = F->getType();
-        int FieldStoreSize = T->getStoreSize();
-        int FieldAllocSize = T->getAllocSize();
+        size_t FieldStoreSize = T->getStoreSize();
+        size_t FieldAllocSize = T->getAllocSize();
+
+        const auto Field32PreAndPostPadding = Record32.getFieldPreAndPostPadding(FieldNum);
 
         std::string FieldName;
         if (!VarName.empty())
@@ -2564,7 +2819,7 @@
           FieldName = F->getName();
 
         // Alignment
-        genAddPadding(FieldOffset - Pos);
+        genAddPadding(FieldOffset - Pos, Field32PreAndPostPadding.first /* pre */);
 
         // eb.add(...)
         mReflection->addFieldIndexMapping(F);
@@ -2579,7 +2834,7 @@
         if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
           // There is padding within the field type. This is only necessary
           // for HC-targeted APIs.
-          genAddPadding(FieldAllocSize - FieldStoreSize);
+          genAddPadding(FieldAllocSize - FieldStoreSize, Field32PreAndPostPadding.second /* post */);
         }
 
         Pos = FieldOffset + FieldAllocSize;
@@ -2587,8 +2842,7 @@
 
       // There maybe some padding after the struct
       size_t RecordAllocSize = ERT->getAllocSize();
-
-      genAddPadding(RecordAllocSize - Pos);
+      genAddPadding(RecordAllocSize - Pos, Record32.getRecordPostPadding());
       break;
     }
     default:
@@ -2598,7 +2852,7 @@
   }
 }
 
-void RSReflectionJavaElementBuilder::genAddPadding(int PaddingSize) {
+void RSReflectionJavaElementBuilder::genAddPadding(int PaddingSize, unsigned Which) {
   while (PaddingSize > 0) {
     const std::string &VarName = createPaddingField();
     genAddStatementStart();
@@ -2612,17 +2866,60 @@
       *mOut << "Element.U8(" << mRenderScriptVar << ")";
       PaddingSize -= 1;
     }
-    genAddStatementEnd(VarName, 0);
+    genAddStatementEnd(VarName, 0, Which);
   }
 }
 
+void RSReflectionJavaElementBuilder::genAddPadding(int PaddingSize,
+                                                   ReflectionState::Val32 Field32PaddingSize) {
+  if (!Field32PaddingSize.first || (PaddingSize == Field32PaddingSize.second)) {
+    // Either we're ignoring the 32-bit case, or 32-bit and 64-bit
+    // padding are the same.
+    genAddPadding(PaddingSize, RSReflectionJava::FieldIndex | RSReflectionJava::Field32Index);
+    return;
+  }
+
+  // We cannot ignore the 32-bit case, and 32-bit and 64-bit padding differ.
+
+  if ((PaddingSize == 0) != (Field32PaddingSize.second == 0)) {
+    // Only pad one of the two cases.
+
+    mOut->indent() << "if (";
+    if (PaddingSize == 0)
+      *mOut << '!';
+    genCheck64Bit(PaddingSize == 0);
+    *mOut << ')';
+
+    mOut->startBlock();
+    if (PaddingSize != 0)
+      genAddPadding(PaddingSize, RSReflectionJava::FieldIndex);
+    else
+      genAddPadding(Field32PaddingSize.second, RSReflectionJava::Field32Index);
+    mOut->endBlock();
+    return;
+  }
+
+  // Pad both of the two cases, differently.
+  mOut->indent() << "if (";
+  genCheck64Bit(false);
+  *mOut << ')';
+  mOut->startBlock();
+  genAddPadding(PaddingSize, RSReflectionJava::FieldIndex);
+  mOut->endBlock();
+  mOut->indent() << "else";
+  mOut->startBlock();
+  genAddPadding(Field32PaddingSize.second, RSReflectionJava::Field32Index);
+  mOut->endBlock();
+}
+
 void RSReflectionJavaElementBuilder::genAddStatementStart() {
   mOut->indent() << mElementBuilderName << ".add(";
 }
 
 void
 RSReflectionJavaElementBuilder::genAddStatementEnd(const std::string &VarName,
-                                                   unsigned ArraySize) {
+                                                   unsigned ArraySize,
+                                                   unsigned Which) {
   *mOut << ", \"" << VarName << "\"";
   if (ArraySize > 0) {
     *mOut << ", " << ArraySize;
@@ -2631,12 +2928,16 @@
   // TODO Review incFieldIndex.  It's probably better to assign the numbers at
   // the start rather
   // than as we're generating the code.
-  mReflection->incFieldIndex();
+  mReflection->incFieldIndex(Which);
 }
 
 /******** Methods to create Element in Java of given record type /end ********/
 
 bool RSReflectionJava::reflect() {
+  // Note that we may issue declareRecord() in many places during the
+  // reflection process.
+  mState->beginRecords();
+
   std::string ErrorMsg;
   if (!genScriptClass(mScriptClassName, ErrorMsg)) {
     std::cerr << "Failed to generate class " << mScriptClassName << " ("
@@ -2644,8 +2945,6 @@
     return false;
   }
 
-  mGeneratedFileNames->push_back(mScriptClassName);
-
   // class ScriptField_<TypeName>
   for (RSContext::const_export_type_iterator
            TI = mRSContext->export_types_begin(),
@@ -2665,6 +2964,8 @@
     }
   }
 
+  mState->endRecords();
+
   return true;
 }
 
@@ -2707,6 +3008,17 @@
   mOut << "\n";
 
   // Imports
+  //
+  // The first few imports are only needed for divergent classes, but
+  // at this point we don't know whether we are emitting a divergent
+  // class.
+  //
+  if (!mRSContext->isCompatLib()) {
+    mOut << "import android.os.Build;\n";
+    mOut << "import android.os.Process;\n";
+    mOut << "import java.lang.reflect.Field;\n";
+  }
+  // (End of imports needed for divergent classes.)
   mOut << "import " << mRSPackageName << ".*;\n";
   if (getEmbedBitcodeInJava()) {
     mOut << "import " << mPackageName << "."
diff --git a/slang_rs_reflection.h b/slang_rs_reflection.h
index 7d54a6a..4d2f795 100644
--- a/slang_rs_reflection.h
+++ b/slang_rs_reflection.h
@@ -29,6 +29,7 @@
 #include "slang_assert.h"
 #include "slang_rs_export_type.h"
 #include "slang_rs_reflect_utils.h"
+#include "slang_rs_reflection_state.h"
 
 namespace slang {
 
@@ -41,6 +42,13 @@
 private:
   const RSContext *mRSContext;
 
+  ReflectionState *mState;
+
+  // If we're in the "collecting" state (according to mState), we
+  // don't actually generate code, but we do want to keep track of
+  // some information about what we WOULD generate.
+  const bool mCollecting;
+
   // The name of the Java package name we're creating this file for,
   // e.g. com.example.android.rs.flashlight
   std::string mPackageName;
@@ -69,7 +77,6 @@
   // e.g. ScriptC_flashlight
   std::string mScriptClassName;
 
-
   // This is set by startClass() and will change for the multiple classes generated.
   std::string mClassName;
 
@@ -90,10 +97,16 @@
 
   // A mapping from a field in a record type to its index in the rsType
   // instance. Only used when generates TypeClass (ScriptField_*).
-  typedef std::map<const RSExportRecordType::Field *, unsigned> FieldIndexMapTy;
+  //
+  // .first = field index
+  // .second = when compiling for both 32-bit and 64-bit (RSCCOptions::mEmit3264),
+  //           and we are reflecting 64-bit code, this is field index for 32-bit;
+  //           otherwise, it is undefined
+  typedef std::map<const RSExportRecordType::Field *, std::pair<unsigned,unsigned> > FieldIndexMapTy;
   FieldIndexMapTy mFieldIndexMap;
   // Field index of current processing TypeClass.
-  unsigned mFieldIndex;
+  unsigned mFieldIndex;    // corresponds to FieldIndexMapTy::mapped_type.first
+  unsigned mField32Index;  // corresponds to FieldIndexMapTy::mapped_type.second
 
   inline void setError(const std::string &Error) { mLastError = Error; }
 
@@ -152,17 +165,22 @@
   void startTypeClass(const std::string &ClassName);
   void endTypeClass();
 
-  inline void incFieldIndex() { mFieldIndex++; }
+  enum { FieldIndex = 0x1, Field32Index = 0x2 };  // bitmask
+  inline void incFieldIndex(unsigned Which) {
+    slangAssert(!(Which & ~(FieldIndex | Field32Index)));
+    if (Which & FieldIndex  ) mFieldIndex++;
+    if (Which & Field32Index) mField32Index++;
+  }
 
-  inline void resetFieldIndex() { mFieldIndex = 0; }
+  inline void resetFieldIndex() { mFieldIndex = mField32Index = 0; }
 
   inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
     slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
                 "Nested structure never occurs in C language.");
-    mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
+    mFieldIndexMap.insert(std::make_pair(F, std::make_pair(mFieldIndex, mField32Index)));
   }
 
-  inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
+  inline std::pair<unsigned, unsigned> getFieldIndex(const RSExportRecordType::Field *F) const {
     FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
     slangAssert((I != mFieldIndexMap.end()) &&
                 "Requesting field is out of scope.");
@@ -171,6 +189,22 @@
 
   inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
 
+  enum {
+    TypeNameWithConstantArrayBrackets = 0x01,
+    TypeNameWithRecordElementName     = 0x02,
+
+    // Three major flavors of types:
+    // - Java
+    // - C
+    // - PseudoC -- Identical to C for all types supported by C;
+    //              for other types, uses a simplified C-like syntax
+    TypeNameC                         = 0x04,
+    TypeNamePseudoC                   = 0x08,
+
+    TypeNameDefault                   = TypeNameWithConstantArrayBrackets|TypeNameWithRecordElementName
+  };
+  static std::string GetTypeName(const RSExportType *ET, unsigned Style = TypeNameDefault);
+
 private:
   static bool exportableReduce(const RSExportType *ResultType);
 
@@ -189,11 +223,12 @@
   void genPointerTypeExportVariable(const RSExportVar *EV);
   void genVectorTypeExportVariable(const RSExportVar *EV);
   void genMatrixTypeExportVariable(const RSExportVar *EV);
-  void genConstantArrayTypeExportVariable(const RSExportVar *EV);
-  void genRecordTypeExportVariable(const RSExportVar *EV);
+  void genConstantArrayTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
+  void genRecordTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
   void genPrivateExportVariable(const std::string &TypeName,
                                 const std::string &VarName);
-  void genSetExportVariable(const std::string &TypeName, const RSExportVar *EV, unsigned Dimension);
+  void genSetExportVariable(const std::string &TypeName, const RSExportVar *EV, unsigned Dimension,
+                            ReflectionState::Val32 AllocSize32 = ReflectionState::NoVal32());
   void genGetExportVariable(const std::string &TypeName,
                             const std::string &VarName);
   void genGetFieldID(const std::string &VarName);
@@ -227,6 +262,14 @@
   void genTypeClassCopyAll(const RSExportRecordType *ERT);
   void genTypeClassResize();
 
+  // emits an expression that evaluates to true on a 64-bit target and
+  // false on a 32-bit target
+  void genCheck64Bit(bool Parens);
+
+  // emits a fragment of the class definition needed to set up for
+  // genCheck64Bit()
+  void genCompute64Bit();
+
   void genBuildElement(const char *ElementBuilderName,
                        const RSExportRecordType *ERT,
                        const char *RenderScriptVar, bool IsInline);
@@ -236,7 +279,8 @@
                                      const char *RenderScriptVar,
                                      unsigned ArraySize);
 
-  bool genCreateFieldPacker(const RSExportType *T, const char *FieldPackerName);
+  bool genCreateFieldPacker(const RSExportType *T, const char *FieldPackerName,
+                            ReflectionState::Val32 AllocSize32);
   void genPackVarOfType(const RSExportType *T, const char *VarName,
                         const char *FieldPackerName);
   void genAllocateVarOfType(const RSExportType *T, const std::string &VarName);
@@ -247,13 +291,26 @@
   void genVectorLengthCompatibilityCheck(const std::string &ArrayName, unsigned VecSize);
   void genNullArrayCheck(const std::string &ArrayName);
 
+  // NOTE
+  //
+  // If there's a nonempty Prefix, then:
+  // - If there's a nonzero value to emit, then emit the prefix followed by the value.
+  // - Otherwise, emit nothing.
+  //
+  // If there's an empty Prefix, then
+  // - Always emit a value, even if zero.
+  //
+  void genConditionalVal(const std::string &Prefix, bool Parens,
+                         size_t Val, ReflectionState::Val32 Val32);
+
 public:
   RSReflectionJava(const RSContext *Context,
                    std::vector<std::string> *GeneratedFileNames,
                    const std::string &OutputBaseDirectory,
                    const std::string &RSSourceFilename,
                    const std::string &BitCodeFileName,
-                   bool EmbedBitcodeInJava);
+                   bool EmbedBitcodeInJava,
+                   ReflectionState *RState);
 
   bool reflect();
 
diff --git a/slang_rs_reflection_state.cpp b/slang_rs_reflection_state.cpp
new file mode 100644
index 0000000..aac03e3
--- /dev/null
+++ b/slang_rs_reflection_state.cpp
@@ -0,0 +1,1127 @@
+/*
+ * 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 <algorithm>
+#include <iostream>
+#include <string>
+
+#include "clang/AST/APValue.h"
+
+#include "slang_assert.h"
+#include "slang_rs_export_foreach.h"
+#include "slang_rs_export_func.h"
+#include "slang_rs_export_reduce.h"
+#include "slang_rs_export_type.h"
+#include "slang_rs_export_var.h"
+#include "slang_rs_reflection.h"
+#include "slang_rs_reflection_state.h"
+
+#include "bcinfo/MetadataExtractor.h"
+
+namespace slang {
+
+static bool equal(const clang::APValue &a, const clang::APValue &b) {
+  if (a.getKind() != b.getKind())
+    return false;
+  switch (a.getKind()) {
+    case clang::APValue::Float:
+      return a.getFloat().bitwiseIsEqual(b.getFloat());
+    case clang::APValue::Int:
+      return a.getInt() == b.getInt();
+    case clang::APValue::Vector: {
+      unsigned NumElements = a.getVectorLength();
+      if (NumElements != b.getVectorLength())
+        return false;
+      for (unsigned i = 0; i < NumElements; ++i) {
+        if (!equal(a.getVectorElt(i), b.getVectorElt(i)))
+          return false;
+      }
+      return true;
+    }
+    default:
+      slangAssert(false && "unexpected APValue kind");
+      return false;
+  }
+}
+
+ReflectionState::~ReflectionState() {
+  slangAssert(mState==S_Initial || mState==S_ClosedJava64 || mState==S_Bad);
+  delete mStringSet;
+}
+
+void ReflectionState::openJava32(size_t NumFiles) {
+  if (kDisabled)
+    return;
+  slangAssert(mState==S_Initial);
+  mState = S_OpenJava32;
+  mStringSet = new llvm::StringSet<>;
+  mFiles.BeginCollecting(NumFiles);
+}
+
+void ReflectionState::closeJava32() {
+  if (kDisabled)
+    return;
+  slangAssert(mState==S_OpenJava32 && (mForEachOpen < 0) && !mOutputClassOpen && (mRecordsState != RS_Open));
+  mState = S_ClosedJava32;
+  mRSC = nullptr;
+}
+
+void ReflectionState::openJava64() {
+  if (kDisabled)
+    return;
+  slangAssert(mState==S_ClosedJava32);
+  mState = S_OpenJava64;
+  mFiles.BeginUsing();
+}
+
+void ReflectionState::closeJava64() {
+  if (kDisabled)
+    return;
+  slangAssert(mState==S_OpenJava64 && (mForEachOpen < 0) && !mOutputClassOpen && (mRecordsState != RS_Open));
+  mState = S_ClosedJava64;
+  mRSC = nullptr;
+}
+
+llvm::StringRef ReflectionState::canon(const std::string &String) {
+  slangAssert(isCollecting());
+  return mStringSet->insert(String).first->getKey();
+}
+
+std::string ReflectionState::getUniqueTypeName(const RSExportType *T) {
+  return RSReflectionJava::GetTypeName(T, RSReflectionJava::TypeNamePseudoC);
+}
+
+void ReflectionState::nextFile(const RSContext *RSC,
+                               const std::string &PackageName,
+                               const std::string &RSSourceFileName) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  mRSC = RSC;
+
+  slangAssert(mRecordsState != RS_Open);
+  mRecordsState = RS_Initial;
+
+  if (isCollecting()) {
+    File &file = mFiles.CollectNext();
+    file.mPackageName = PackageName;
+    file.mRSSourceFileName = RSSourceFileName;
+  }
+  if (isUsing()) {
+    File &file = mFiles.UseNext();
+    slangAssert(file.mRSSourceFileName == RSSourceFileName);
+    if (file.mPackageName != PackageName)
+      mRSC->ReportError("in file '%0' Java package name is '%1' for 32-bit targets "
+                        "but '%2' for 64-bit targets")
+          << RSSourceFileName << file.mPackageName << PackageName;
+  }
+}
+
+void ReflectionState::dump() {
+  const size_t NumFiles = mFiles.Size();
+  for (int i = 0; i < NumFiles; ++i) {
+    const File &file = mFiles[i];
+    std::cout << "file = \"" << file.mRSSourceFileName << "\", "
+              << "package = \"" << file.mPackageName << "\"" << std::endl;
+
+    // NOTE: "StringMap iteration order, however, is not guaranteed to
+    // be deterministic".  So sort before dumping.
+    typedef const llvm::StringMap<File::Record>::MapEntryTy *RecordsEntryTy;
+    std::vector<RecordsEntryTy> Records;
+    Records.reserve(file.mRecords.size());
+    for (auto I = file.mRecords.begin(), E = file.mRecords.end(); I != E; I++)
+      Records.push_back(&(*I));
+    std::sort(Records.begin(), Records.end(),
+              [](RecordsEntryTy a, RecordsEntryTy b) { return a->getKey().compare(b->getKey())==-1; });
+    for (auto Record : Records) {
+      const auto &Val = Record->getValue();
+      std::cout << "  (Record) name=\"" << Record->getKey().str() << "\""
+                << " allocSize=" << Val.mAllocSize
+                << " postPadding=" << Val.mPostPadding
+                << " ordinary=" << Val.mOrdinary
+                << " matchedByName=" << Val.mMatchedByName
+                << std::endl;
+      const size_t NumFields = Val.mFieldCount;
+      for (int fieldIdx = 0; fieldIdx < NumFields; ++fieldIdx) {
+        const auto &field = Val.mFields[fieldIdx];
+        std::cout << "    (Field) name=\"" << field.mName << "\" ("
+                  << field.mPrePadding << ", \"" << field.mType.str()
+                  << "\"(" << field.mStoreSize << ")@" << field.mOffset
+                  << ", " << field.mPostPadding << ")" << std::endl;
+      }
+    }
+
+    const size_t NumVars = file.mVariables.Size();
+    for (int varIdx = 0; varIdx < NumVars; ++varIdx) {
+      const auto &var = file.mVariables[varIdx];
+      std::cout << "  (Var) name=\"" << var.mName << "\" type=\"" << var.mType.str()
+                << "\" const=" << var.mIsConst << " initialized=" << (var.mInitializerCount != 0)
+                << " allocSize=" << var.mAllocSize << std::endl;
+    }
+
+    for (int feIdx = 0; feIdx < file.mForEachCount; ++feIdx) {
+      const auto &fe = file.mForEaches[feIdx];
+      std::cout << "  (ForEach) ordinal=" << feIdx << " state=";
+      switch (fe.mState) {
+        case File::ForEach::S_Initial:
+          std::cout << "initial" << std::endl;
+          continue;
+        case File::ForEach::S_Collected:
+          std::cout << "collected";
+          break;
+        case File::ForEach::S_UseMatched:
+          std::cout << "usematched";
+          break;
+        default:
+          std::cout << fe.mState;
+          break;
+      }
+      std::cout << " name=\"" << fe.mName << "\" kernel=" << fe.mIsKernel
+                << " hasOut=" << fe.mHasOut << " out=\"" << fe.mOut.str()
+                << "\" metadata=0x" << std::hex << fe.mSignatureMetadata << std::dec
+                << std::endl;
+      const size_t NumIns = fe.mIns.Size();
+      for (int insIdx = 0; insIdx < NumIns; ++insIdx)
+        std::cout << "    (In) " << fe.mIns[insIdx].str() << std::endl;
+      const size_t NumParams = fe.mParams.Size();
+      for (int paramsIdx = 0; paramsIdx < NumParams; ++paramsIdx)
+        std::cout << "    (Param) " << fe.mParams[paramsIdx].str() << std::endl;
+    }
+
+    for (auto feBad : mForEachesBad) {
+      std::cout << "  (ForEachBad) ordinal=" << feBad->getOrdinal()
+                << " name=\"" << feBad->getName() << "\""
+                << std::endl;
+    }
+
+    const size_t NumInvokables = file.mInvokables.Size();
+    for (int invIdx = 0; invIdx < NumInvokables; ++invIdx) {
+      const auto &inv = file.mInvokables[invIdx];
+      std::cout << "  (Invokable) name=\"" << inv.mName << "\"" << std::endl;
+      const size_t NumParams = inv.mParamCount;
+      for (int paramsIdx = 0; paramsIdx < NumParams; ++paramsIdx)
+        std::cout << "    (Param) " << inv.mParams[paramsIdx].str() << std::endl;
+    }
+
+    const size_t NumReduces = file.mReduces.Size();
+    for (int redIdx = 0; redIdx < NumReduces; ++redIdx) {
+      const auto &red = file.mReduces[redIdx];
+      std::cout << "  (Reduce) name=\"" << red.mName
+                << "\" result=\"" << red.mResult.str()
+                << "\" exportable=" << red.mIsExportable
+                << std::endl;
+      const size_t NumIns = red.mAccumInCount;
+      for (int insIdx = 0; insIdx < NumIns; ++insIdx)
+        std::cout << "    (In) " << red.mAccumIns[insIdx].str() << std::endl;
+    }
+  }
+}
+
+// ForEach /////////////////////////////////////////////////////////////////////////////////////
+
+void ReflectionState::beginForEaches(size_t Count) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  if (isCollecting()) {
+    auto &file = mFiles.Current();
+    file.mForEaches = new File::ForEach[Count];
+    file.mForEachCount = Count;
+  }
+  if (isUsing()) {
+    slangAssert(mForEachesBad.empty());
+    mNumForEachesMatchedByOrdinal = 0;
+  }
+}
+
+// Keep this in sync with RSReflectionJava::genExportForEach().
+void ReflectionState::beginForEach(const RSExportForEach *EF) {
+  slangAssert(!isClosed() && (mForEachOpen < 0));
+  if (!isActive())
+    return;
+
+  const bool IsKernel = EF->isKernelStyle();
+  const std::string Name = EF->getName();
+  const unsigned Ordinal = EF->getOrdinal();
+  const size_t InCount = EF->getInTypes().size();
+  const size_t ParamCount = EF->params_count();
+
+  const RSExportType *OET = EF->getOutType();
+  if (OET && !IsKernel) {
+    slangAssert(OET->getClass() == RSExportType::ExportClassPointer);
+    OET = static_cast<const RSExportPointerType *>(OET)->getPointeeType();
+  }
+  const std::string OutType = (OET ? getUniqueTypeName(OET) : "");
+  const bool HasOut = (EF->hasOut() || EF->hasReturn());
+
+  mForEachOpen = Ordinal;
+  mForEachFatal = true;  // we'll set this to false if everything looks ok
+
+  auto &file = mFiles.Current();
+  auto &foreaches = file.mForEaches;
+  if (isCollecting()) {
+    slangAssert(Ordinal < file.mForEachCount);
+    auto &foreach = foreaches[Ordinal];
+    slangAssert(foreach.mState == File::ForEach::S_Initial);
+    foreach.mState = File::ForEach::S_Collected;
+    foreach.mName = Name;
+    foreach.mIns.BeginCollecting(InCount);
+    foreach.mParams.BeginCollecting(ParamCount);
+    foreach.mOut = canon(OutType);
+    foreach.mHasOut = HasOut;
+    foreach.mSignatureMetadata = 0;
+    foreach.mIsKernel = IsKernel;
+  }
+  if (isUsing()) {
+    if (Ordinal >= file.mForEachCount) {
+      mForEachesBad.push_back(EF);
+      return;
+    }
+
+    auto &foreach = foreaches[Ordinal];
+    slangAssert(foreach.mState == File::ForEach::S_Collected);
+    foreach.mState = File::ForEach::S_UseMatched;
+    ++mNumForEachesMatchedByOrdinal;
+
+    if (foreach.mName != Name) {
+      // Order matters because it determines slot number
+      mForEachesBad.push_back(EF);
+      return;
+    }
+
+    // At this point, we have matching ordinal and matching name.
+
+    if (foreach.mIsKernel != IsKernel) {
+      mRSC->ReportError(EF->getLocation(),
+                        "foreach kernel '%0' has __attribute__((kernel)) for %select{32|64}1-bit targets "
+                        "but not for %select{64|32}1-bit targets")
+          << Name << IsKernel;
+      return;
+    }
+
+    if ((foreach.mHasOut != HasOut) || !foreach.mOut.equals(OutType)) {
+      // There are several different patterns we need to handle:
+      // (1) Two different non-void* output types
+      // (2) One non-void* output type, one void* output type
+      // (3) One non-void* output type, one no-output
+      // (4) One void* output type, one no-output
+      if (foreach.mHasOut && HasOut) {
+        if (foreach.mOut.size() && OutType.size()) {
+          // (1) Two different non-void* output types
+          mRSC->ReportError(EF->getLocation(),
+                            "foreach kernel '%0' has output type '%1' for 32-bit targets "
+                            "but output type '%2' for 64-bit targets")
+              << Name << foreach.mOut.str() << OutType;
+        } else {
+          // (2) One non-void* return type, one void* output type
+          const bool hasTyped64 = OutType.size();
+          mRSC->ReportError(EF->getLocation(),
+                            "foreach kernel '%0' has output type '%1' for %select{32|64}2-bit targets "
+                            "but has untyped output for %select{64|32}2-bit targets")
+              << Name << (foreach.mOut.str() + OutType) << hasTyped64;
+        }
+      } else {
+        const std::string CombinedOutType = (foreach.mOut.str() + OutType);
+        if (CombinedOutType.size()) {
+          // (3) One non-void* output type, one no-output
+          mRSC->ReportError(EF->getLocation(),
+                            "foreach kernel '%0' has output type '%1' for %select{32|64}2-bit targets "
+                            "but no output for %select{64|32}2-bit targets")
+              << Name << CombinedOutType << HasOut;
+        } else {
+          // (4) One void* output type, one no-output
+          mRSC->ReportError(EF->getLocation(),
+                            "foreach kernel '%0' has untyped output for %select{32|64}1-bit targets "
+                            "but no output for %select{64|32}1-bit targets")
+              << Name << HasOut;
+        }
+      }
+    }
+
+    bool BadCount = false;
+    if (foreach.mIns.Size() != InCount) {
+      mRSC->ReportError(EF->getLocation(),
+                        "foreach kernel '%0' has %1 input%s1 for 32-bit targets "
+                        "but %2 input%s2 for 64-bit targets")
+          << Name << unsigned(foreach.mIns.Size()) << unsigned(InCount);
+      BadCount = true;
+    }
+    if (foreach.mParams.Size() != ParamCount) {
+      mRSC->ReportError(EF->getLocation(),
+                        "foreach kernel '%0' has %1 usrData parameter%s1 for 32-bit targets "
+                        "but %2 usrData parameter%s2 for 64-bit targets")
+          << Name << unsigned(foreach.mParams.Size()) << unsigned(ParamCount);
+      BadCount = true;
+    }
+
+    if (BadCount)
+      return;
+
+    foreach.mIns.BeginUsing();
+    foreach.mParams.BeginUsing();
+  }
+
+  mForEachFatal = false;
+}
+
+void ReflectionState::addForEachIn(const RSExportForEach *EF, const RSExportType *Type) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mForEachOpen == EF->getOrdinal());
+
+  // Type may be nullptr in the case of void*.  See RSExportForEach::Create().
+  if (Type && !EF->isKernelStyle()) {
+    slangAssert(Type->getClass() == RSExportType::ExportClassPointer);
+    Type = static_cast<const RSExportPointerType *>(Type)->getPointeeType();
+  }
+  const std::string TypeName = (Type ? getUniqueTypeName(Type) : std::string());
+
+  auto &ins = mFiles.Current().mForEaches[EF->getOrdinal()].mIns;
+  if (isCollecting()) {
+    ins.CollectNext() = canon(TypeName);
+  }
+  if (isUsing()) {
+    if (mForEachFatal)
+      return;
+
+    if (!ins.UseNext().equals(TypeName)) {
+      if (ins.Current().size() && TypeName.size()) {
+        mRSC->ReportError(EF->getLocation(),
+                          "%ordinal0 input of foreach kernel '%1' "
+                          "has type '%2' for 32-bit targets "
+                          "but type '%3' for 64-bit targets")
+            << unsigned(ins.CurrentIdx() + 1)
+            << EF->getName()
+            << ins.Current().str()
+            << TypeName;
+      } else {
+        const bool hasType64 = TypeName.size();
+        mRSC->ReportError(EF->getLocation(),
+                          "%ordinal0 input of foreach kernel '%1' "
+                          "has type '%2' for %select{32|64}3-bit targets "
+                          "but is untyped for %select{64|32}3-bit targets")
+            << unsigned(ins.CurrentIdx() + 1)
+            << EF->getName()
+            << (ins.Current().str() + TypeName)
+            << hasType64;
+      }
+    }
+  }
+}
+
+void ReflectionState::addForEachParam(const RSExportForEach *EF, const RSExportType *Type) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mForEachOpen == EF->getOrdinal());
+
+  const std::string TypeName = getUniqueTypeName(Type);
+
+  auto &params = mFiles.Current().mForEaches[EF->getOrdinal()].mParams;
+  if (isCollecting()) {
+    params.CollectNext() = canon(TypeName);
+  }
+  if (isUsing()) {
+    if (mForEachFatal)
+      return;
+
+    if (!params.UseNext().equals(TypeName)) {
+      mRSC->ReportError(EF->getLocation(),
+                        "%ordinal0 usrData parameter of foreach kernel '%1' "
+                        "has type '%2' for 32-bit targets "
+                        "but type '%3' for 64-bit targets")
+          << unsigned(params.CurrentIdx() + 1)
+          << EF->getName()
+          << params.Current().str()
+          << TypeName;
+    }
+  }
+}
+
+void ReflectionState::addForEachSignatureMetadata(const RSExportForEach *EF, unsigned Metadata) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mForEachOpen == EF->getOrdinal());
+
+  // These are properties in the metadata that we need to check.
+  const unsigned SpecialParameterBits = bcinfo::MD_SIG_X|bcinfo::MD_SIG_Y|bcinfo::MD_SIG_Z|bcinfo::MD_SIG_Ctxt;
+
+#ifndef __DISABLE_ASSERTS
+  {
+    // These are properties in the metadata that we already check in
+    // some other way.
+    const unsigned BoringBits = bcinfo::MD_SIG_In|bcinfo::MD_SIG_Out|bcinfo::MD_SIG_Usr|bcinfo::MD_SIG_Kernel;
+
+    slangAssert((Metadata & ~(SpecialParameterBits | BoringBits)) == 0);
+  }
+#endif
+
+  auto &mSignatureMetadata = mFiles.Current().mForEaches[EF->getOrdinal()].mSignatureMetadata;
+  if (isCollecting()) {
+    mSignatureMetadata = Metadata;
+  }
+  if (isUsing()) {
+    if (mForEachFatal)
+      return;
+
+    if ((mSignatureMetadata & SpecialParameterBits) != (Metadata & SpecialParameterBits)) {
+      mRSC->ReportError(EF->getLocation(),
+                        "foreach kernel '%0' has different special parameters "
+                        "for 32-bit targets than for 64-bit targets")
+          << EF->getName();
+    }
+  }
+}
+
+void ReflectionState::endForEach() {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mForEachOpen >= 0);
+  if (isUsing() && !mForEachFatal) {
+    slangAssert(mFiles.Current().mForEaches[mForEachOpen].mIns.isFinished());
+    slangAssert(mFiles.Current().mForEaches[mForEachOpen].mParams.isFinished());
+  }
+
+  mForEachOpen = -1;
+}
+
+void ReflectionState::endForEaches() {
+  slangAssert(mForEachOpen < 0);
+  if (!isUsing())
+    return;
+
+  const auto &file = mFiles.Current();
+
+  if (!mForEachesBad.empty()) {
+    std::sort(mForEachesBad.begin(), mForEachesBad.end(),
+         [](const RSExportForEach *a, const RSExportForEach *b) { return a->getOrdinal() < b->getOrdinal(); });
+    // Note that after the sort, all kernels that are bad because of
+    // name mismatch precede all kernels that are bad because of
+    // too-high ordinal.
+
+    // 32-bit and 64-bit compiles need to see foreach kernels in the
+    // same order, because of slot number assignment.  Once we see the
+    // first name mismatch in the sequence of foreach kernels, it
+    // doesn't make sense to issue further diagnostics regarding
+    // foreach kernels except those that still happen to match by name
+    // and ordinal (we already handled those diagnostics between
+    // beginForEach() and endForEach()).
+    bool ForEachesOrderFatal = false;
+
+    for (const RSExportForEach *EF : mForEachesBad) {
+      if (EF->getOrdinal() >= file.mForEachCount) {
+        mRSC->ReportError(EF->getLocation(),
+                          "foreach kernel '%0' is only present for 64-bit targets")
+            << EF->getName();
+      } else {
+        mRSC->ReportError(EF->getLocation(),
+                          "%ordinal0 foreach kernel is '%1' for 32-bit targets "
+                          "but '%2' for 64-bit targets")
+            << (EF->getOrdinal() + 1)
+            << mFiles.Current().mForEaches[EF->getOrdinal()].mName
+            << EF->getName();
+        ForEachesOrderFatal = true;
+        break;
+      }
+    }
+
+    mForEachesBad.clear();
+
+    if (ForEachesOrderFatal)
+      return;
+  }
+
+  if (mNumForEachesMatchedByOrdinal == file.mForEachCount)
+    return;
+  for (unsigned ord = 0; ord < file.mForEachCount; ord++) {
+    const auto &fe = file.mForEaches[ord];
+    if (fe.mState == File::ForEach::S_Collected) {
+      mRSC->ReportError("in file '%0' foreach kernel '%1' is only present for 32-bit targets")
+          << file.mRSSourceFileName << fe.mName;
+    }
+  }
+}
+
+// Invokable ///////////////////////////////////////////////////////////////////////////////////
+
+// Keep this in sync with RSReflectionJava::genExportFunction().
+void ReflectionState::declareInvokable(const RSExportFunc *EF) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  const std::string Name = EF->getName(/*Mangle=*/false);
+  const size_t ParamCount = EF->getNumParameters();
+
+  auto &invokables = mFiles.Current().mInvokables;
+  if (isCollecting()) {
+    auto &invokable = invokables.CollectNext();
+    invokable.mName = Name;
+    invokable.mParamCount = ParamCount;
+    if (EF->hasParam()) {
+      unsigned FieldIdx = 0;
+      invokable.mParams = new llvm::StringRef[ParamCount];
+      for (RSExportFunc::const_param_iterator I = EF->params_begin(),
+                                              E = EF->params_end();
+           I != E; I++, FieldIdx++) {
+        invokable.mParams[FieldIdx] = canon(getUniqueTypeName((*I)->getType()));
+      }
+    }
+  }
+  if (isUsing()) {
+    if (mInvokablesOrderFatal)
+      return;
+
+    if (invokables.isFinished()) {
+      // This doesn't actually break reflection, but that's a
+      // coincidence of the fact that we reflect during the 64-bit
+      // compilation pass rather than the 32-bit compilation pass, and
+      // of the fact that the "extra" invokable(s) are at the end.
+      mRSC->ReportError(EF->getLocation(),
+                        "invokable function '%0' is only present for 64-bit targets")
+          << Name;
+      return;
+    }
+
+    auto &invokable = invokables.UseNext();
+
+    if (invokable.mName != Name) {
+      // Order matters because it determines slot number
+      mRSC->ReportError(EF->getLocation(),
+                        "%ordinal0 invokable function is '%1' for 32-bit targets "
+                        "but '%2' for 64-bit targets")
+          << unsigned(invokables.CurrentIdx() + 1)
+          << invokable.mName
+          << Name;
+      mInvokablesOrderFatal = true;
+      return;
+    }
+
+    if (invokable.mParamCount != ParamCount) {
+      mRSC->ReportError(EF->getLocation(),
+                        "invokable function '%0' has %1 parameter%s1 for 32-bit targets "
+                        "but %2 parameter%s2 for 64-bit targets")
+          << Name << unsigned(invokable.mParamCount) << unsigned(ParamCount);
+      return;
+    }
+    if (EF->hasParam()) {
+      unsigned FieldIdx = 0;
+      for (RSExportFunc::const_param_iterator I = EF->params_begin(),
+                                              E = EF->params_end();
+           I != E; I++, FieldIdx++) {
+        const std::string Type = getUniqueTypeName((*I)->getType());
+        if (!invokable.mParams[FieldIdx].equals(Type)) {
+          mRSC->ReportError(EF->getLocation(),
+                            "%ordinal0 parameter of invokable function '%1' "
+                            "has type '%2' for 32-bit targets "
+                            "but type '%3' for 64-bit targets")
+              << (FieldIdx + 1)
+              << Name
+              << invokable.mParams[FieldIdx].str()
+              << Type;
+        }
+      }
+    }
+  }
+}
+
+void ReflectionState::endInvokables() {
+  if (!isUsing() || mInvokablesOrderFatal)
+    return;
+
+  auto &invokables = mFiles.Current().mInvokables;
+  while (!invokables.isFinished()) {
+    const auto &invokable = invokables.UseNext();
+    mRSC->ReportError("in file '%0' invokable function '%1' is only present for 32-bit targets")
+        << mFiles.Current().mRSSourceFileName << invokable.mName;
+  }
+}
+
+// Record //////////////////////////////////////////////////////////////////////////////////////
+
+void ReflectionState::beginRecords() {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mRecordsState != RS_Open);
+  mRecordsState = RS_Open;
+  mNumRecordsMatchedByName = 0;
+}
+
+void ReflectionState::endRecords() {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mRecordsState == RS_Open);
+  mRecordsState = RS_Closed;
+
+  if (isUsing()) {
+    const File &file = mFiles.Current();
+    if (mNumRecordsMatchedByName == file.mRecords.size())
+      return;
+    // NOTE: "StringMap iteration order, however, is not guaranteed to
+    // be deterministic".  So sort by name before reporting.
+    // Alternatively, if we record additional information, we could
+    // sort by source location or by order in which we discovered the
+    // need to export.
+    std::vector<llvm::StringRef> Non64RecordNames;
+    for (auto I = file.mRecords.begin(), E = file.mRecords.end(); I != E; I++)
+      if (!I->getValue().mMatchedByName && I->getValue().mOrdinary)
+        Non64RecordNames.push_back(I->getKey());
+    std::sort(Non64RecordNames.begin(), Non64RecordNames.end(),
+              [](llvm::StringRef a, llvm::StringRef b) { return a.compare(b)==-1; });
+    for (auto N : Non64RecordNames)
+      mRSC->ReportError("in file '%0' structure '%1' is exported only for 32-bit targets")
+          << file.mRSSourceFileName << N.str();
+  }
+}
+
+void ReflectionState::declareRecord(const RSExportRecordType *ERT, bool Ordinary) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  slangAssert(mRecordsState == RS_Open);
+
+  auto &records = mFiles.Current().mRecords;
+  if (isCollecting()) {
+    // Keep struct/field layout in sync with
+    // RSReflectionJava::genPackVarOfType() and
+    // RSReflectionJavaElementBuilder::genAddElement()
+
+    // Save properties of record
+
+    const size_t FieldCount = ERT->fields_size();
+    File::Record::Field *Fields = new File::Record::Field[FieldCount];
+
+    size_t Pos = 0;  // Relative position of field within record
+    unsigned FieldIdx = 0;
+    for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), E = ERT->fields_end();
+         I != E; I++, FieldIdx++) {
+      const RSExportRecordType::Field *FieldExport = *I;
+      size_t FieldOffset = FieldExport->getOffsetInParent();
+      const RSExportType *T = FieldExport->getType();
+      size_t FieldStoreSize = T->getStoreSize();
+      size_t FieldAllocSize = T->getAllocSize();
+
+      slangAssert(FieldOffset >= Pos);
+      slangAssert(FieldAllocSize >= FieldStoreSize);
+
+      auto &FieldState = Fields[FieldIdx];
+      FieldState.mName = FieldExport->getName();
+      FieldState.mType = canon(getUniqueTypeName(T));
+      FieldState.mPrePadding = FieldOffset - Pos;
+      FieldState.mPostPadding = FieldAllocSize - FieldStoreSize;
+      FieldState.mOffset = FieldOffset;
+      FieldState.mStoreSize = FieldStoreSize;
+
+      Pos = FieldOffset + FieldAllocSize;
+    }
+
+    slangAssert(ERT->getAllocSize() >= Pos);
+
+    // Insert record into map
+
+    slangAssert(records.find(ERT->getName()) == records.end());
+    File::Record &record = records[ERT->getName()];
+    record.mFields = Fields;
+    record.mFieldCount = FieldCount;
+    record.mPostPadding = ERT->getAllocSize() - Pos;
+    record.mAllocSize = ERT->getAllocSize();
+    record.mOrdinary = Ordinary;
+    record.mMatchedByName = false;
+  }
+  if (isUsing()) {
+    if (!Ordinary)
+      return;
+
+    const auto RIT = records.find(ERT->getName());
+    if (RIT == records.end()) {
+      // This doesn't actually break reflection, but that's a
+      // coincidence of the fact that we reflect during the 64-bit
+      // compilation pass rather than the 32-bit compilation pass, so
+      // a record that's only classified as exported during the 64-bit
+      // compilation pass doesn't cause any problems.
+      mRSC->ReportError(ERT->getLocation(), "structure '%0' is exported only for 64-bit targets")
+          << ERT->getName();
+      return;
+    }
+    File::Record &record = RIT->getValue();
+    record.mMatchedByName = true;
+    ++mNumRecordsMatchedByName;
+    slangAssert(record.mOrdinary);
+
+    if (ERT->fields_size() != record.mFieldCount) {
+      mRSC->ReportError(ERT->getLocation(),
+                        "exported structure '%0' has %1 field%s1 for 32-bit targets "
+                        "but %2 field%s2 for 64-bit targets")
+          << ERT->getName() << unsigned(record.mFieldCount) << unsigned(ERT->fields_size());
+      return;
+    }
+
+    // Note that we are deliberately NOT comparing layout properties
+    // (such as Field offsets and sizes, or Record allocation size);
+    // we need to tolerate layout differences between 32-bit
+    // compilation and 64-bit compilation.
+
+    unsigned FieldIdx = 0;
+    for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), E = ERT->fields_end();
+         I != E; I++, FieldIdx++) {
+      const RSExportRecordType::Field &FieldExport = **I;
+      const File::Record::Field &FieldState = record.mFields[FieldIdx];
+      if (FieldState.mName != FieldExport.getName()) {
+        mRSC->ReportError(ERT->getLocation(),
+                          "%ordinal0 field of exported structure '%1' "
+                          "is '%2' for 32-bit targets "
+                          "but '%3' for 64-bit targets")
+            << (FieldIdx + 1) << ERT->getName() << FieldState.mName << FieldExport.getName();
+        return;
+      }
+      const std::string FieldExportType = getUniqueTypeName(FieldExport.getType());
+      if (!FieldState.mType.equals(FieldExportType)) {
+        mRSC->ReportError(ERT->getLocation(),
+                          "field '%0' of exported structure '%1' "
+                          "has type '%2' for 32-bit targets "
+                          "but type '%3' for 64-bit targets")
+            << FieldState.mName << ERT->getName() << FieldState.mType.str() << FieldExportType;
+      }
+    }
+  }
+}
+
+ReflectionState::Record32
+ReflectionState::getRecord32(const RSExportRecordType *ERT) {
+  if (isUsing()) {
+    const auto &Records = mFiles.Current().mRecords;
+    const auto RIT = Records.find(ERT->getName());
+    if (RIT != Records.end())
+      return Record32(&RIT->getValue());
+  }
+  return Record32();
+}
+
+// Reduce //////////////////////////////////////////////////////////////////////////////////////
+
+void ReflectionState::declareReduce(const RSExportReduce *ER, bool IsExportable) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return;
+
+  auto &reduces = mFiles.Current().mReduces;
+  if (isCollecting()) {
+    auto &reduce = reduces.CollectNext();
+    reduce.mName = ER->getNameReduce();
+
+    const auto &InTypes = ER->getAccumulatorInTypes();
+    const size_t InTypesSize = InTypes.size();
+    reduce.mAccumInCount = InTypesSize;
+    reduce.mAccumIns = new llvm::StringRef[InTypesSize];
+    unsigned InTypesIdx = 0;
+    for (const auto &InType : InTypes)
+      reduce.mAccumIns[InTypesIdx++] = canon(getUniqueTypeName(InType));
+
+    reduce.mResult = canon(getUniqueTypeName(ER->getResultType()));
+    reduce.mIsExportable = IsExportable;
+  }
+  if (isUsing()) {
+    if (mReducesOrderFatal)
+      return;
+
+    const std::string Name = ER->getNameReduce();
+
+    if (reduces.isFinished()) {
+      // This doesn't actually break reflection, but that's a
+      // coincidence of the fact that we reflect during the 64-bit
+      // compilation pass rather than the 32-bit compilation pass, and
+      // of the fact that the "extra" reduction kernel(s) are at the
+      // end.
+      mRSC->ReportError(ER->getLocation(),
+                        "reduction kernel '%0' is only present for 64-bit targets")
+          << Name;
+      return;
+    }
+
+    auto &reduce = reduces.UseNext();
+
+    if (reduce.mName != Name) {
+      // Order matters because it determines slot number.  We might be
+      // able to tolerate certain cases if we ignore non-exportable
+      // kernels in the two sequences (32-bit and 64-bit) -- non-exportable
+      // kernels do not take up slot numbers.
+      mRSC->ReportError(ER->getLocation(),
+                        "%ordinal0 reduction kernel is '%1' for 32-bit targets "
+                        "but '%2' for 64-bit targets")
+          << unsigned(reduces.CurrentIdx() + 1)
+          << reduce.mName
+          << Name;
+      mReducesOrderFatal = true;
+      return;
+    }
+
+    // If at least one of the two kernels (32-bit or 64-bit) is not
+    // exporable, then there will be no reflection for that kernel,
+    // and so any mismatch in result type or in inputs is irrelevant.
+    // However, we may make more kernels exportable in the future.
+    // Therefore, we'll forbid mismatches anyway.
+
+    if (reduce.mIsExportable != IsExportable) {
+      mRSC->ReportError(ER->getLocation(),
+                        "reduction kernel '%0' is reflected in Java only for %select{32|64}1-bit targets")
+          << reduce.mName
+          << IsExportable;
+    }
+
+    const std::string ResultType = getUniqueTypeName(ER->getResultType());
+    if (!reduce.mResult.equals(ResultType)) {
+      mRSC->ReportError(ER->getLocation(),
+                        "reduction kernel '%0' has result type '%1' for 32-bit targets "
+                        "but result type '%2' for 64-bit targets")
+          << reduce.mName << reduce.mResult.str() << ResultType;
+    }
+
+    const auto &InTypes = ER->getAccumulatorInTypes();
+    if (reduce.mAccumInCount != InTypes.size()) {
+      mRSC->ReportError(ER->getLocation(),
+                        "reduction kernel '%0' has %1 input%s1 for 32-bit targets "
+                        "but %2 input%s2 for 64-bit targets")
+          << Name << unsigned(reduce.mAccumInCount) << unsigned(InTypes.size());
+      return;
+    }
+    unsigned FieldIdx = 0;
+    for (const auto &InType : InTypes) {
+      const std::string InTypeName = getUniqueTypeName(InType);
+      const llvm::StringRef StateInTypeName = reduce.mAccumIns[FieldIdx++];
+      if (!StateInTypeName.equals(InTypeName)) {
+        mRSC->ReportError(ER->getLocation(),
+                          "%ordinal0 input of reduction kernel '%1' "
+                          "has type '%2' for 32-bit targets "
+                          "but type '%3' for 64-bit targets")
+            << FieldIdx
+            << Name
+            << StateInTypeName.str()
+            << InTypeName;
+      }
+    }
+  }
+}
+
+void ReflectionState::endReduces() {
+  if (!isUsing() || mReducesOrderFatal)
+    return;
+
+  auto &reduces = mFiles.Current().mReduces;
+  while (!reduces.isFinished()) {
+    const auto &reduce = reduces.UseNext();
+    mRSC->ReportError("in file '%0' reduction kernel '%1' is only present for 32-bit targets")
+        << mFiles.Current().mRSSourceFileName << reduce.mName;
+  }
+}
+
+// Variable ////////////////////////////////////////////////////////////////////////////////////
+
+// Keep this in sync with initialization handling in
+// RSReflectionJava::genScriptClassConstructor().
+ReflectionState::Val32 ReflectionState::declareVariable(const RSExportVar *EV) {
+  slangAssert(!isClosed());
+  if (!isActive())
+    return NoVal32();
+
+  auto &variables = mFiles.Current().mVariables;
+  if (isCollecting()) {
+    auto &variable = variables.CollectNext();
+    variable.mName = EV->getName();
+    variable.mType = canon(getUniqueTypeName(EV->getType()));
+    variable.mAllocSize = EV->getType()->getAllocSize();
+    variable.mIsConst = EV->isConst();
+    if (!EV->getInit().isUninit()) {
+      variable.mInitializerCount = 1;
+      variable.mInitializers = new clang::APValue[1];
+      variable.mInitializers[0] = EV->getInit();
+    } else if (EV->getArraySize()) {
+      variable.mInitializerCount = EV->getNumInits();
+      variable.mInitializers = new clang::APValue[variable.mInitializerCount];
+      for (size_t i = 0; i < variable.mInitializerCount; ++i)
+        variable.mInitializers[i] = EV->getInitArray(i);
+    } else {
+      variable.mInitializerCount = 0;
+    }
+    return NoVal32();
+  }
+
+  /*-- isUsing() -----------------------------------------------------------*/
+
+  slangAssert(isUsing());
+
+  if (mVariablesOrderFatal)
+    return NoVal32();
+
+  if (variables.isFinished()) {
+    // This doesn't actually break reflection, but that's a
+    // coincidence of the fact that we reflect during the 64-bit
+    // compilation pass rather than the 32-bit compilation pass, and
+    // of the fact that the "extra" variable(s) are at the end.
+    mRSC->ReportError(EV->getLocation(), "global variable '%0' is only present for 64-bit targets")
+        << EV->getName();
+    return NoVal32();
+  }
+
+  const auto &variable = variables.UseNext();
+
+  if (variable.mName != EV->getName()) {
+    // Order matters because it determines slot number
+    mRSC->ReportError(EV->getLocation(),
+                      "%ordinal0 global variable is '%1' for 32-bit targets "
+                      "but '%2' for 64-bit targets")
+        << unsigned(variables.CurrentIdx() + 1)
+        << variable.mName
+        << EV->getName();
+    mVariablesOrderFatal = true;
+    return NoVal32();
+  }
+
+  const std::string TypeName = getUniqueTypeName(EV->getType());
+
+  if (!variable.mType.equals(TypeName)) {
+    mRSC->ReportError(EV->getLocation(),
+                      "global variable '%0' has type '%1' for 32-bit targets "
+                      "but type '%2' for 64-bit targets")
+        << EV->getName()
+        << variable.mType.str()
+        << TypeName;
+    return NoVal32();
+  }
+
+  if (variable.mIsConst != EV->isConst()) {
+    mRSC->ReportError(EV->getLocation(),
+                      "global variable '%0' has inconsistent 'const' qualification "
+                      "between 32-bit targets and 64-bit targets")
+        << EV->getName();
+    return NoVal32();
+  }
+
+  // NOTE: Certain syntactically different but semantically
+  // equivalent initialization patterns are unnecessarily rejected
+  // as errors.
+  //
+  // Background:
+  //
+  // . A vector initialized with a scalar value is treated
+  //   by reflection as if all elements of the vector are
+  //   initialized with the scalar value.
+  // . A vector may be initialized with a vector of greater
+  //   length; reflection ignores the extra initializers.
+  // . If only the beginning of a vector is explicitly
+  //   initialized, reflection treats it as if trailing elements are
+  //   initialized to zero (by issuing explicit assignments to those
+  //   trailing elements).
+  // . If only the beginning of an array is explicitly initialized,
+  //   reflection treats it as if trailing elements are initialized
+  //   to zero (by Java rules for newly-created arrays).
+  //
+  // Unnecessarily rejected as errors:
+  //
+  // . One compile initializes a vector with a scalar, and
+  //   another initializes it with a vector whose elements
+  //   are the scalar, as in
+  //
+  //     int2 x =
+  //     #ifdef __LP64__
+  //       1
+  //     #else
+  //       { 1, 1 }
+  //     #endif
+  //
+  // . Compiles initialize a vector with vectors of different
+  //   lengths, but the initializers agree up to the length
+  //   of the variable being initialized, as in
+  //
+  //     int2 x = { 1, 2
+  //     #ifdef __LP64__
+  //       3
+  //     #else
+  //       4
+  //     #endif
+  //     };
+  //
+  // . Two compiles agree with the initializer for a vector or
+  //   array, except that one has some number of explicit trailing
+  //   zeroes, as in
+  //
+  //     int x[4] = { 3, 2, 1
+  //     #ifdef __LP64__
+  //       , 0
+  //     #endif
+  //     };
+
+  bool MismatchedInitializers = false;
+  if (!EV->getInit().isUninit()) {
+    // Use phase has a scalar initializer.
+    // Make sure that Collect phase had a matching scalar initializer.
+    if ((variable.mInitializerCount != 1) ||
+        !equal(variable.mInitializers[0], EV->getInit()))
+      MismatchedInitializers = true;
+  } else if (EV->getArraySize()) {
+    const size_t UseSize = EV->getNumInits();
+    if (variable.mInitializerCount != UseSize)
+      MismatchedInitializers = true;
+    else {
+      for (int i = 0; i < UseSize; ++i)
+        if (!equal(variable.mInitializers[i], EV->getInitArray(i))) {
+          MismatchedInitializers = true;
+          break;
+        }
+    }
+  } else if (variable.mInitializerCount != 0) {
+    // Use phase does not have a scalar initializer, variable is not
+    // an array, and Collect phase has an initializer.  This is an error.
+    MismatchedInitializers = true;
+  }
+
+  if (MismatchedInitializers) {
+    mRSC->ReportError(EV->getLocation(),
+                      "global variable '%0' is initialized differently for 32-bit targets "
+                      "than for 64-bit targets")
+        << EV->getName();
+    return NoVal32();
+  }
+
+  return Val32(true, variable.mAllocSize);
+}
+
+void ReflectionState::endVariables() {
+  if (!isUsing() || mVariablesOrderFatal)
+    return;
+
+  auto &variables = mFiles.Current().mVariables;
+  while (!variables.isFinished()) {
+    const auto &variable = variables.UseNext();
+    mRSC->ReportError("in file '%0' global variable '%1' is only present for 32-bit targets")
+        << mFiles.Current().mRSSourceFileName << variable.mName;
+  }
+}
+
+}  // namespace slang
diff --git a/slang_rs_reflection_state.h b/slang_rs_reflection_state.h
new file mode 100644
index 0000000..d937be8
--- /dev/null
+++ b/slang_rs_reflection_state.h
@@ -0,0 +1,776 @@
+/*
+ * 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 _FRAMEWORKS_COMPILE_SLANG_REFLECTION_STATE_H_  // NOLINT
+#define _FRAMEWORKS_COMPILE_SLANG_REFLECTION_STATE_H_
+
+#include <string>
+#include <utility>
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "clang/AST/APValue.h"
+
+#include "slang_assert.h"
+
+namespace slang {
+
+class RSContext;
+class RSExportForEach;
+class RSExportFunc;
+class RSExportRecordType;
+class RSExportReduce;
+class RSExportType;
+class RSExportVar;
+
+// ---------------------
+// class ReflectionState
+// ---------------------
+//
+// This class is used to collect data from 32-bit compilation for use
+// during the reflected code generation that occurs during 64-bit
+// compilation.  The data is used for two purposes:
+//
+// 1) Accommodating rs object handle size differences when laying out
+//    data (in particular, variables and records).
+// 2) Emitting errors when differences between 32-bit and 64-bit
+//    compilation cannot be tolerated in the reflected code (for
+//    example, size_t has different sizes, and so cannot be part
+//    of any exportable).
+//
+// The model for using this class is as follows:
+// a) Instantiate a class instance.  The instance is in the S_Initial
+//    state.
+// b) Call openJava32() to move the instance to the S_OpenJava32
+//    ("Collecting") state.
+// c) Run the reflection pass on all files in 32-bit mode.  Do not
+//    actually generate reflected code; but call various methods on
+//    the instance (begin*(), declare*(), end*(), etc.) to collect
+//    information.
+// d) Call closeJava32() to move the instance to the S_ClosedJava32
+//    state.
+// e) Call openJava64() to move the instance to the S_OpenJava64
+//    ("Using") state.
+// f) Run the reflection pass on all files in 64-bit mode.  Call the
+//    same methods as in step (c), as well as some further methods to
+//    query the information collected in step (c) in order to handle
+//    layout differences.  All error reporting for 32-bit versus
+//    64-bit differences is handled in the methods themselves.
+// g) Call closeJava64 to move the instance to the S_ClosedJava64
+//    state.
+// h) Destroy the instance.
+//
+// There are two exceptions to this model:
+//
+// 1) If not doing both 32-bit and 64-bit compilation, then skip steps
+//    (b), (d), (e), and (g).  (This is what happens if reflecting C++
+//    instead of Java, or reflecting Java but using the -m32 or -m64
+//    option.)  In this case, the methods called in steps (c) and (f)
+//    are no-ops: They do not collect information, they do not report
+//    errors, and they return "no information available" when step (f)
+//    asks for 32-bit layout related information.
+// 2) The class instance can be moved to the S_Bad state by class
+//    ReflectionState::Tentative (see that class for more information)
+//    when reflection itself aborts due to some error.  The only legal
+//    thing to do with an instance in this state is invoke its
+//    destructor.
+//
+// All exported entities except for Records have slot numbers assigned
+// in reflection order.  These slot numbers must match up between
+// 32-bit and 64-bit compilation.  Therefore, we (generally) require
+// that entities be presented to ReflectionState (via begin*() or
+// declare*()) in the same order during the Collecting and Using
+// phases.  This presentation order is generally the same as lexical
+// order in the user code, which makes it simple to emit meaningful
+// diagnostics when the order is inconsistent (for example, 32-bit and
+// 64-bit compilation disagree on the name of the kernel in a
+// particular slot).  ReflectionState generally builds up an array of
+// each sort of entity, in the presentation order.  There are two
+// exceptions:
+//
+// a) Records, as mentioned above.  Exported Records have no slot
+//    number, and therefore reflection order doesn't matter.  In
+//    practice, Records aren't necessarily reflected in consistent
+//    order, because they are determined to be exported as a
+//    consequence of determining that other entities are to be
+//    exported; and variations between 32-bit and 64-bit compilation
+//    can therefore result in inconsistent Record reflection order.
+//    Therefore, ReflectionState builds up a map of Records.
+// b) ForEach kernels.  ForEach kernels are not necessarily reflected
+//    in lexical order (there is some sorting to segregate root
+//    kernel, old-style kernels, and new-style kernels).  In order to
+//    give meaningful diagnostics for slot order mismatches, it's
+//    enough to solve the simpler problem of giving meaningful
+//    diagnostics for lexical order mismatches (although this is
+//    stricter than necessary because of the sorting that occurs
+//    before slot assignment).  Therefore, ReflectionState builds up
+//    an array of ForEaches in lexical order rather than in
+//    presentation (slot) order, and accesses the array randomly
+//    rather than sequentially.
+//
+class ReflectionState {
+ private:
+  // Set this to true to turn everything into a no-op, just as if none
+  // of the open*() or close*() methods were ever called.
+  static const bool kDisabled = false;
+
+ public:
+  ReflectionState() :
+      mRSC(nullptr),
+      mState(S_Initial),
+      mForEachOpen(-1),
+      mOutputClassOpen(false),
+      mRecordsState(RS_Initial),
+      mStringSet(nullptr) { }
+  ~ReflectionState();
+
+  ReflectionState(const ReflectionState &) = delete;
+  void operator=(const ReflectionState &) = delete;
+
+  // For use in the debugger.
+  void dump();
+
+  // A possibly-present value describing a property for a 32-bit target.
+  // When .first is false, the value is absent, and .second is unspecified.
+  typedef std::pair<bool, size_t> Val32;
+  static Val32 NoVal32() { return Val32(false, ~size_t(0)); }
+
+  void openJava32(size_t NumFiles);
+  void closeJava32();
+  void openJava64();
+  void closeJava64();
+
+  bool isCollecting() const { return mState==S_OpenJava32; }
+
+  // ----------------------------------------------------------------------
+
+  // Use these methods during the "Collecting" phase to track
+  // information about a class being generated -- a script class or a
+  // type class.  We call such a class "Divergent" if it needs to have
+  // at least one runtime check to distinguish between 32-bit and
+  // 64-bit targets.
+  //
+  //   Indicate that we are beginning to generate the class.
+  //
+  void beginOutputClass() {
+    slangAssert(!mOutputClassOpen && !isClosed());
+    mOutputClassOpen = true;
+    mOutputClassDivergent = false;
+  }
+  //
+  //   Record the fact that we've learned the class is divergent.
+  //
+  void setOutputClassDivergent() {
+    slangAssert(mOutputClassOpen);
+    mOutputClassDivergent = true;
+  }
+  //
+  //   Indicate that we've finished generating the class.  Returns
+  //   true IFF we've learned the class is divergent.
+  //
+  bool endOutputClass() {
+    slangAssert(mOutputClassOpen);
+    mOutputClassOpen = false;
+    return mOutputClassDivergent;
+  }
+
+  // ----------------------------------------------------------------------
+
+  // --------------------------------
+  // class ReflectionState::Tentative
+  // --------------------------------
+  //
+  // This class aids in error handling.  The model is as follows:
+  // a) Instantiate the class with a pointer to a ReflectionState
+  //    instance.
+  // b) Before destroying the class instance, if there have been no
+  //    errors, call the ok() method on the instance.
+  // c) When the instance is destroyed, if ok() has not been called on
+  //    it, this class will put the ReflectionState into the S_Bad
+  //    state.
+  //
+  // The idea is to "poison" the ReflectionState if we quit reflection
+  // early because of some error -- we don't want to get in a
+  // situation where we only have partial information from the
+  // Collecting phase (because of quitting early) but try to use it
+  // during the Using phase.
+  //
+  friend class Tentative;
+  class Tentative {
+   public:
+    Tentative(ReflectionState *state) : mState(state) { }
+    ~Tentative() { if (mState) mState->mState = ReflectionState::S_Bad; }
+
+    void ok() { mState = nullptr; }
+
+    Tentative(const Tentative &) = delete;
+    void operator=(const Tentative &) = delete;
+
+   private:
+    ReflectionState *mState;
+  };
+
+  // ----------------------------------------------------------------------
+
+  // Model for ForEach kernels (per File):
+  //
+  // a) beginForEaches(number_of_non_dummy_root_kernels_in_file)
+  // b) mixture of declareForEachDummyRoot() calls and
+  //    beginForEach()..endForEach() calls
+  // c) endForEaches()
+  //
+  // For a given ForEach kernel:
+  //
+  // b1) beginForEach()
+  // b2) call any number of addForEachIn() (one per input)
+  // b3) call any number of addForEachParam() (one per param)
+  // b4) call addForEachSignatureMetadata() (if it's reflected)
+  // b5) call endForEach()
+  //
+  // b2, b3, b4 can occur in any order
+
+  void beginForEaches(size_t Count);
+
+  void declareForEachDummyRoot(const RSExportForEach *) { /* we don't care */ };
+
+  void beginForEach(const RSExportForEach *EF);
+
+  void addForEachIn(const RSExportForEach *EF, const RSExportType *Type);
+
+  void addForEachParam(const RSExportForEach *EF, const RSExportType *Type);
+
+  void addForEachSignatureMetadata(const RSExportForEach *EF, unsigned Metadata);
+
+  void endForEach();
+
+  void endForEaches();
+
+  // ----------------------------------------------------------------------
+
+  // Model for Invokable functions (per File):
+  //
+  // a) beginInvokables(number_of_invokables_in_file)
+  // b) declareInvokable() for each Invokable (order must be
+  //    consistent between 32-bit and 64-bit compile)
+  // c) endInvokables()
+
+  void beginInvokables(size_t Count) {
+    mInvokablesOrderFatal = false;
+    begin(&File::mInvokables, Count);
+  }
+
+  void declareInvokable(const RSExportFunc *EF);
+
+  void endInvokables();
+
+  // ----------------------------------------------------------------------
+
+  // Model for reduction kernels (per File):
+  //
+  // a) beginReduces(number_of_reduction_kernels_in_file)
+  // b) declareReduce() for each reduction kernel (order must be
+  //    consistent between 32-bit and 64-bit compile)
+  // c) endReduces()
+
+  void beginReduces(size_t Count) {
+    mReducesOrderFatal = false;
+    begin(&File::mReduces, Count);
+  }
+
+  void declareReduce(const RSExportReduce *ER, bool IsExportable);
+
+  void endReduces();
+
+  // ----------------------------------------------------------------------
+
+  // Model for records (per File):
+  //
+  // a) beginRecords()
+  // b) declareRecord() for each Record (order doesn't matter)
+  // c) endRecords()
+  //
+  // And at any time during the Using phase, can call getRecord32() to
+  // get information from the 32-bit compile (Collecting phase).
+
+  void beginRecords();
+
+  // An "Ordinary" record is anything other than an
+  // internally-synthesized helper record.  We do not emit diagnostics
+  // for mismatched helper records -- we assume that the constructs
+  // from which those helper records were derived are also mismatched,
+  // and that we'll get diagnostics for those constructs.
+  void declareRecord(const RSExportRecordType *ERT, bool Ordinary = true);
+
+  void endRecords();
+
+  class Record32;
+
+  // During the Using phase, obtain information about a Record from
+  // the Collecting phase.  ERT should be from the Using phase, not
+  // the Collecting phase.  The value returned from this function is
+  // valid for the lifetime of the ReflectionState instance.
+  Record32 getRecord32(const RSExportRecordType *ERT);
+
+  // ----------------------------------------------------------------------
+
+  // Model for Variables (per file):
+  //
+  // a) beginVariables(number_of_exported_variables_in_file)
+  // b) declareVariable() for each Variable (order must be consistent
+  //    between 32-bit and 64-bit); in the Using phase, returns some
+  //    information about the Variable from 32-bit compilation
+  // c) endVariables()
+
+  void beginVariables(size_t Count) {
+    mVariablesOrderFatal = false;
+    begin(&File::mVariables, Count);
+  }
+
+  // If isUsing(), returns variable's 32-bit AllocSize; otherwise, returns NoVal32().
+  Val32 declareVariable(const RSExportVar *EV);
+
+  void endVariables();
+
+  // ----------------------------------------------------------------------
+
+  // ReflectionState has a notion of "current file".  After an
+  // openJava*() or closeJava*() call, there is no current file.
+  // Calling the nextFile() method when in the Collecting or Using
+  // state "advances" to the next file in the list of files being
+  // compiled, whose properties are specified by the arguments to
+  // nextFile().  All of the various begin*(), declare*(), end*()
+  // etc. calls implicitly refer to entities in the current file.
+  //
+  // RSC must remain valid until the next call to nextFile() or the
+  // next S_* state change.
+  void nextFile(const RSContext *RSC, const std::string &PackageName, const std::string &RSSourceFileName);
+
+  // ----------------------------------------------------------------------
+
+ private:
+  enum State {
+    S_Initial,          // No captured information
+    S_OpenJava32,       // Capturing information for 32-bit Java
+    S_ClosedJava32,     // Captured  information for 32-bit Java
+    S_OpenJava64,       // Capturing information for 64-bit Java
+    S_ClosedJava64,     // Captured  information for 64-bit Java
+    S_Bad,              // Abnormal termination
+  };
+
+  // context associated with compilation of the current file
+  const RSContext *mRSC;
+
+  State mState;
+
+  /*== ForEach ==================================================================*/
+
+  // The data in this section is transient during ForEach processing
+  // for each File.
+
+  int mForEachOpen;    // if nonnegative, then ordinal of beginForEach() without matching endForEach()
+  bool mForEachFatal;  // fatal mismatch in comparing ForEach; do no further comparisons for it
+
+  // Tracks mismatches discovered during the Use phase.
+  // There are two possibilities:
+  // - if (ordinal + 1) is greater than the number of ForEaches from the Collecting phase,
+  //   then this is an "extra" ForEach discovered during the Use phase
+  // - otherwise the Collecting phase and the Use phase disagree on the name of the
+  //   ForEach at this ordinal position (the Collecting phase's kernel name is
+  //   available in mFiles.Current().mForEaches[ordinal].mName)
+  llvm::SmallVector<const RSExportForEach *, 0> mForEachesBad;
+
+  // During the Use phase, keep track of how many ForEach ordinals we
+  // have seen that correspond to ordinals seen during the Collect
+  // phase.  This helps determine whether we have to issue errors at
+  // endForEaches().
+  size_t mNumForEachesMatchedByOrdinal;
+
+  /*== Invokable ================================================================*/
+
+  // 32-bit and 64-bit compiles need to see invokables in the same
+  // order, because of slot number assignment.  Once we see the first
+  // name mismatch in the sequence of invokables for a given File, it
+  // doesn't make sense to issue further diagnostics regarding
+  // invokables for that File.
+  bool mInvokablesOrderFatal;
+
+  /*== OutputClass ==============================================================*/
+
+  // This data tracks information about a class being generated -- a
+  // script class or a type class.  We call such a class "Divergent"
+  // if it needs to have at least one runtime check to distinguish
+  // between 32-bit and 64-bit targets.
+
+  bool mOutputClassOpen;  // beginOutputClass() without matching endOutputClass()
+  bool mOutputClassDivergent;  // has class been marked divergent?
+
+  /*== Record ===================================================================*/
+
+  // This field enforces necessary discipline on the use of
+  // beginRecords()/declareRecord()/endRecord().
+  enum {
+    RS_Initial,  // no beginRecords() yet for current File
+    RS_Open,     // beginRecords() but no endRecords() for current File
+    RS_Closed    // endRecords() for current File
+  } mRecordsState;
+
+  // During the Use phase, keep track of how many records we have seen
+  // that have same-named counterparts seen during the Collect phase.
+  // This helps determine whether we have to issue errors at
+  // endRecords().
+  size_t mNumRecordsMatchedByName;
+
+  /*== Reduce ===================================================================*/
+
+  // 32-bit and 64-bit compiles need to see reduction kernels in the
+  // same order, because of slot number assignment.  Once we see the
+  // first name mismatch in the sequence of reduction kernels for a
+  // given File, it doesn't make sense to issue further diagnostics
+  // regarding reduction kernels for that File.
+  bool mReducesOrderFatal;
+
+  /*== Variable =================================================================*/
+
+  // 32-bit and 64-bit compiles need to see variables in the same
+  // order, because of slot number assignment.  Once we see the first
+  // name mismatch in the sequence of variables for a given File, it
+  // doesn't make sense to issue further diagnostics regarding
+  // variables for that File.
+  bool mVariablesOrderFatal;
+
+  /*=============================================================================*/
+
+  bool isActive() const { return isCollecting() || isUsing(); }
+  bool isClosed() const { return mState==S_ClosedJava32 || mState==S_ClosedJava64; }
+  bool isUsing() const { return mState==S_OpenJava64; }
+
+  // For anything with a type (such as a Variable or a Record field),
+  // the type is represented via its name.  To save space, we don't
+  // create multiple instances of the same name -- we have a canonical
+  // instance in mStringSet, and use a StringRef to refer to it.  The
+  // method canon() returns a StringRef to the canonical
+  // instance, creating the instance if necessary.
+  llvm::StringRef canon(const std::string &String);
+  llvm::StringSet<> *mStringSet;
+
+  // Synthesize a name for the specified type.  There should be a
+  // one-to-one correspondence between the name and a C type (after
+  // typedefs and integer expressions have been "flattened", and
+  // considering a struct type to be identified solely by its name).
+  static std::string getUniqueTypeName(const RSExportType *T);
+
+  // ------------------------------
+  // template class ArrayWithCursor
+  // ------------------------------
+  //
+  // This class represents a fixed-length dynamically-allocated array
+  // (length is specified by a method call after instantiation) along
+  // with a cursor that traverses the array.  The behavior of the
+  // class is very specific to the needs of ReflectionState.
+  //
+  // The model for using this class is as follows:
+  // a) Instantiate a class instance.  The instance is in the
+  //    S_Initial state.
+  // b) Call BeginCollecting() with an array capacity.  This allocates
+  //    the array members and moves the instance to the S_Collecting
+  //    state.  The array size (contrast with capacity) is zero, and
+  //    the cursor has not been placed.
+  // c) Call CollectNext() a number of times equal to the capacity.
+  //    Each time CollectNext() is called, it extends the array size
+  //    by 1, and advances the cursor to the "new" member.  The idea
+  //    is to set the value of the "new" member at this time.
+  // d) Call BeginUsing().  This moves the instance to the S_Using
+  //    state and "unplaces" the cursor.
+  // e) Call UseNext() a number of times equal to the capacity.  Each
+  //    time UseNext() is called, it advances the cursor to the next
+  //    member (first member, the first time it is called).
+  //    The cursor is stepping through the members that were "created"
+  //    by CollectNext() during the S_Collecting state; the idea is to
+  //    look at their values.
+  // f) Destroy the instance.
+  //
+  template <typename Member> class ArrayWithCursor {
+   public:
+    ArrayWithCursor() : mState(S_Initial), mMembers(nullptr), mCapacity(0), mSize(0), mCursor(~size_t(0)) { }
+
+    ~ArrayWithCursor() { delete [] mMembers; }
+
+    ArrayWithCursor(const ArrayWithCursor &) = delete;
+    void operator=(const ArrayWithCursor &) = delete;
+
+    void BeginCollecting(size_t Size) {
+      slangAssert(mState == S_Initial);
+      mState = S_Collecting;
+      mMembers = new Member[Size];
+      mCapacity = Size;
+    }
+    // Increments the array size, advances the cursor to the new
+    // member, and returns a reference to that member.
+    Member &CollectNext() {
+      slangAssert((mState == S_Collecting) && (mCursor + 1 == mSize) && (mSize < mCapacity));
+      ++mSize;
+      return mMembers[++mCursor];
+    }
+
+    void BeginUsing() {
+      slangAssert((mState == S_Collecting) && (mCursor + 1 == mSize) && (mSize == mCapacity));
+      mState = S_Using;
+      mCursor = ~size_t(0);
+    }
+    // Advances the cursor to the next member, and returns a reference
+    // to that member.
+    Member &UseNext() {
+      slangAssert((mState == S_Using) && (mCursor + 1 < mSize));
+      return mMembers[++mCursor];
+    }
+
+    // Is the cursor on the last array member?
+    bool isFinished() const {
+      return mCursor + 1 == mSize;
+    }
+
+    size_t Size() const { return mSize; }
+
+    // Return a reference to the member under the cursor.
+    Member &Current() {
+      slangAssert(mCursor < mSize);
+      return mMembers[mCursor];
+    }
+    const Member &Current() const {
+      slangAssert(mCursor < mSize);
+      return mMembers[mCursor];
+    }
+    // Return the cursor position (zero-based).  Cursor must have been
+    // placed (i.e., if we're Collecting, we must have called
+    // CollectNext() at least once; and if we're Using, we must have
+    // called UseNext() at least once).
+    size_t CurrentIdx() const {
+      slangAssert(mCursor < mSize);
+      return mCursor;
+    }
+
+    // Return a reference to the specified member.  Must be within the
+    // array size (not merely within its capacity).
+    Member &operator[](size_t idx) {
+      slangAssert(idx < mSize);
+      return mMembers[idx];
+    }
+    const Member &operator[](size_t idx) const {
+      slangAssert(idx < mSize);
+      return mMembers[idx];
+    }
+
+   private:
+    enum State { S_Initial, S_Collecting, S_Using };
+    State mState;
+
+    Member *mMembers;
+    size_t mCapacity;
+    size_t mSize;
+    size_t mCursor;
+  };
+
+
+  struct File {
+    File() : mForEaches(nullptr) { }
+    ~File() { delete [] mForEaches; }
+
+    File(const File &) = delete;
+    void operator=(const File &) = delete;
+
+    std::string mPackageName;
+    std::string mRSSourceFileName;
+
+    struct ForEach {
+      ForEach() : mState(S_Initial) { }
+      ForEach(const ForEach &) = delete;
+      void operator=(const ForEach &) = delete;
+
+      enum {
+        S_Initial,    // ForEach has been instantiated
+        S_Collected,  // beginForEach() has been called while Collecting
+        S_UseMatched  // beginForEach() has been called while Using,
+                      //   and found this ForEach
+      } mState;
+
+      std::string mName;
+
+      // Types.  mIns[] and mOut can be null in case we have an
+      // old-style kernel with a void* input or output.
+      ArrayWithCursor<llvm::StringRef> mIns;
+      ArrayWithCursor<llvm::StringRef> mParams;
+      llvm::StringRef mOut;
+      bool mHasOut;  // to distinguish between no output and void* output.
+
+      unsigned mSignatureMetadata;
+      bool mIsKernel;  // new-style (by-value) rather than old-style
+    };
+    ForEach *mForEaches;  // indexed by ordinal (lexical order)
+    size_t mForEachCount;
+
+    struct Invokable {
+      Invokable() : mParams(nullptr) { }
+      ~Invokable() { delete [] mParams; }
+
+      Invokable(const Invokable &) = delete;
+      void operator=(const Invokable &) = delete;
+
+      std::string mName;
+      llvm::StringRef *mParams;  // Types
+      size_t mParamCount;
+    };
+    ArrayWithCursor<Invokable> mInvokables;
+
+    // There are two things we need to do with a Record:
+    // - Support structure sizes and layouts that differ between
+    //   32-bit and 64-bit compilation.
+    // - Do consistency checking between 32-bit and 64-bit compilation.
+    //
+    // TODO: Move this out of File to avoid duplication?  That is,
+    //       instead of tracking Records on a per-File basis, instead
+    //       track them globally?
+    //
+    //       (Because of ODR, we shouldn't have inconsistencies
+    //       between Files.)
+    //
+    struct Record {
+      Record() : mFields(nullptr) { }
+      ~Record() { delete [] mFields; }
+
+      Record(const Record &) = delete;
+      void operator=(const Record &) = delete;
+
+      struct Field {
+        std::string mName;
+        llvm::StringRef mType;
+        size_t mPrePadding;   // this.OffsetInParent - (prev.OffsetInParent + prev.AllocSize)
+        size_t mPostPadding;  // this.AllocSize - this.StoreSize
+        size_t mOffset;       // this.OffsetInParent
+        size_t mStoreSize;    // this.StoreSize
+      };
+      Field *mFields;
+      size_t mFieldCount;
+      size_t mPostPadding;    // padding after the end of the padded
+                              //   last field
+      size_t mAllocSize;
+      bool mOrdinary;         // anything other than an
+                              //   internally-synthesized helper
+                              //   record.  We do not emit diagnostics
+                              //   for inconsistent helper records.
+      bool mMatchedByName;    // has declareRecord() been called on
+                              //   this record during the Using phase?
+    };
+    llvm::StringMap<Record> mRecords;
+
+    struct Reduce {
+      Reduce() : mAccumIns(nullptr) { }
+      ~Reduce() { delete [] mAccumIns; }
+
+      Reduce(const Reduce &) = delete;
+      void operator=(const Reduce &) = delete;
+
+      std::string mName;
+
+      // only apply to exportable
+      llvm::StringRef *mAccumIns;  // Types
+      size_t mAccumInCount;
+      llvm::StringRef mResult;  // Type
+
+      bool mIsExportable;
+    };
+    ArrayWithCursor<Reduce> mReduces;
+
+    struct Variable {
+      Variable() : mInitializers(nullptr) { }
+      ~Variable() { delete [] mInitializers; }
+
+      Variable(const Variable &) = delete;
+      void operator=(const Variable &) = delete;
+
+      std::string mName;
+      llvm::StringRef mType;
+      clang::APValue *mInitializers;
+      size_t mInitializerCount;
+      size_t mAllocSize;
+      bool mIsConst;
+    };
+    ArrayWithCursor<Variable> mVariables;
+
+  };
+  ArrayWithCursor<File> mFiles;
+
+  // Utility template -- common pattern used by many begin*() methods.
+  template <typename Member>
+  void begin(ArrayWithCursor<Member> File::*Array, size_t Count) {
+    slangAssert(!isClosed());
+    if (!isActive())
+      return;
+
+    auto &file = mFiles.Current();
+    if (isCollecting())
+      (file.*Array).BeginCollecting(Count);
+    if (isUsing())
+      (file.*Array).BeginUsing();
+  }
+
+ public:
+
+  // This class represents 32-bit layout information built up during
+  // the Collecting phase, for use during the Using phase.  It
+  // provides an interface between class ReflectionState and client
+  // code that actually performs reflection.
+  class Record32 {
+    friend class ReflectionState;
+
+   public:
+    Record32() : mRecord(nullptr) { }
+
+    Val32 getRecordPostPadding() const {
+      if (!mRecord)
+        return NoVal32();
+      return Val32(true, mRecord->mPostPadding);
+    }
+
+    Val32 getRecordAllocSize() const {
+      if (!mRecord)
+        return NoVal32();
+      return Val32(true, mRecord->mAllocSize);
+    }
+
+    std::pair<Val32, Val32> getFieldPreAndPostPadding(unsigned idx) const {
+      if (!mRecord || idx >= mRecord->mFieldCount)
+        return std::make_pair(NoVal32(), NoVal32());
+      const File::Record::Field &field = mRecord->mFields[idx];
+      return std::make_pair(Val32(true, field.mPrePadding), Val32(true, field.mPostPadding));
+    }
+
+    std::pair<Val32, Val32> getFieldOffsetAndStoreSize(unsigned idx) const {
+      if (!mRecord || idx >= mRecord->mFieldCount)
+        return std::make_pair(NoVal32(), NoVal32());
+      const File::Record::Field &field = mRecord->mFields[idx];
+      return std::make_pair(Val32(true, field.mOffset), Val32(true, field.mStoreSize));
+    }
+
+   private:
+    Record32(const File::Record *Record) : mRecord(Record) { }
+    const File::Record *mRecord;
+  };
+};
+
+}
+
+#endif  // _FRAMEWORKS_COMPILE_SLANG_REFLECTION_STATE_H_  NOLINT
diff --git a/slang_version.h b/slang_version.h
index d56d175..aae7d04 100644
--- a/slang_version.h
+++ b/slang_version.h
@@ -39,6 +39,7 @@
   SLANG_JB_MR1_TARGET_API = 17,
   SLANG_JB_MR2_TARGET_API = 18,
   SLANG_KK_TARGET_API = 19,
+  SLANG_L_TARGET_API = 21,
   SLANG_M_TARGET_API = 23,
   SLANG_N_TARGET_API = 24,
   SLANG_N_MR1_TARGET_API = 25,
diff --git a/tests/F_reflection3264_foreach_mismatch/reflection3264_foreach_mismatch.rs b/tests/F_reflection3264_foreach_mismatch/reflection3264_foreach_mismatch.rs
new file mode 100644
index 0000000..c8e4a6d
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch/reflection3264_foreach_mismatch.rs
@@ -0,0 +1,141 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// disagree on RS_KERNEL
+
+#ifdef __LP64__
+void aa(int *aout) { }
+#else
+void RS_KERNEL aa(double in) { }
+#endif
+
+#ifdef __LP64__
+int RS_KERNEL bb(float fin, double din) { return 0; }
+#else
+void bb(const long *ain) { }
+#endif
+
+// two different non-void* output types
+
+void cc(size_t *out) { }
+
+size_t RS_KERNEL dd() { return 0; }
+
+// one non-void* output type, one void* output type
+
+#ifdef __LP64__
+void ee(const int *in, short *out) { }
+void ff(const int *in, void *out) { }
+#else
+void ee(const int *in, void *out) { }
+void ff(const int *in, short *out) { }
+#endif
+
+// one non-void* output type, one no-output
+
+#ifdef __LP64__
+void gg(const int *in, int *out) { }
+void hh(const int *in) { }
+int RS_KERNEL ii(int v) { return 0; }
+void RS_KERNEL jj(int v) { }
+#else
+void gg(const int *in) { }
+void hh(const int *in, int *out) { }
+void RS_KERNEL ii(int v) { }
+int RS_KERNEL jj(int v) { return 0; }
+#endif
+
+// one void* output type, one no-output
+
+#ifdef __LP64__
+void kk(const int *in, void *out) { }
+void ll(const int *in) { }
+#else
+void kk(const int *in) { }
+void ll(const int *in, void *out) { }
+#endif
+
+// disagree on input count
+
+void mm(
+#ifdef __LP64__
+const int *in,
+#endif
+  double *out) { }
+
+void RS_KERNEL nn(
+#ifdef __LP64__
+int in0,
+#endif
+  size_t v) { }
+
+// disagree on param count
+
+void oo(const size_t *in, size_t *out
+#ifdef __LP64__
+            , const char *d
+#endif
+            ) { }
+
+// disagree on special parameters
+
+void pp(const int *in,
+#ifdef __LP64__
+          int x,
+#endif
+          int y) { }
+
+void RS_KERNEL qq(int in0, long in1,
+#ifdef __LP64__
+int x
+#else
+int y
+#endif
+                      ) { }
+
+// disagree on input types
+
+void rr(const size_t *in) { }
+
+void ss(
+#ifdef __LP64__
+const void *in
+#else
+const char *in
+#endif
+) { }
+
+void tt(
+#ifdef __LP64__
+const short *in
+#else
+const void *in
+#endif
+) { }
+
+struct S { int f; } s;
+struct T { int f; } t;
+#ifdef __LP64__
+#define QQTYPE struct T
+#else
+#define QQTYPE struct S
+#endif
+
+void RS_KERNEL uu(int a, size_t b, char c, QQTYPE d) { }
+
+// disagree on param types
+
+void vv(const int *a, const size_t *b) { }
+
+// ... note that today, a void* param is ignored for reflection
+#ifdef __LP64__
+void ww(const int *a, const void *b) { }
+void xx(const int *a, const float *b) { }
+void yy(const int *a, const void *b) { }
+void zz(const int *a) { }
+#else
+void ww(const int *a, const float *b) { }
+void xx(const int *a, const void *b) { }
+void yy(const int *a) { }
+void zz(const int *a, const void *b) { }
+#endif
diff --git a/tests/F_reflection3264_foreach_mismatch/stderr.txt.expect b/tests/F_reflection3264_foreach_mismatch/stderr.txt.expect
new file mode 100644
index 0000000..e24f176
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch/stderr.txt.expect
@@ -0,0 +1,26 @@
+reflection3264_foreach_mismatch.rs:13:15: error: foreach kernel 'bb' has __attribute__((kernel)) for 64-bit targets but not for 32-bit targets
+reflection3264_foreach_mismatch.rs:22:18: error: foreach kernel 'dd' has output type 'uint' for 32-bit targets but output type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch.rs:39:15: error: foreach kernel 'ii' has output type 'int' for 64-bit targets but no output for 32-bit targets
+reflection3264_foreach_mismatch.rs:40:16: error: foreach kernel 'jj' has output type 'int' for 32-bit targets but no output for 64-bit targets
+reflection3264_foreach_mismatch.rs:66:16: error: foreach kernel 'nn' has 1 input for 32-bit targets but 2 inputs for 64-bit targets
+reflection3264_foreach_mismatch.rs:88:16: error: foreach kernel 'qq' has different special parameters for 32-bit targets than for 64-bit targets
+reflection3264_foreach_mismatch.rs:124:16: error: 2nd input of foreach kernel 'uu' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch.rs:124:16: error: 4th input of foreach kernel 'uu' has type 'struct S' for 32-bit targets but type 'struct T' for 64-bit targets
+reflection3264_foreach_mismatch.rs:133:6: error: foreach kernel 'xx' has 0 usrData parameters for 32-bit targets but 1 usrData parameter for 64-bit targets
+reflection3264_foreach_mismatch.rs:132:6: error: foreach kernel 'ww' has 1 usrData parameter for 32-bit targets but 0 usrData parameters for 64-bit targets
+reflection3264_foreach_mismatch.rs:128:6: error: 1st usrData parameter of foreach kernel 'vv' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch.rs:108:6: error: 1st input of foreach kernel 'tt' has type 'short' for 64-bit targets but is untyped for 32-bit targets
+reflection3264_foreach_mismatch.rs:100:6: error: 1st input of foreach kernel 'ss' has type 'char' for 32-bit targets but is untyped for 64-bit targets
+reflection3264_foreach_mismatch.rs:98:6: error: 1st input of foreach kernel 'rr' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch.rs:82:6: error: foreach kernel 'pp' has different special parameters for 32-bit targets than for 64-bit targets
+reflection3264_foreach_mismatch.rs:74:6: error: foreach kernel 'oo' has output type 'uint' for 32-bit targets but output type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch.rs:74:6: error: foreach kernel 'oo' has 0 usrData parameters for 32-bit targets but 1 usrData parameter for 64-bit targets
+reflection3264_foreach_mismatch.rs:60:6: error: foreach kernel 'mm' has 0 inputs for 32-bit targets but 1 input for 64-bit targets
+reflection3264_foreach_mismatch.rs:52:6: error: foreach kernel 'll' has untyped output for 32-bit targets but no output for 64-bit targets
+reflection3264_foreach_mismatch.rs:51:6: error: foreach kernel 'kk' has untyped output for 64-bit targets but no output for 32-bit targets
+reflection3264_foreach_mismatch.rs:38:6: error: foreach kernel 'hh' has output type 'int' for 32-bit targets but no output for 64-bit targets
+reflection3264_foreach_mismatch.rs:37:6: error: foreach kernel 'gg' has output type 'int' for 64-bit targets but no output for 32-bit targets
+reflection3264_foreach_mismatch.rs:28:6: error: foreach kernel 'ff' has output type 'short' for 32-bit targets but has untyped output for 64-bit targets
+reflection3264_foreach_mismatch.rs:27:6: error: foreach kernel 'ee' has output type 'short' for 64-bit targets but has untyped output for 32-bit targets
+reflection3264_foreach_mismatch.rs:20:6: error: foreach kernel 'cc' has output type 'uint' for 32-bit targets but output type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch.rs:7:6: error: foreach kernel 'aa' has __attribute__((kernel)) for 32-bit targets but not for 64-bit targets
diff --git a/tests/F_reflection3264_foreach_mismatch/stdout.txt.expect b/tests/F_reflection3264_foreach_mismatch/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch/stdout.txt.expect
diff --git a/tests/F_reflection3264_foreach_mismatch_extra32/reflection3264_foreach_mismatch_extra32.rs b/tests/F_reflection3264_foreach_mismatch_extra32/reflection3264_foreach_mismatch_extra32.rs
new file mode 100644
index 0000000..8bf08c3
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_extra32/reflection3264_foreach_mismatch_extra32.rs
@@ -0,0 +1,14 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+void aa(const int *in) { }
+
+void RS_KERNEL bb(int in) { }
+
+#ifndef __LP64__
+
+void cc(const int *in) { }
+
+void RS_KERNEL dd(int in) { }
+
+#endif
diff --git a/tests/F_reflection3264_foreach_mismatch_extra32/stderr.txt.expect b/tests/F_reflection3264_foreach_mismatch_extra32/stderr.txt.expect
new file mode 100644
index 0000000..a5c8588
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_extra32/stderr.txt.expect
@@ -0,0 +1,2 @@
+error: in file 'reflection3264_foreach_mismatch_extra32.rs' foreach kernel 'cc' is only present for 32-bit targets
+error: in file 'reflection3264_foreach_mismatch_extra32.rs' foreach kernel 'dd' is only present for 32-bit targets
diff --git a/tests/F_reflection3264_foreach_mismatch_extra32/stdout.txt.expect b/tests/F_reflection3264_foreach_mismatch_extra32/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_extra32/stdout.txt.expect
diff --git a/tests/F_reflection3264_foreach_mismatch_extra64/reflection3264_foreach_mismatch_extra64.rs b/tests/F_reflection3264_foreach_mismatch_extra64/reflection3264_foreach_mismatch_extra64.rs
new file mode 100644
index 0000000..469ec99
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_extra64/reflection3264_foreach_mismatch_extra64.rs
@@ -0,0 +1,14 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+void aa(const int *in) { }
+
+void RS_KERNEL bb(int in) { }
+
+#ifdef __LP64__
+
+void cc(const int *in) { }
+
+void RS_KERNEL dd(int in) { }
+
+#endif
diff --git a/tests/F_reflection3264_foreach_mismatch_extra64/stderr.txt.expect b/tests/F_reflection3264_foreach_mismatch_extra64/stderr.txt.expect
new file mode 100644
index 0000000..4e8160e
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_extra64/stderr.txt.expect
@@ -0,0 +1,2 @@
+reflection3264_foreach_mismatch_extra64.rs:10:6: error: foreach kernel 'cc' is only present for 64-bit targets
+reflection3264_foreach_mismatch_extra64.rs:12:16: error: foreach kernel 'dd' is only present for 64-bit targets
diff --git a/tests/F_reflection3264_foreach_mismatch_extra64/stdout.txt.expect b/tests/F_reflection3264_foreach_mismatch_extra64/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_extra64/stdout.txt.expect
diff --git a/tests/F_reflection3264_foreach_mismatch_name32/reflection3264_foreach_mismatch_name32.rs b/tests/F_reflection3264_foreach_mismatch_name32/reflection3264_foreach_mismatch_name32.rs
new file mode 100644
index 0000000..89b597b
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_name32/reflection3264_foreach_mismatch_name32.rs
@@ -0,0 +1,23 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// There are multiple name mismatches (cc*, dd*) but only the first is
+// reported.  This reporting doesn't prevent errors for kernels with
+// matched names from being reported.
+
+void aa(const size_t *in) { }
+
+#ifdef __LP64__
+void cc64(const int *in) { }
+void dd64(const int *in) { }
+#else
+void cc32(const float *in) { }
+void dd32(const float *in) { }
+#endif
+
+void RS_KERNEL bb(size_t in) { }
+
+// extra kernel goes unreported because of cc* name mismatch
+#ifndef __LP64__
+void e(const int *in) { }
+#endif
diff --git a/tests/F_reflection3264_foreach_mismatch_name32/stderr.txt.expect b/tests/F_reflection3264_foreach_mismatch_name32/stderr.txt.expect
new file mode 100644
index 0000000..1d58483
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_name32/stderr.txt.expect
@@ -0,0 +1,3 @@
+reflection3264_foreach_mismatch_name32.rs:18:16: error: 1st input of foreach kernel 'bb' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch_name32.rs:8:6: error: 1st input of foreach kernel 'aa' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch_name32.rs:11:6: error: 2nd foreach kernel is 'cc32' for 32-bit targets but 'cc64' for 64-bit targets
diff --git a/tests/F_reflection3264_foreach_mismatch_name32/stdout.txt.expect b/tests/F_reflection3264_foreach_mismatch_name32/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_name32/stdout.txt.expect
diff --git a/tests/F_reflection3264_foreach_mismatch_name64/reflection3264_foreach_mismatch_name64.rs b/tests/F_reflection3264_foreach_mismatch_name64/reflection3264_foreach_mismatch_name64.rs
new file mode 100644
index 0000000..59646f5
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_name64/reflection3264_foreach_mismatch_name64.rs
@@ -0,0 +1,23 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// There are multiple name mismatches (cc*, dd*) but only the first is
+// reported.  This reporting doesn't prevent errors for kernels with
+// matched names from being reported.
+
+void aa(const size_t *in) { }
+
+#ifdef __LP64__
+void cc64(const int *in) { }
+void dd64(const int *in) { }
+#else
+void cc32(const float *in) { }
+void dd32(const float *in) { }
+#endif
+
+void RS_KERNEL bb(size_t in) { }
+
+// extra kernel goes unreported because of cc* name mismatch
+#ifdef __LP64__
+void e(const int *in) { }
+#endif
diff --git a/tests/F_reflection3264_foreach_mismatch_name64/stderr.txt.expect b/tests/F_reflection3264_foreach_mismatch_name64/stderr.txt.expect
new file mode 100644
index 0000000..2175d70
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_name64/stderr.txt.expect
@@ -0,0 +1,3 @@
+reflection3264_foreach_mismatch_name64.rs:18:16: error: 1st input of foreach kernel 'bb' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch_name64.rs:8:6: error: 1st input of foreach kernel 'aa' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_foreach_mismatch_name64.rs:11:6: error: 2nd foreach kernel is 'cc32' for 32-bit targets but 'cc64' for 64-bit targets
diff --git a/tests/F_reflection3264_foreach_mismatch_name64/stdout.txt.expect b/tests/F_reflection3264_foreach_mismatch_name64/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_foreach_mismatch_name64/stdout.txt.expect
diff --git a/tests/F_reflection3264_invokable_extra32/reflection3264_invokable_extra32.rs b/tests/F_reflection3264_invokable_extra32/reflection3264_invokable_extra32.rs
new file mode 100644
index 0000000..18ce97f
--- /dev/null
+++ b/tests/F_reflection3264_invokable_extra32/reflection3264_invokable_extra32.rs
@@ -0,0 +1,16 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+void a() { }
+
+void b() { }
+
+void c() { }
+
+#ifndef __LP64__
+
+void d() { }
+
+void e() { }
+
+#endif
diff --git a/tests/F_reflection3264_invokable_extra32/stderr.txt.expect b/tests/F_reflection3264_invokable_extra32/stderr.txt.expect
new file mode 100644
index 0000000..ba0f30a
--- /dev/null
+++ b/tests/F_reflection3264_invokable_extra32/stderr.txt.expect
@@ -0,0 +1,2 @@
+error: in file 'reflection3264_invokable_extra32.rs' invokable function 'd' is only present for 32-bit targets
+error: in file 'reflection3264_invokable_extra32.rs' invokable function 'e' is only present for 32-bit targets
diff --git a/tests/F_reflection3264_invokable_extra32/stdout.txt.expect b/tests/F_reflection3264_invokable_extra32/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_invokable_extra32/stdout.txt.expect
diff --git a/tests/F_reflection3264_invokable_extra64/reflection3264_invokable_extra64.rs b/tests/F_reflection3264_invokable_extra64/reflection3264_invokable_extra64.rs
new file mode 100644
index 0000000..e9c1e1f
--- /dev/null
+++ b/tests/F_reflection3264_invokable_extra64/reflection3264_invokable_extra64.rs
@@ -0,0 +1,16 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+void a() { }
+
+void b() { }
+
+void c() { }
+
+#ifdef __LP64__
+
+void d() { }
+
+void e() { }
+
+#endif
diff --git a/tests/F_reflection3264_invokable_extra64/stderr.txt.expect b/tests/F_reflection3264_invokable_extra64/stderr.txt.expect
new file mode 100644
index 0000000..4f0d9f9
--- /dev/null
+++ b/tests/F_reflection3264_invokable_extra64/stderr.txt.expect
@@ -0,0 +1,2 @@
+reflection3264_invokable_extra64.rs:12:6: error: invokable function 'd' is only present for 64-bit targets
+reflection3264_invokable_extra64.rs:14:6: error: invokable function 'e' is only present for 64-bit targets
diff --git a/tests/F_reflection3264_invokable_extra64/stdout.txt.expect b/tests/F_reflection3264_invokable_extra64/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_invokable_extra64/stdout.txt.expect
diff --git a/tests/F_reflection3264_invokable_mismatch/reflection3264_invokable_mismatch.rs b/tests/F_reflection3264_invokable_mismatch/reflection3264_invokable_mismatch.rs
new file mode 100644
index 0000000..5b3527b
--- /dev/null
+++ b/tests/F_reflection3264_invokable_mismatch/reflection3264_invokable_mismatch.rs
@@ -0,0 +1,33 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+#ifdef __LP64__
+void a(float f) { }
+#else
+void a(double f, float g) { }
+#endif
+
+void b(int j, size_t k, int l, ssize_t m) { }
+
+#ifdef __LP64__
+void c64() { }
+#else
+void c32() { }
+#endif
+
+// the errors after this point should go unreported, because of the
+// invokable name mismatch above (c32 versus c64)
+
+#ifdef __LP64__
+void z(float f) { }
+#else
+void z(double f, float g) { }
+#endif
+
+void y(int j, size_t k, int l, ssize_t m) { }
+
+#ifdef __LP64__
+void x64() { }
+#else
+void x32() { }
+#endif
diff --git a/tests/F_reflection3264_invokable_mismatch/stderr.txt.expect b/tests/F_reflection3264_invokable_mismatch/stderr.txt.expect
new file mode 100644
index 0000000..868ec30
--- /dev/null
+++ b/tests/F_reflection3264_invokable_mismatch/stderr.txt.expect
@@ -0,0 +1,4 @@
+reflection3264_invokable_mismatch.rs:5:6: error: invokable function 'a' has 2 parameters for 32-bit targets but 1 parameter for 64-bit targets
+reflection3264_invokable_mismatch.rs:10:6: error: 2nd parameter of invokable function 'b' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_invokable_mismatch.rs:10:6: error: 4th parameter of invokable function 'b' has type 'int' for 32-bit targets but type 'long' for 64-bit targets
+reflection3264_invokable_mismatch.rs:13:6: error: 3rd invokable function is 'c32' for 32-bit targets but 'c64' for 64-bit targets
diff --git a/tests/F_reflection3264_invokable_mismatch/stdout.txt.expect b/tests/F_reflection3264_invokable_mismatch/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_invokable_mismatch/stdout.txt.expect
diff --git a/tests/F_reflection3264_multifile/reflection3264_multifile_1.rs b/tests/F_reflection3264_multifile/reflection3264_multifile_1.rs
new file mode 100644
index 0000000..8ea1418
--- /dev/null
+++ b/tests/F_reflection3264_multifile/reflection3264_multifile_1.rs
@@ -0,0 +1,10 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// no errors in this file, so we should compile reflection3264_multifile_2.rs
+
+int v;
+
+int w;
+
+void f1(int a) { }
diff --git a/tests/F_reflection3264_multifile/reflection3264_multifile_2.rs b/tests/F_reflection3264_multifile/reflection3264_multifile_2.rs
new file mode 100644
index 0000000..2b5be58
--- /dev/null
+++ b/tests/F_reflection3264_multifile/reflection3264_multifile_2.rs
@@ -0,0 +1,16 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+short v;
+
+short w;
+
+void f2(int a) { }
+
+// error: invokable is only present for 32-bit targets
+#ifndef __LP64__
+void g() { }
+#endif
+
+// error: 'in2' has different types for 32-bit and 64-bit targets
+void RS_KERNEL m(int in1, size_t in2) { }
diff --git a/tests/F_reflection3264_multifile/reflection3264_multifile_3.rs b/tests/F_reflection3264_multifile/reflection3264_multifile_3.rs
new file mode 100644
index 0000000..7bf2788
--- /dev/null
+++ b/tests/F_reflection3264_multifile/reflection3264_multifile_3.rs
@@ -0,0 +1,8 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// we stop compiling after the first file with an error;
+// reflection3264_multifile_2.rs has errors, so we never get here, and
+// never report errors for this file's 'v' and 'w'.
+
+size_t v, w;
diff --git a/tests/F_reflection3264_multifile/stderr.txt.expect b/tests/F_reflection3264_multifile/stderr.txt.expect
new file mode 100644
index 0000000..31c4d5f
--- /dev/null
+++ b/tests/F_reflection3264_multifile/stderr.txt.expect
@@ -0,0 +1,2 @@
+reflection3264_multifile_2.rs:16:16: error: 2nd input of foreach kernel 'm' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+error: in file 'reflection3264_multifile_2.rs' invokable function 'g' is only present for 32-bit targets
diff --git a/tests/F_reflection3264_multifile/stdout.txt.expect b/tests/F_reflection3264_multifile/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_multifile/stdout.txt.expect
diff --git a/tests/F_reflection3264_package_mismatch/reflection3264_package_mismatch.rs b/tests/F_reflection3264_package_mismatch/reflection3264_package_mismatch.rs
new file mode 100644
index 0000000..d0452f8
--- /dev/null
+++ b/tests/F_reflection3264_package_mismatch/reflection3264_package_mismatch.rs
@@ -0,0 +1,8 @@
+#pragma version(1)
+
+#ifdef __LP64__
+#pragma rs java_package_name(sixty_four)
+#else
+#pragma rs java_package_name(thirty_two)
+#endif
+
diff --git a/tests/F_reflection3264_package_mismatch/stderr.txt.expect b/tests/F_reflection3264_package_mismatch/stderr.txt.expect
new file mode 100644
index 0000000..030f573
--- /dev/null
+++ b/tests/F_reflection3264_package_mismatch/stderr.txt.expect
@@ -0,0 +1 @@
+error: in file 'reflection3264_package_mismatch.rs' Java package name is 'thirty_two' for 32-bit targets but 'sixty_four' for 64-bit targets
diff --git a/tests/F_reflection3264_package_mismatch/stdout.txt.expect b/tests/F_reflection3264_package_mismatch/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_package_mismatch/stdout.txt.expect
diff --git a/tests/F_reflection3264_reduce_extra32/reflection3264_reduce_extra32.rs b/tests/F_reflection3264_reduce_extra32/reflection3264_reduce_extra32.rs
new file mode 100644
index 0000000..e734158
--- /dev/null
+++ b/tests/F_reflection3264_reduce_extra32/reflection3264_reduce_extra32.rs
@@ -0,0 +1,12 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+static void accum(int *a, int v) { }
+
+#pragma rs reduce(aa) accumulator(accum)
+#pragma rs reduce(bb) accumulator(accum)
+
+#ifndef __LP64__
+#pragma rs reduce(cc) accumulator(accum)
+#pragma rs reduce(dd) accumulator(accum)
+#endif
diff --git a/tests/F_reflection3264_reduce_extra32/stderr.txt.expect b/tests/F_reflection3264_reduce_extra32/stderr.txt.expect
new file mode 100644
index 0000000..c058403
--- /dev/null
+++ b/tests/F_reflection3264_reduce_extra32/stderr.txt.expect
@@ -0,0 +1,2 @@
+error: in file 'reflection3264_reduce_extra32.rs' reduction kernel 'cc' is only present for 32-bit targets
+error: in file 'reflection3264_reduce_extra32.rs' reduction kernel 'dd' is only present for 32-bit targets
diff --git a/tests/F_reflection3264_reduce_extra32/stdout.txt.expect b/tests/F_reflection3264_reduce_extra32/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_reduce_extra32/stdout.txt.expect
diff --git a/tests/F_reflection3264_reduce_extra64/reflection3264_reduce_extra64.rs b/tests/F_reflection3264_reduce_extra64/reflection3264_reduce_extra64.rs
new file mode 100644
index 0000000..c653d50
--- /dev/null
+++ b/tests/F_reflection3264_reduce_extra64/reflection3264_reduce_extra64.rs
@@ -0,0 +1,12 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+static void accum(int *a, int v) { }
+
+#pragma rs reduce(aa) accumulator(accum)
+#pragma rs reduce(bb) accumulator(accum)
+
+#ifdef __LP64__
+#pragma rs reduce(cc) accumulator(accum)
+#pragma rs reduce(dd) accumulator(accum)
+#endif
diff --git a/tests/F_reflection3264_reduce_extra64/stderr.txt.expect b/tests/F_reflection3264_reduce_extra64/stderr.txt.expect
new file mode 100644
index 0000000..864c196
--- /dev/null
+++ b/tests/F_reflection3264_reduce_extra64/stderr.txt.expect
@@ -0,0 +1,2 @@
+reflection3264_reduce_extra64.rs:10:12: error: reduction kernel 'cc' is only present for 64-bit targets
+reflection3264_reduce_extra64.rs:11:12: error: reduction kernel 'dd' is only present for 64-bit targets
diff --git a/tests/F_reflection3264_reduce_extra64/stdout.txt.expect b/tests/F_reflection3264_reduce_extra64/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_reduce_extra64/stdout.txt.expect
diff --git a/tests/F_reflection3264_reduce_mismatch/reflection3264_reduce_mismatch.rs b/tests/F_reflection3264_reduce_mismatch/reflection3264_reduce_mismatch.rs
new file mode 100644
index 0000000..10b3d85
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch/reflection3264_reduce_mismatch.rs
@@ -0,0 +1,71 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+struct S { int f; } ss;
+
+// accumulator types need not match; function names need not match
+#ifdef __LP64__
+#pragma rs reduce(aa) accumulator(aaAccum) combiner(aaCombAlpha) outconverter(aaOut)
+#else
+#pragma rs reduce(aa) accumulator(aaAccum) combiner(aaCombBeta) outconverter(aaOut)
+#endif
+static void aaAccum(size_t *a, int v) { }
+static void
+#ifdef __LP64__
+aaCombAlpha
+#else
+aaCombBeta
+#endif
+(size_t *a, const size_t *other) { }
+static void aaOut(int *out, const size_t *a) { }
+
+// which functions are present need not match; special arguments need not match
+#ifdef __LP64__
+#pragma rs reduce(bb) accumulator(bbAccum) combiner(bbComb) outconverter(bbOut)
+static void bbOut(int *out, const int *accum) { }
+#else
+#pragma rs reduce(bb) accumulator(bbAccum) combiner(bbComb)
+#endif
+static void bbAccum(int *a, int v,
+#ifdef __LP64__
+                    int x,
+#endif
+                    int y) { }
+static void bbComb(int *a, const int *b) { }
+
+// result type must match; ordinary argument types must match
+#pragma rs reduce(cc) accumulator(ccAccum) combiner(ccComb) outconverter(ccOut)
+static void ccAccum(int *accum, char i, size_t j, short k, size_t l) { }
+static void ccComb(int *accum, const int *other) { }
+static void ccOut(size_t *out, const int *accum) { }
+
+// accumulators must have same number of inputs
+#pragma rs reduce(dd) accumulator(ddAccum) combiner(ddComb)
+#ifdef __LP64__
+static void ddAccum(int *accum, char c) { }
+#else
+static void ddAccum(int *accum, short a, float b) { }
+#endif
+static void ddComb(int *accum, const int *other) { }
+
+// here, 32-bit kernel, 64-bit kernel, or both are not reflected in Java
+#pragma rs reduce(ee) accumulator(eeAccum) combiner(eeComb) outconverter(eeOut)
+#pragma rs reduce(ff) accumulator(ffAccum) combiner(ffComb) outconverter(ffOut)
+#pragma rs reduce(gg) accumulator(ggAccum) outconverter(ggOut)
+#ifdef __LP64__
+#define EETYPE struct S
+#define FFTYPE int
+#define FFINEXTRA int j
+#else
+#define EETYPE int
+#define FFTYPE struct S
+#define FFINEXTRA int j, int k
+#endif
+static void eeAccum(int *a, int v, size_t k) { }
+static void eeComb(int *a, const int *other) { }
+static void eeOut(EETYPE *out, const int *a) { }
+static void ffAccum(int *a, int v, FFINEXTRA) { }
+static void ffComb(int *a, const int *other) { }
+static void ffOut(FFTYPE *out, const int *a) { }
+static void ggAccum(size_t *a, size_t v) { }
+static void ggOut(struct S *out, const size_t *a) { }
diff --git a/tests/F_reflection3264_reduce_mismatch/stderr.txt.expect b/tests/F_reflection3264_reduce_mismatch/stderr.txt.expect
new file mode 100644
index 0000000..9c9a577
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch/stderr.txt.expect
@@ -0,0 +1,11 @@
+reflection3264_reduce_mismatch.rs:37:12: error: reduction kernel 'cc' has result type 'uint' for 32-bit targets but result type 'ulong' for 64-bit targets
+reflection3264_reduce_mismatch.rs:37:12: error: 2nd input of reduction kernel 'cc' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_reduce_mismatch.rs:37:12: error: 4th input of reduction kernel 'cc' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_reduce_mismatch.rs:43:12: error: reduction kernel 'dd' has 2 inputs for 32-bit targets but 1 input for 64-bit targets
+reflection3264_reduce_mismatch.rs:52:12: error: reduction kernel 'ee' is reflected in Java only for 32-bit targets
+reflection3264_reduce_mismatch.rs:52:12: error: reduction kernel 'ee' has result type 'int' for 32-bit targets but result type 'struct S' for 64-bit targets
+reflection3264_reduce_mismatch.rs:52:12: error: 2nd input of reduction kernel 'ee' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_reduce_mismatch.rs:53:12: error: reduction kernel 'ff' is reflected in Java only for 64-bit targets
+reflection3264_reduce_mismatch.rs:53:12: error: reduction kernel 'ff' has result type 'struct S' for 32-bit targets but result type 'int' for 64-bit targets
+reflection3264_reduce_mismatch.rs:53:12: error: reduction kernel 'ff' has 3 inputs for 32-bit targets but 2 inputs for 64-bit targets
+reflection3264_reduce_mismatch.rs:54:12: error: 1st input of reduction kernel 'gg' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
diff --git a/tests/F_reflection3264_reduce_mismatch/stdout.txt.expect b/tests/F_reflection3264_reduce_mismatch/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch/stdout.txt.expect
diff --git a/tests/F_reflection3264_reduce_mismatch_name_exp/reflection3264_reduce_mismatch_name_exp.rs b/tests/F_reflection3264_reduce_mismatch_name_exp/reflection3264_reduce_mismatch_name_exp.rs
new file mode 100644
index 0000000..7548cfe
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch_name_exp/reflection3264_reduce_mismatch_name_exp.rs
@@ -0,0 +1,15 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+static void accumBad(size_t *a, size_t v) { }
+
+#ifdef __LP64__
+#pragma rs reduce(a64) accumulator(accumBad)
+#else
+#pragma rs reduce(a32) accumulator(accumBad)
+#endif
+
+// the errors after this point should go unreported, because of the
+// name mismatch above (a32 versus a64)
+
+#pragma rs reduce(b) accumulator(accumBad)
diff --git a/tests/F_reflection3264_reduce_mismatch_name_exp/stderr.txt.expect b/tests/F_reflection3264_reduce_mismatch_name_exp/stderr.txt.expect
new file mode 100644
index 0000000..c5527b1
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch_name_exp/stderr.txt.expect
@@ -0,0 +1 @@
+reflection3264_reduce_mismatch_name_exp.rs:7:12: error: 1st reduction kernel is 'a32' for 32-bit targets but 'a64' for 64-bit targets
diff --git a/tests/F_reflection3264_reduce_mismatch_name_exp/stdout.txt.expect b/tests/F_reflection3264_reduce_mismatch_name_exp/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch_name_exp/stdout.txt.expect
diff --git a/tests/F_reflection3264_reduce_mismatch_name_noexp/reflection3264_reduce_mismatch_name_noexp.rs b/tests/F_reflection3264_reduce_mismatch_name_noexp/reflection3264_reduce_mismatch_name_noexp.rs
new file mode 100644
index 0000000..496ff01
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch_name_noexp/reflection3264_reduce_mismatch_name_noexp.rs
@@ -0,0 +1,18 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+struct S { int f; };
+
+static void accumGood(struct S *a, struct S v) { }
+static void accumBad(size_t *a, size_t v) { }
+
+#ifdef __LP64__
+#pragma rs reduce(a64) accumulator(accumGood)
+#else
+#pragma rs reduce(a32) accumulator(accumGood)
+#endif
+
+// the errors after this point should go unreported, because of the
+// name mismatch above (a32 versus a64)
+
+#pragma rs reduce(b) accumulator(accumBad)
diff --git a/tests/F_reflection3264_reduce_mismatch_name_noexp/stderr.txt.expect b/tests/F_reflection3264_reduce_mismatch_name_noexp/stderr.txt.expect
new file mode 100644
index 0000000..940684f
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch_name_noexp/stderr.txt.expect
@@ -0,0 +1 @@
+reflection3264_reduce_mismatch_name_noexp.rs:10:12: error: 1st reduction kernel is 'a32' for 32-bit targets but 'a64' for 64-bit targets
diff --git a/tests/F_reflection3264_reduce_mismatch_name_noexp/stdout.txt.expect b/tests/F_reflection3264_reduce_mismatch_name_noexp/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_reduce_mismatch_name_noexp/stdout.txt.expect
diff --git a/tests/F_reflection3264_struct_mismatch/reflection3264_struct_mismatch.rs b/tests/F_reflection3264_struct_mismatch/reflection3264_struct_mismatch.rs
new file mode 100644
index 0000000..5858add
--- /dev/null
+++ b/tests/F_reflection3264_struct_mismatch/reflection3264_struct_mismatch.rs
@@ -0,0 +1,81 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+struct t { int f; };
+
+struct q { int f; };
+
+struct b { int f; };
+
+struct j { int f; };
+
+struct f { int f; };
+
+struct o { int f; };
+
+// disagreement as to which struct types are exported
+
+#ifdef __LP64__
+struct t aa;
+struct q bb;
+struct b cc;
+int dd;
+int ee;
+int ff;
+#else
+int aa;
+int bb;
+int cc;
+struct j dd;
+struct f ee;
+struct o ff;
+#endif
+
+// disagreeement as to how many fields in an exported struct
+
+#ifdef __LP64__
+struct FieldCount {
+  int a;
+  float b;
+};
+#else
+struct FieldCount {
+  double c;
+};
+#endif
+
+struct FieldCount gg;
+
+// disagreement as to field name in an exported struct
+// (after first mismatched name, we do not report
+// any other errors for the struct)
+
+#ifdef __LP64__
+struct FieldName {
+  int a;
+  int b;
+  int c;
+  int d;
+};
+#else
+struct FieldName {
+  int a;
+  int e;
+  float c;
+  int f;
+};
+#endif
+
+struct FieldName hh;
+
+// disagreement as to field types in an exported struct
+
+struct FieldType {
+  int a;
+  size_t b;
+  rs_allocation c;
+  float d;
+  char e[sizeof(size_t)];
+};
+
+struct FieldType ii;
diff --git a/tests/F_reflection3264_struct_mismatch/stderr.txt.expect b/tests/F_reflection3264_struct_mismatch/stderr.txt.expect
new file mode 100644
index 0000000..4c70112
--- /dev/null
+++ b/tests/F_reflection3264_struct_mismatch/stderr.txt.expect
@@ -0,0 +1,16 @@
+reflection3264_struct_mismatch.rs:19:10: error: global variable 'aa' has type 'int' for 32-bit targets but type 'struct t' for 64-bit targets
+reflection3264_struct_mismatch.rs:20:10: error: global variable 'bb' has type 'int' for 32-bit targets but type 'struct q' for 64-bit targets
+reflection3264_struct_mismatch.rs:21:10: error: global variable 'cc' has type 'int' for 32-bit targets but type 'struct b' for 64-bit targets
+reflection3264_struct_mismatch.rs:22:5: error: global variable 'dd' has type 'struct j' for 32-bit targets but type 'int' for 64-bit targets
+reflection3264_struct_mismatch.rs:23:5: error: global variable 'ee' has type 'struct f' for 32-bit targets but type 'int' for 64-bit targets
+reflection3264_struct_mismatch.rs:24:5: error: global variable 'ff' has type 'struct o' for 32-bit targets but type 'int' for 64-bit targets
+reflection3264_struct_mismatch.rs:6:8: error: structure 'q' is exported only for 64-bit targets
+reflection3264_struct_mismatch.rs:8:8: error: structure 'b' is exported only for 64-bit targets
+reflection3264_struct_mismatch.rs:4:8: error: structure 't' is exported only for 64-bit targets
+reflection3264_struct_mismatch.rs:54:8: error: 2nd field of exported structure 'FieldName' is 'e' for 32-bit targets but 'b' for 64-bit targets
+reflection3264_struct_mismatch.rs:73:8: error: field 'b' of exported structure 'FieldType' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_struct_mismatch.rs:73:8: error: field 'e' of exported structure 'FieldType' has type 'char[4]' for 32-bit targets but type 'char[8]' for 64-bit targets
+reflection3264_struct_mismatch.rs:37:8: error: exported structure 'FieldCount' has 1 field for 32-bit targets but 2 fields for 64-bit targets
+error: in file 'reflection3264_struct_mismatch.rs' structure 'f' is exported only for 32-bit targets
+error: in file 'reflection3264_struct_mismatch.rs' structure 'j' is exported only for 32-bit targets
+error: in file 'reflection3264_struct_mismatch.rs' structure 'o' is exported only for 32-bit targets
diff --git a/tests/F_reflection3264_struct_mismatch/stdout.txt.expect b/tests/F_reflection3264_struct_mismatch/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_struct_mismatch/stdout.txt.expect
diff --git a/tests/F_reflection3264_variable_extra32/reflection3264_variable_extra32.rs b/tests/F_reflection3264_variable_extra32/reflection3264_variable_extra32.rs
new file mode 100644
index 0000000..a26178f
--- /dev/null
+++ b/tests/F_reflection3264_variable_extra32/reflection3264_variable_extra32.rs
@@ -0,0 +1,16 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+int a;
+
+size_t b;
+
+double c;
+
+#ifndef __LP64__
+
+char d;
+
+short e = 1;
+
+#endif
diff --git a/tests/F_reflection3264_variable_extra32/stderr.txt.expect b/tests/F_reflection3264_variable_extra32/stderr.txt.expect
new file mode 100644
index 0000000..ec0b242
--- /dev/null
+++ b/tests/F_reflection3264_variable_extra32/stderr.txt.expect
@@ -0,0 +1,3 @@
+reflection3264_variable_extra32.rs:6:8: error: global variable 'b' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+error: in file 'reflection3264_variable_extra32.rs' global variable 'd' is only present for 32-bit targets
+error: in file 'reflection3264_variable_extra32.rs' global variable 'e' is only present for 32-bit targets
diff --git a/tests/F_reflection3264_variable_extra32/stdout.txt.expect b/tests/F_reflection3264_variable_extra32/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_variable_extra32/stdout.txt.expect
diff --git a/tests/F_reflection3264_variable_extra64/reflection3264_variable_extra64.rs b/tests/F_reflection3264_variable_extra64/reflection3264_variable_extra64.rs
new file mode 100644
index 0000000..4b9e946
--- /dev/null
+++ b/tests/F_reflection3264_variable_extra64/reflection3264_variable_extra64.rs
@@ -0,0 +1,16 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+int a;
+
+size_t b;
+
+double c;
+
+#ifdef __LP64__
+
+char d;
+
+short e = 1;
+
+#endif
diff --git a/tests/F_reflection3264_variable_extra64/stderr.txt.expect b/tests/F_reflection3264_variable_extra64/stderr.txt.expect
new file mode 100644
index 0000000..6888f90
--- /dev/null
+++ b/tests/F_reflection3264_variable_extra64/stderr.txt.expect
@@ -0,0 +1,3 @@
+reflection3264_variable_extra64.rs:6:8: error: global variable 'b' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_variable_extra64.rs:12:6: error: global variable 'd' is only present for 64-bit targets
+reflection3264_variable_extra64.rs:14:7: error: global variable 'e' is only present for 64-bit targets
diff --git a/tests/F_reflection3264_variable_extra64/stdout.txt.expect b/tests/F_reflection3264_variable_extra64/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_variable_extra64/stdout.txt.expect
diff --git a/tests/F_reflection3264_variable_mismatch/reflection3264_variable_mismatch.rs b/tests/F_reflection3264_variable_mismatch/reflection3264_variable_mismatch.rs
new file mode 100644
index 0000000..b203751
--- /dev/null
+++ b/tests/F_reflection3264_variable_mismatch/reflection3264_variable_mismatch.rs
@@ -0,0 +1,66 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+struct Foo { int f; } foo;
+struct Bar { int f; } bar;
+
+size_t a;
+
+int b[sizeof(void*)];
+
+rs_allocation c;
+
+#ifdef __LP64__
+const
+#endif
+int d = 0;
+
+#ifndef __LP64__
+const
+#endif
+int e = 0;
+
+#ifdef __LP64__
+struct Foo f;
+#else
+struct Bar f;
+#endif
+
+size_t g[10];
+
+#ifdef __LP64__
+int h64;
+#else
+int h32;
+#endif
+
+// the errors after this point should go unreported, because of the
+// variable name mismatch above (h32 versus h64)
+
+size_t z;
+
+int y[sizeof(void*)];
+
+rs_allocation x;
+
+#ifdef __LP64__
+const
+#endif
+int w = 0;
+
+#ifndef __LP64__
+const
+#endif
+int v = 0;
+
+#ifdef __LP64__
+struct Foo u;
+#else
+struct Bar u;
+#endif
+
+#ifdef __LP64__
+int t64;
+#else
+int t32;
+#endif
diff --git a/tests/F_reflection3264_variable_mismatch/stderr.txt.expect b/tests/F_reflection3264_variable_mismatch/stderr.txt.expect
new file mode 100644
index 0000000..bc28bc5
--- /dev/null
+++ b/tests/F_reflection3264_variable_mismatch/stderr.txt.expect
@@ -0,0 +1,7 @@
+reflection3264_variable_mismatch.rs:7:8: error: global variable 'a' has type 'uint' for 32-bit targets but type 'ulong' for 64-bit targets
+reflection3264_variable_mismatch.rs:9:5: error: global variable 'b' has type 'int[4]' for 32-bit targets but type 'int[8]' for 64-bit targets
+reflection3264_variable_mismatch.rs:16:5: error: global variable 'd' has inconsistent 'const' qualification between 32-bit targets and 64-bit targets
+reflection3264_variable_mismatch.rs:21:5: error: global variable 'e' has inconsistent 'const' qualification between 32-bit targets and 64-bit targets
+reflection3264_variable_mismatch.rs:24:12: error: global variable 'f' has type 'struct Bar' for 32-bit targets but type 'struct Foo' for 64-bit targets
+reflection3264_variable_mismatch.rs:29:8: error: global variable 'g' has type 'uint[10]' for 32-bit targets but type 'ulong[10]' for 64-bit targets
+reflection3264_variable_mismatch.rs:32:5: error: 10th global variable is 'h32' for 32-bit targets but 'h64' for 64-bit targets
diff --git a/tests/F_reflection3264_variable_mismatch/stdout.txt.expect b/tests/F_reflection3264_variable_mismatch/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_variable_mismatch/stdout.txt.expect
diff --git a/tests/F_reflection3264_variable_mismatch_init/reflection3264_variable_mismatch_init.rs b/tests/F_reflection3264_variable_mismatch_init/reflection3264_variable_mismatch_init.rs
new file mode 100644
index 0000000..2aa142c
--- /dev/null
+++ b/tests/F_reflection3264_variable_mismatch_init/reflection3264_variable_mismatch_init.rs
@@ -0,0 +1,76 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+float a = 1.23f;
+
+float b = 4.56f + sizeof(void*);
+
+double c = 7.89;
+
+double d = 98.7 * sizeof(void*);
+
+char e = 'e';
+
+char f = sizeof(void*);
+
+int2 g = { 1, 2 };
+
+int2 h = { 3, sizeof(void*) };
+
+float4 i = { 1.2f, 3.4f, 5.6f, 7.8f };
+
+float4 j = { 1.2f, 3.4f,  // vector component initialized differently
+#ifdef __LP64__
+             5.6f,
+#else
+             6.5f,
+#endif
+             7.8f };
+
+int k
+#ifdef __LP64__
+= 0  // we get an error even though explicit zero initialization is redundant
+#endif
+    ;
+
+int l[10] = { 1, 2, 3 };
+
+int m[10] = { 1, 2, 3
+#ifdef __LP64__
+              , 4  // array with a different number of initializers
+#endif
+              , 5
+};
+
+int2 n = { 1
+#ifdef __LP64__
+           , 2  // vector with different number of initializers
+#endif
+};
+
+float4 jj = { 1.2f, 3.4f,  // vector component initialized differently
+#ifndef __LP64__
+             5.6f,
+#else
+             6.5f,
+#endif
+             7.8f };
+
+int kk
+#ifndef __LP64__
+= 0  // we get an error even though explicit zero initialization is redundant
+#endif
+    ;
+
+int mm[10] = { 1, 2, 3
+#ifndef __LP64__
+              , 4  // array with a different number of initializers
+#endif
+              , 5
+};
+
+int2 nn = { 1
+#ifndef __LP64__
+            , 2  // vector with a different number of initializers
+#endif
+};
diff --git a/tests/F_reflection3264_variable_mismatch_init/stderr.txt.expect b/tests/F_reflection3264_variable_mismatch_init/stderr.txt.expect
new file mode 100644
index 0000000..c342a62
--- /dev/null
+++ b/tests/F_reflection3264_variable_mismatch_init/stderr.txt.expect
@@ -0,0 +1,12 @@
+reflection3264_variable_mismatch_init.rs:6:7: error: global variable 'b' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:10:8: error: global variable 'd' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:14:6: error: global variable 'f' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:18:6: error: global variable 'h' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:22:8: error: global variable 'j' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:30:5: error: global variable 'k' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:38:5: error: global variable 'm' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:45:6: error: global variable 'n' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:51:8: error: global variable 'jj' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:59:5: error: global variable 'kk' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:65:5: error: global variable 'mm' is initialized differently for 32-bit targets than for 64-bit targets
+reflection3264_variable_mismatch_init.rs:72:6: error: global variable 'nn' is initialized differently for 32-bit targets than for 64-bit targets
diff --git a/tests/F_reflection3264_variable_mismatch_init/stdout.txt.expect b/tests/F_reflection3264_variable_mismatch_init/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_reflection3264_variable_mismatch_init/stdout.txt.expect
diff --git a/tests/P_reduce_general_accumulator/ScriptC_reduce_general_accumulator.java.expect b/tests/P_reduce_general_accumulator/ScriptC_reduce_general_accumulator.java.expect
index c39ce7c..e742b69 100644
--- a/tests/P_reduce_general_accumulator/ScriptC_reduce_general_accumulator.java.expect
+++ b/tests/P_reduce_general_accumulator/ScriptC_reduce_general_accumulator.java.expect
@@ -21,6 +21,9 @@
 
 package accumulator;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import accumulator.reduce_general_accumulatorBitCode;
 
diff --git a/tests/P_reduce_general_duplicate_array/ScriptC_reduce_general_duplicate_array.java.expect b/tests/P_reduce_general_duplicate_array/ScriptC_reduce_general_duplicate_array.java.expect
index c4d88ab..f582ddc 100644
--- a/tests/P_reduce_general_duplicate_array/ScriptC_reduce_general_duplicate_array.java.expect
+++ b/tests/P_reduce_general_duplicate_array/ScriptC_reduce_general_duplicate_array.java.expect
@@ -21,6 +21,9 @@
 
 package array;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import array.reduce_general_duplicate_arrayBitCode;
 
diff --git a/tests/P_reduce_general_examples/ScriptC_reduce_general_examples.java.expect b/tests/P_reduce_general_examples/ScriptC_reduce_general_examples.java.expect
index 74b295e..129b785 100644
--- a/tests/P_reduce_general_examples/ScriptC_reduce_general_examples.java.expect
+++ b/tests/P_reduce_general_examples/ScriptC_reduce_general_examples.java.expect
@@ -21,6 +21,9 @@
 
 package examples;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import examples.reduce_general_examplesBitCode;
 
diff --git a/tests/P_reduce_general_examples_backward/ScriptC_reduce_general_examples_backward.java.expect b/tests/P_reduce_general_examples_backward/ScriptC_reduce_general_examples_backward.java.expect
index 50437f3..49c5ede 100644
--- a/tests/P_reduce_general_examples_backward/ScriptC_reduce_general_examples_backward.java.expect
+++ b/tests/P_reduce_general_examples_backward/ScriptC_reduce_general_examples_backward.java.expect
@@ -21,6 +21,9 @@
 
 package examples;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import examples.reduce_general_examples_backwardBitCode;
 
diff --git a/tests/P_reduce_general_examples_explicit/ScriptC_reduce_general_examples_explicit.java.expect b/tests/P_reduce_general_examples_explicit/ScriptC_reduce_general_examples_explicit.java.expect
index 013838e..adcba0c 100644
--- a/tests/P_reduce_general_examples_explicit/ScriptC_reduce_general_examples_explicit.java.expect
+++ b/tests/P_reduce_general_examples_explicit/ScriptC_reduce_general_examples_explicit.java.expect
@@ -21,6 +21,9 @@
 
 package examples;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import examples.reduce_general_examples_explicitBitCode;
 
diff --git a/tests/P_reduce_general_examples_halter/ScriptC_reduce_general_examples_halter.java.expect b/tests/P_reduce_general_examples_halter/ScriptC_reduce_general_examples_halter.java.expect
index 0b2f3da..5a8966a 100644
--- a/tests/P_reduce_general_examples_halter/ScriptC_reduce_general_examples_halter.java.expect
+++ b/tests/P_reduce_general_examples_halter/ScriptC_reduce_general_examples_halter.java.expect
@@ -21,6 +21,9 @@
 
 package examples;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import examples.reduce_general_examples_halterBitCode;
 
diff --git a/tests/P_reduce_general_input/ScriptC_reduce_general_input.java.expect b/tests/P_reduce_general_input/ScriptC_reduce_general_input.java.expect
index bc151f1..56d10b2 100644
--- a/tests/P_reduce_general_input/ScriptC_reduce_general_input.java.expect
+++ b/tests/P_reduce_general_input/ScriptC_reduce_general_input.java.expect
@@ -21,6 +21,9 @@
 
 package input;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import input.reduce_general_inputBitCode;
 
diff --git a/tests/P_reduce_general_input/ScriptField_MyStruct.java.expect b/tests/P_reduce_general_input/ScriptField_MyStruct.java.expect
index ec10677..8f3859b 100644
--- a/tests/P_reduce_general_input/ScriptField_MyStruct.java.expect
+++ b/tests/P_reduce_general_input/ScriptField_MyStruct.java.expect
@@ -21,6 +21,9 @@
 
 package input;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import input.reduce_general_inputBitCode;
 
diff --git a/tests/P_reduce_general_inputs/ScriptC_reduce_general_inputs.java.expect b/tests/P_reduce_general_inputs/ScriptC_reduce_general_inputs.java.expect
index 05b80ad..198f438 100644
--- a/tests/P_reduce_general_inputs/ScriptC_reduce_general_inputs.java.expect
+++ b/tests/P_reduce_general_inputs/ScriptC_reduce_general_inputs.java.expect
@@ -21,6 +21,9 @@
 
 package inputs;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import inputs.reduce_general_inputsBitCode;
 
diff --git a/tests/P_reduce_general_inputs/ScriptField_MyStruct.java.expect b/tests/P_reduce_general_inputs/ScriptField_MyStruct.java.expect
index 182f920..95c1c50 100644
--- a/tests/P_reduce_general_inputs/ScriptField_MyStruct.java.expect
+++ b/tests/P_reduce_general_inputs/ScriptField_MyStruct.java.expect
@@ -21,6 +21,9 @@
 
 package inputs;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import inputs.reduce_general_inputsBitCode;
 
diff --git a/tests/P_reduce_general_result/ScriptC_reduce_general_result.java.expect b/tests/P_reduce_general_result/ScriptC_reduce_general_result.java.expect
index c1bd6d5..bbd40ba 100644
--- a/tests/P_reduce_general_result/ScriptC_reduce_general_result.java.expect
+++ b/tests/P_reduce_general_result/ScriptC_reduce_general_result.java.expect
@@ -21,6 +21,9 @@
 
 package result;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import result.reduce_general_resultBitCode;
 
diff --git a/tests/P_reduce_general_result/ScriptField_MyStruct.java.expect b/tests/P_reduce_general_result/ScriptField_MyStruct.java.expect
index 9943781..834c865 100644
--- a/tests/P_reduce_general_result/ScriptField_MyStruct.java.expect
+++ b/tests/P_reduce_general_result/ScriptField_MyStruct.java.expect
@@ -21,6 +21,9 @@
 
 package result;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import result.reduce_general_resultBitCode;
 
diff --git a/tests/P_reduce_general_struct/ScriptC_reduce_general_struct.java.expect b/tests/P_reduce_general_struct/ScriptC_reduce_general_struct.java.expect
index 983ea39..d2d15da 100644
--- a/tests/P_reduce_general_struct/ScriptC_reduce_general_struct.java.expect
+++ b/tests/P_reduce_general_struct/ScriptC_reduce_general_struct.java.expect
@@ -21,6 +21,9 @@
 
 package struct;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import struct.reduce_general_structBitCode;
 
diff --git a/tests/P_reflection3264_divergent/ScriptC_reflection3264_divergent.java.expect b/tests/P_reflection3264_divergent/ScriptC_reflection3264_divergent.java.expect
new file mode 100644
index 0000000..9f1eefe
--- /dev/null
+++ b/tests/P_reflection3264_divergent/ScriptC_reflection3264_divergent.java.expect
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptC_reflection3264_divergent extends ScriptC {
+    private static final String __rs_resource_name = "reflection3264_divergent";
+    // Constructor
+    public  ScriptC_reflection3264_divergent(RenderScript rs) {
+        super(rs,
+              __rs_resource_name,
+              reflection3264_divergentBitCode.getBitCode32(),
+              reflection3264_divergentBitCode.getBitCode64());
+        __I32 = Element.I32(rs);
+        __@@INVALID@@ = Element.@@INVALID@@(rs);
+        __ALLOCATION = Element.ALLOCATION(rs);
+        __ScriptField_NonDivergent = ScriptField_NonDivergent.createElement(rs);
+        __ScriptField_Divergent = ScriptField_Divergent.createElement(rs);
+        __ScriptField_DivergentNest = ScriptField_DivergentNest.createElement(rs);
+    }
+
+    private Element __@@INVALID@@;
+    private Element __ALLOCATION;
+    private Element __I32;
+    private Element __ScriptField_Divergent;
+    private Element __ScriptField_DivergentNest;
+    private Element __ScriptField_NonDivergent;
+    private FieldPacker __rs_fp_@@INVALID@@;
+    private FieldPacker __rs_fp_ALLOCATION;
+    private FieldPacker __rs_fp_I32;
+    private FieldPacker __rs_fp_ScriptField_Divergent;
+    private FieldPacker __rs_fp_ScriptField_DivergentNest;
+    private FieldPacker __rs_fp_ScriptField_NonDivergent;
+    private final static int mExportVarIdx_intVar = 0;
+    private int mExportVar_intVar;
+    public synchronized void set_intVar(int v) {
+        setVar(mExportVarIdx_intVar, v);
+        mExportVar_intVar = v;
+    }
+
+    public int get_intVar() {
+        return mExportVar_intVar;
+    }
+
+    public Script.FieldID getFieldID_intVar() {
+        return createFieldID(mExportVarIdx_intVar, null);
+    }
+
+    private final static int mExportVarIdx_intArray = 1;
+    private int[] mExportVar_intArray;
+    public synchronized void set_intArray(int[] v) {
+        mExportVar_intArray = v;
+        FieldPacker fp = new FieldPacker(40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_intArray, fp, __I32, __dimArr);
+    }
+
+    public int[] get_intArray() {
+        return mExportVar_intArray;
+    }
+
+    public Script.FieldID getFieldID_intArray() {
+        return createFieldID(mExportVarIdx_intArray, null);
+    }
+
+    private final static int mExportVarIdx_matVar = 2;
+    private Matrix2f mExportVar_matVar;
+    public synchronized void set_matVar(Matrix2f v) {
+        mExportVar_matVar = v;
+        FieldPacker fp = new FieldPacker(16);
+        fp.addMatrix(v);
+        setVar(mExportVarIdx_matVar, fp);
+    }
+
+    public Matrix2f get_matVar() {
+        return mExportVar_matVar;
+    }
+
+    public Script.FieldID getFieldID_matVar() {
+        return createFieldID(mExportVarIdx_matVar, null);
+    }
+
+    private final static int mExportVarIdx_matArray = 3;
+    private Matrix2f[] mExportVar_matArray;
+    public synchronized void set_matArray(Matrix2f[] v) {
+        mExportVar_matArray = v;
+        FieldPacker fp = new FieldPacker(160);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addMatrix(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_matArray, fp, __@@INVALID@@, __dimArr);
+    }
+
+    public Matrix2f[] get_matArray() {
+        return mExportVar_matArray;
+    }
+
+    public Script.FieldID getFieldID_matArray() {
+        return createFieldID(mExportVarIdx_matArray, null);
+    }
+
+    private final static int mExportVarIdx_allocVar = 4;
+    private Allocation mExportVar_allocVar;
+    public synchronized void set_allocVar(Allocation v) {
+        setVar(mExportVarIdx_allocVar, v);
+        mExportVar_allocVar = v;
+    }
+
+    public Allocation get_allocVar() {
+        return mExportVar_allocVar;
+    }
+
+    public Script.FieldID getFieldID_allocVar() {
+        return createFieldID(mExportVarIdx_allocVar, null);
+    }
+
+    private final static int mExportVarIdx_allocArray = 5;
+    private Allocation[] mExportVar_allocArray;
+    public synchronized void set_allocArray(Allocation[] v) {
+        mExportVar_allocArray = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 320 : 40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addObj(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_allocArray, fp, __ALLOCATION, __dimArr);
+    }
+
+    public Allocation[] get_allocArray() {
+        return mExportVar_allocArray;
+    }
+
+    public Script.FieldID getFieldID_allocArray() {
+        return createFieldID(mExportVarIdx_allocArray, null);
+    }
+
+    private final static int mExportVarIdx_ndVar = 6;
+    private ScriptField_NonDivergent.Item mExportVar_ndVar;
+    public synchronized void set_ndVar(ScriptField_NonDivergent.Item v) {
+        mExportVar_ndVar = v;
+        FieldPacker fp = new FieldPacker(8);
+        fp.addI32(v.i);
+        fp.addI32(v.j);
+        int []__dimArr = new int[1];
+        __dimArr[0] = 1;
+        setVar(mExportVarIdx_ndVar, fp, __ScriptField_NonDivergent, __dimArr);
+    }
+
+    public ScriptField_NonDivergent.Item get_ndVar() {
+        return mExportVar_ndVar;
+    }
+
+    public Script.FieldID getFieldID_ndVar() {
+        return createFieldID(mExportVarIdx_ndVar, null);
+    }
+
+    private final static int mExportVarIdx_ndArray = 7;
+    private ScriptField_NonDivergent.Item[] mExportVar_ndArray;
+    public synchronized void set_ndArray(ScriptField_NonDivergent.Item[] v) {
+        mExportVar_ndArray = v;
+        FieldPacker fp = new FieldPacker(80);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1].i);
+            fp.addI32(v[ct1].j);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_ndArray, fp, __ScriptField_NonDivergent, __dimArr);
+    }
+
+    public ScriptField_NonDivergent.Item[] get_ndArray() {
+        return mExportVar_ndArray;
+    }
+
+    public Script.FieldID getFieldID_ndArray() {
+        return createFieldID(mExportVarIdx_ndArray, null);
+    }
+
+    private final static int mExportVarIdx_dVar = 8;
+    private ScriptField_Divergent.Item mExportVar_dVar;
+    public synchronized void set_dVar(ScriptField_Divergent.Item v) {
+        mExportVar_dVar = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 48 : 12);
+        fp.addI32(v.i);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addObj(v.a);
+        fp.addI32(v.j);
+        fp.skip(sIs64Bit ? 4 : 0);
+        int []__dimArr = new int[1];
+        __dimArr[0] = 1;
+        setVar(mExportVarIdx_dVar, fp, __ScriptField_Divergent, __dimArr);
+    }
+
+    public ScriptField_Divergent.Item get_dVar() {
+        return mExportVar_dVar;
+    }
+
+    public Script.FieldID getFieldID_dVar() {
+        return createFieldID(mExportVarIdx_dVar, null);
+    }
+
+    private final static int mExportVarIdx_dArray = 9;
+    private ScriptField_Divergent.Item[] mExportVar_dArray;
+    public synchronized void set_dArray(ScriptField_Divergent.Item[] v) {
+        mExportVar_dArray = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 400 : 120);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1].i);
+            fp.skip(sIs64Bit ? 4 : 0);
+            fp.addObj(v[ct1].a);
+            fp.addI32(v[ct1].j);
+            fp.skip(sIs64Bit ? 4 : 0);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_dArray, fp, __ScriptField_Divergent, __dimArr);
+    }
+
+    public ScriptField_Divergent.Item[] get_dArray() {
+        return mExportVar_dArray;
+    }
+
+    public Script.FieldID getFieldID_dArray() {
+        return createFieldID(mExportVarIdx_dArray, null);
+    }
+
+    private final static int mExportVarIdx_dnVar = 10;
+    private ScriptField_DivergentNest.Item mExportVar_dnVar;
+    public synchronized void set_dnVar(ScriptField_DivergentNest.Item v) {
+        mExportVar_dnVar = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 64 : 20);
+        fp.addI32(v.x);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addI32(v.d.i);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addObj(v.d.a);
+        fp.addI32(v.d.j);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addI32(v.y);
+        fp.skip(sIs64Bit ? 4 : 0);
+        int []__dimArr = new int[1];
+        __dimArr[0] = 1;
+        setVar(mExportVarIdx_dnVar, fp, __ScriptField_DivergentNest, __dimArr);
+    }
+
+    public ScriptField_DivergentNest.Item get_dnVar() {
+        return mExportVar_dnVar;
+    }
+
+    public Script.FieldID getFieldID_dnVar() {
+        return createFieldID(mExportVarIdx_dnVar, null);
+    }
+
+    private final static int mExportVarIdx_dnArray = 11;
+    private ScriptField_DivergentNest.Item[] mExportVar_dnArray;
+    public synchronized void set_dnArray(ScriptField_DivergentNest.Item[] v) {
+        mExportVar_dnArray = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 480 : 200);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1].x);
+            fp.skip(sIs64Bit ? 4 : 0);
+            fp.addI32(v[ct1].d.i);
+            fp.skip(sIs64Bit ? 4 : 0);
+            fp.addObj(v[ct1].d.a);
+            fp.addI32(v[ct1].d.j);
+            fp.skip(sIs64Bit ? 4 : 0);
+            fp.addI32(v[ct1].y);
+            fp.skip(sIs64Bit ? 4 : 0);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_dnArray, fp, __ScriptField_DivergentNest, __dimArr);
+    }
+
+    public ScriptField_DivergentNest.Item[] get_dnArray() {
+        return mExportVar_dnArray;
+    }
+
+    public Script.FieldID getFieldID_dnArray() {
+        return createFieldID(mExportVarIdx_dnArray, null);
+    }
+
+    //private final static int mExportForEachIdx_root = 0;
+    private final static int mExportForEachIdx_dnFe = 1;
+    public Script.KernelID getKernelID_dnFe() {
+        return createKernelID(mExportForEachIdx_dnFe, 7, null, null);
+    }
+
+    public void forEach_dnFe(Allocation ain, Allocation aout, ScriptField_DivergentNest.Item data) {
+        forEach_dnFe(ain, aout, data, null);
+    }
+
+    public void forEach_dnFe(Allocation ain, Allocation aout, ScriptField_DivergentNest.Item data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker dnFe_fp = new FieldPacker(sIs64Bit ? 64 : 20);
+        dnFe_fp.addI32(data.x);
+        dnFe_fp.skip(sIs64Bit ? 4 : 0);
+        dnFe_fp.addI32(data.d.i);
+        dnFe_fp.skip(sIs64Bit ? 4 : 0);
+        dnFe_fp.addObj(data.d.a);
+        dnFe_fp.addI32(data.d.j);
+        dnFe_fp.skip(sIs64Bit ? 4 : 0);
+        dnFe_fp.addI32(data.y);
+        dnFe_fp.skip(sIs64Bit ? 4 : 0);
+        forEach(mExportForEachIdx_dnFe, ain, aout, dnFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_dFe = 2;
+    public Script.KernelID getKernelID_dFe() {
+        return createKernelID(mExportForEachIdx_dFe, 7, null, null);
+    }
+
+    public void forEach_dFe(Allocation ain, Allocation aout, ScriptField_Divergent.Item data) {
+        forEach_dFe(ain, aout, data, null);
+    }
+
+    public void forEach_dFe(Allocation ain, Allocation aout, ScriptField_Divergent.Item data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker dFe_fp = new FieldPacker(sIs64Bit ? 48 : 12);
+        dFe_fp.addI32(data.i);
+        dFe_fp.skip(sIs64Bit ? 4 : 0);
+        dFe_fp.addObj(data.a);
+        dFe_fp.addI32(data.j);
+        dFe_fp.skip(sIs64Bit ? 4 : 0);
+        forEach(mExportForEachIdx_dFe, ain, aout, dFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_ndFe = 3;
+    public Script.KernelID getKernelID_ndFe() {
+        return createKernelID(mExportForEachIdx_ndFe, 7, null, null);
+    }
+
+    public void forEach_ndFe(Allocation ain, Allocation aout, ScriptField_NonDivergent.Item data) {
+        forEach_ndFe(ain, aout, data, null);
+    }
+
+    public void forEach_ndFe(Allocation ain, Allocation aout, ScriptField_NonDivergent.Item data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker ndFe_fp = new FieldPacker(8);
+        ndFe_fp.addI32(data.i);
+        ndFe_fp.addI32(data.j);
+        forEach(mExportForEachIdx_ndFe, ain, aout, ndFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_allocFe = 4;
+    public Script.KernelID getKernelID_allocFe() {
+        return createKernelID(mExportForEachIdx_allocFe, 7, null, null);
+    }
+
+    public void forEach_allocFe(Allocation ain, Allocation aout, Allocation data) {
+        forEach_allocFe(ain, aout, data, null);
+    }
+
+    public void forEach_allocFe(Allocation ain, Allocation aout, Allocation data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker allocFe_fp = new FieldPacker(sIs64Bit ? 32 : 4);
+        allocFe_fp.addObj(data);
+        forEach(mExportForEachIdx_allocFe, ain, aout, allocFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_matFe = 5;
+    public Script.KernelID getKernelID_matFe() {
+        return createKernelID(mExportForEachIdx_matFe, 7, null, null);
+    }
+
+    public void forEach_matFe(Allocation ain, Allocation aout, Matrix2f data) {
+        forEach_matFe(ain, aout, data, null);
+    }
+
+    public void forEach_matFe(Allocation ain, Allocation aout, Matrix2f data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker matFe_fp = new FieldPacker(16);
+        matFe_fp.addMatrix(data);
+        forEach(mExportForEachIdx_matFe, ain, aout, matFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_intFe = 6;
+    public Script.KernelID getKernelID_intFe() {
+        return createKernelID(mExportForEachIdx_intFe, 7, null, null);
+    }
+
+    public void forEach_intFe(Allocation ain, Allocation aout, int data) {
+        forEach_intFe(ain, aout, data, null);
+    }
+
+    public void forEach_intFe(Allocation ain, Allocation aout, int data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker intFe_fp = new FieldPacker(4);
+        intFe_fp.addI32(data);
+        forEach(mExportForEachIdx_intFe, ain, aout, intFe_fp, sc);
+    }
+
+    private final static int mExportFuncIdx_ndInv = 0;
+    public Script.InvokeID getInvokeID_ndInv() {
+        return createInvokeID(mExportFuncIdx_ndInv);
+    }
+
+    public void invoke_ndInv(int i, int j) {
+        FieldPacker ndInv_fp = new FieldPacker(8);
+        ndInv_fp.addI32(i);
+        ndInv_fp.addI32(j);
+        invoke(mExportFuncIdx_ndInv, ndInv_fp);
+    }
+
+    private final static int mExportFuncIdx_dInv = 1;
+    public Script.InvokeID getInvokeID_dInv() {
+        return createInvokeID(mExportFuncIdx_dInv);
+    }
+
+    public void invoke_dInv(int i, Allocation a, int j) {
+        FieldPacker dInv_fp = new FieldPacker(sIs64Bit ? 48 : 12);
+        dInv_fp.addI32(i);
+        dInv_fp.skip(sIs64Bit ? 4 : 0);
+        dInv_fp.addObj(a);
+        dInv_fp.addI32(j);
+        dInv_fp.skip(sIs64Bit ? 4 : 0);
+        invoke(mExportFuncIdx_dInv, dInv_fp);
+    }
+
+    private final static int mExportFuncIdx_dnInv = 2;
+    public Script.InvokeID getInvokeID_dnInv() {
+        return createInvokeID(mExportFuncIdx_dnInv);
+    }
+
+    public void invoke_dnInv(int x, ScriptField_Divergent.Item d, int y) {
+        FieldPacker dnInv_fp = new FieldPacker(sIs64Bit ? 64 : 20);
+        dnInv_fp.addI32(x);
+        dnInv_fp.skip(sIs64Bit ? 4 : 0);
+        dnInv_fp.addI32(d.i);
+        dnInv_fp.skip(sIs64Bit ? 4 : 0);
+        dnInv_fp.addObj(d.a);
+        dnInv_fp.addI32(d.j);
+        dnInv_fp.skip(sIs64Bit ? 4 : 0);
+        dnInv_fp.addI32(y);
+        dnInv_fp.skip(sIs64Bit ? 4 : 0);
+        invoke(mExportFuncIdx_dnInv, dnInv_fp);
+    }
+
+    private static boolean sIs64Bit;
+
+    static {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            sIs64Bit = Process.is64Bit();
+        }
+
+        else {
+            try {
+                Field f = RenderScript.class.getDeclaredField("sPointerSize");
+                f.setAccessible(true);
+                sIs64Bit = (f.getInt(null) == 8);
+            }
+
+            catch (Throwable e) {
+                sIs64Bit = false;
+            }
+
+        }
+
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent/ScriptField_Divergent.java.expect b/tests/P_reflection3264_divergent/ScriptField_Divergent.java.expect
new file mode 100644
index 0000000..1be4ac2
--- /dev/null
+++ b/tests/P_reflection3264_divergent/ScriptField_Divergent.java.expect
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptField_Divergent extends android.renderscript.Script.FieldBase {
+    static public class Item {
+
+        int i;
+        Allocation a;
+        int j;
+
+        Item() {
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    private static java.lang.ref.WeakReference<Element> mElementCache = new java.lang.ref.WeakReference<Element>(null);
+    public static Element createElement(RenderScript rs) {
+        Element.Builder eb = new Element.Builder(rs);
+        eb.add(Element.I32(rs), "i");
+        if (sIs64Bit) {
+            eb.add(Element.U32(rs), "#rs_padding_1");
+        }
+
+        eb.add(Element.ALLOCATION(rs), "a");
+        eb.add(Element.I32(rs), "j");
+        if (sIs64Bit) {
+            eb.add(Element.U32(rs), "#rs_padding_2");
+        }
+
+        return eb.create();
+    }
+
+    private  ScriptField_Divergent(RenderScript rs) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+    }
+
+    public  ScriptField_Divergent(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count);
+    }
+
+    public  ScriptField_Divergent(RenderScript rs, int count, int usages) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count, usages);
+    }
+
+    public static ScriptField_Divergent create1D(RenderScript rs, int dimX, int usages) {
+        ScriptField_Divergent obj = new ScriptField_Divergent(rs);
+        obj.mAllocation = Allocation.createSized(rs, obj.mElement, dimX, usages);
+        return obj;
+    }
+
+    public static ScriptField_Divergent create1D(RenderScript rs, int dimX) {
+        return create1D(rs, dimX, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_Divergent create2D(RenderScript rs, int dimX, int dimY) {
+        return create2D(rs, dimX, dimY, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_Divergent create2D(RenderScript rs, int dimX, int dimY, int usages) {
+        ScriptField_Divergent obj = new ScriptField_Divergent(rs);
+        Type.Builder b = new Type.Builder(rs, obj.mElement);
+        b.setX(dimX);
+        b.setY(dimY);
+        Type t = b.create();
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    public static Type.Builder createTypeBuilder(RenderScript rs) {
+        Element e = createElement(rs);
+        return new Type.Builder(rs, e);
+    }
+
+    public static ScriptField_Divergent createCustom(RenderScript rs, Type.Builder tb, int usages) {
+        ScriptField_Divergent obj = new ScriptField_Divergent(rs);
+        Type t = tb.create();
+        if (t.getElement() != obj.mElement) {
+            throw new RSIllegalArgumentException("Type.Builder did not match expected element type.");
+        }
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    private void copyToArrayLocal(Item i, FieldPacker fp) {
+        fp.addI32(i.i);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addObj(i.a);
+        fp.addI32(i.j);
+        fp.skip(sIs64Bit ? 4 : 0);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        mIOBuffer.reset(index * mElement.getBytesSize());
+        copyToArrayLocal(i, mIOBuffer);
+    }
+
+    public synchronized void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            FieldPacker fp = new FieldPacker(mElement.getBytesSize());
+            copyToArrayLocal(i, fp);
+            mAllocation.setFromFieldPacker(index, fp);
+        }
+
+    }
+
+    public synchronized Item get(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index];
+    }
+
+    public synchronized void set_i(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].i = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize());
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 0, fp);
+        }
+
+    }
+
+    public synchronized void set_a(int index, Allocation v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].a = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + (sIs64Bit ? 8 : 4));
+            mIOBuffer.addObj(v);
+            FieldPacker fp = new FieldPacker(sIs64Bit ? 32 : 4);
+            fp.addObj(v);
+            mAllocation.setFromFieldPacker(index, sIs64Bit ? 2 : 1, fp);
+        }
+
+    }
+
+    public synchronized void set_j(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].j = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + (sIs64Bit ? 40 : 8));
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, sIs64Bit ? 3 : 2, fp);
+        }
+
+    }
+
+    public synchronized int get_i(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].i;
+    }
+
+    public synchronized Allocation get_a(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index].a;
+    }
+
+    public synchronized int get_j(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].j;
+    }
+
+    public synchronized void copyAll() {
+        for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.setFromFieldPacker(0, mIOBuffer);
+    }
+
+    public synchronized void resize(int newSize) {
+        if (mItemArray != null)  {
+            int oldSize = mItemArray.length;
+            int copySize = Math.min(oldSize, newSize);
+            if (newSize == oldSize) return;
+            Item ni[] = new Item[newSize];
+            System.arraycopy(mItemArray, 0, ni, 0, copySize);
+            mItemArray = ni;
+        }
+
+        mAllocation.resize(newSize);
+        if (mIOBuffer != null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+    }
+
+    private static boolean sIs64Bit;
+
+    static {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            sIs64Bit = Process.is64Bit();
+        }
+
+        else {
+            try {
+                Field f = RenderScript.class.getDeclaredField("sPointerSize");
+                f.setAccessible(true);
+                sIs64Bit = (f.getInt(null) == 8);
+            }
+
+            catch (Throwable e) {
+                sIs64Bit = false;
+            }
+
+        }
+
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent/ScriptField_DivergentNest.java.expect b/tests/P_reflection3264_divergent/ScriptField_DivergentNest.java.expect
new file mode 100644
index 0000000..18ba85a
--- /dev/null
+++ b/tests/P_reflection3264_divergent/ScriptField_DivergentNest.java.expect
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptField_DivergentNest extends android.renderscript.Script.FieldBase {
+    static public class Item {
+
+        int x;
+        ScriptField_Divergent.Item d;
+        int y;
+
+        Item() {
+            d = new ScriptField_Divergent.Item();
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    private static java.lang.ref.WeakReference<Element> mElementCache = new java.lang.ref.WeakReference<Element>(null);
+    public static Element createElement(RenderScript rs) {
+        Element.Builder eb = new Element.Builder(rs);
+        eb.add(Element.I32(rs), "x");
+        if (sIs64Bit) {
+            eb.add(Element.U32(rs), "#rs_padding_1");
+        }
+
+        eb.add(ScriptField_Divergent.createElement(rs), "d");
+        eb.add(Element.I32(rs), "y");
+        if (sIs64Bit) {
+            eb.add(Element.U32(rs), "#rs_padding_2");
+        }
+
+        return eb.create();
+    }
+
+    private  ScriptField_DivergentNest(RenderScript rs) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+    }
+
+    public  ScriptField_DivergentNest(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count);
+    }
+
+    public  ScriptField_DivergentNest(RenderScript rs, int count, int usages) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count, usages);
+    }
+
+    public static ScriptField_DivergentNest create1D(RenderScript rs, int dimX, int usages) {
+        ScriptField_DivergentNest obj = new ScriptField_DivergentNest(rs);
+        obj.mAllocation = Allocation.createSized(rs, obj.mElement, dimX, usages);
+        return obj;
+    }
+
+    public static ScriptField_DivergentNest create1D(RenderScript rs, int dimX) {
+        return create1D(rs, dimX, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_DivergentNest create2D(RenderScript rs, int dimX, int dimY) {
+        return create2D(rs, dimX, dimY, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_DivergentNest create2D(RenderScript rs, int dimX, int dimY, int usages) {
+        ScriptField_DivergentNest obj = new ScriptField_DivergentNest(rs);
+        Type.Builder b = new Type.Builder(rs, obj.mElement);
+        b.setX(dimX);
+        b.setY(dimY);
+        Type t = b.create();
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    public static Type.Builder createTypeBuilder(RenderScript rs) {
+        Element e = createElement(rs);
+        return new Type.Builder(rs, e);
+    }
+
+    public static ScriptField_DivergentNest createCustom(RenderScript rs, Type.Builder tb, int usages) {
+        ScriptField_DivergentNest obj = new ScriptField_DivergentNest(rs);
+        Type t = tb.create();
+        if (t.getElement() != obj.mElement) {
+            throw new RSIllegalArgumentException("Type.Builder did not match expected element type.");
+        }
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    private void copyToArrayLocal(Item i, FieldPacker fp) {
+        fp.addI32(i.x);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addI32(i.d.i);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addObj(i.d.a);
+        fp.addI32(i.d.j);
+        fp.skip(sIs64Bit ? 4 : 0);
+        fp.addI32(i.y);
+        fp.skip(sIs64Bit ? 4 : 0);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        mIOBuffer.reset(index * mElement.getBytesSize());
+        copyToArrayLocal(i, mIOBuffer);
+    }
+
+    public synchronized void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            FieldPacker fp = new FieldPacker(mElement.getBytesSize());
+            copyToArrayLocal(i, fp);
+            mAllocation.setFromFieldPacker(index, fp);
+        }
+
+    }
+
+    public synchronized Item get(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index];
+    }
+
+    public synchronized void set_x(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].x = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize());
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 0, fp);
+        }
+
+    }
+
+    public synchronized void set_d(int index, ScriptField_Divergent.Item v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].d = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + (sIs64Bit ? 8 : 4));
+            mIOBuffer.addI32(v.i);
+            mIOBuffer.skip(sIs64Bit ? 4 : 0);
+            mIOBuffer.addObj(v.a);
+            mIOBuffer.addI32(v.j);
+            mIOBuffer.skip(sIs64Bit ? 4 : 0);
+            FieldPacker fp = new FieldPacker(sIs64Bit ? 48 : 12);
+            fp.addI32(v.i);
+            fp.skip(sIs64Bit ? 4 : 0);
+            fp.addObj(v.a);
+            fp.addI32(v.j);
+            fp.skip(sIs64Bit ? 4 : 0);
+            mAllocation.setFromFieldPacker(index, sIs64Bit ? 2 : 1, fp);
+        }
+
+    }
+
+    public synchronized void set_y(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].y = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + (sIs64Bit ? 56 : 16));
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, sIs64Bit ? 3 : 2, fp);
+        }
+
+    }
+
+    public synchronized int get_x(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].x;
+    }
+
+    public synchronized ScriptField_Divergent.Item get_d(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index].d;
+    }
+
+    public synchronized int get_y(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].y;
+    }
+
+    public synchronized void copyAll() {
+        for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.setFromFieldPacker(0, mIOBuffer);
+    }
+
+    public synchronized void resize(int newSize) {
+        if (mItemArray != null)  {
+            int oldSize = mItemArray.length;
+            int copySize = Math.min(oldSize, newSize);
+            if (newSize == oldSize) return;
+            Item ni[] = new Item[newSize];
+            System.arraycopy(mItemArray, 0, ni, 0, copySize);
+            mItemArray = ni;
+        }
+
+        mAllocation.resize(newSize);
+        if (mIOBuffer != null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+    }
+
+    private static boolean sIs64Bit;
+
+    static {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            sIs64Bit = Process.is64Bit();
+        }
+
+        else {
+            try {
+                Field f = RenderScript.class.getDeclaredField("sPointerSize");
+                f.setAccessible(true);
+                sIs64Bit = (f.getInt(null) == 8);
+            }
+
+            catch (Throwable e) {
+                sIs64Bit = false;
+            }
+
+        }
+
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent/ScriptField_NonDivergent.java.expect b/tests/P_reflection3264_divergent/ScriptField_NonDivergent.java.expect
new file mode 100644
index 0000000..437b9c5
--- /dev/null
+++ b/tests/P_reflection3264_divergent/ScriptField_NonDivergent.java.expect
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptField_NonDivergent extends android.renderscript.Script.FieldBase {
+    static public class Item {
+
+        int i;
+        int j;
+
+        Item() {
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    private static java.lang.ref.WeakReference<Element> mElementCache = new java.lang.ref.WeakReference<Element>(null);
+    public static Element createElement(RenderScript rs) {
+        Element.Builder eb = new Element.Builder(rs);
+        eb.add(Element.I32(rs), "i");
+        eb.add(Element.I32(rs), "j");
+        return eb.create();
+    }
+
+    private  ScriptField_NonDivergent(RenderScript rs) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+    }
+
+    public  ScriptField_NonDivergent(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count);
+    }
+
+    public  ScriptField_NonDivergent(RenderScript rs, int count, int usages) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count, usages);
+    }
+
+    public static ScriptField_NonDivergent create1D(RenderScript rs, int dimX, int usages) {
+        ScriptField_NonDivergent obj = new ScriptField_NonDivergent(rs);
+        obj.mAllocation = Allocation.createSized(rs, obj.mElement, dimX, usages);
+        return obj;
+    }
+
+    public static ScriptField_NonDivergent create1D(RenderScript rs, int dimX) {
+        return create1D(rs, dimX, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_NonDivergent create2D(RenderScript rs, int dimX, int dimY) {
+        return create2D(rs, dimX, dimY, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_NonDivergent create2D(RenderScript rs, int dimX, int dimY, int usages) {
+        ScriptField_NonDivergent obj = new ScriptField_NonDivergent(rs);
+        Type.Builder b = new Type.Builder(rs, obj.mElement);
+        b.setX(dimX);
+        b.setY(dimY);
+        Type t = b.create();
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    public static Type.Builder createTypeBuilder(RenderScript rs) {
+        Element e = createElement(rs);
+        return new Type.Builder(rs, e);
+    }
+
+    public static ScriptField_NonDivergent createCustom(RenderScript rs, Type.Builder tb, int usages) {
+        ScriptField_NonDivergent obj = new ScriptField_NonDivergent(rs);
+        Type t = tb.create();
+        if (t.getElement() != obj.mElement) {
+            throw new RSIllegalArgumentException("Type.Builder did not match expected element type.");
+        }
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    private void copyToArrayLocal(Item i, FieldPacker fp) {
+        fp.addI32(i.i);
+        fp.addI32(i.j);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        mIOBuffer.reset(index * mElement.getBytesSize());
+        copyToArrayLocal(i, mIOBuffer);
+    }
+
+    public synchronized void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            FieldPacker fp = new FieldPacker(mElement.getBytesSize());
+            copyToArrayLocal(i, fp);
+            mAllocation.setFromFieldPacker(index, fp);
+        }
+
+    }
+
+    public synchronized Item get(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index];
+    }
+
+    public synchronized void set_i(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].i = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize());
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 0, fp);
+        }
+
+    }
+
+    public synchronized void set_j(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].j = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + 4);
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 1, fp);
+        }
+
+    }
+
+    public synchronized int get_i(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].i;
+    }
+
+    public synchronized int get_j(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].j;
+    }
+
+    public synchronized void copyAll() {
+        for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.setFromFieldPacker(0, mIOBuffer);
+    }
+
+    public synchronized void resize(int newSize) {
+        if (mItemArray != null)  {
+            int oldSize = mItemArray.length;
+            int copySize = Math.min(oldSize, newSize);
+            if (newSize == oldSize) return;
+            Item ni[] = new Item[newSize];
+            System.arraycopy(mItemArray, 0, ni, 0, copySize);
+            mItemArray = ni;
+        }
+
+        mAllocation.resize(newSize);
+        if (mIOBuffer != null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent/reflection3264_divergent.rs b/tests/P_reflection3264_divergent/reflection3264_divergent.rs
new file mode 100644
index 0000000..05a43a5
--- /dev/null
+++ b/tests/P_reflection3264_divergent/reflection3264_divergent.rs
@@ -0,0 +1,75 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// "Divergent" = reflected code must have a runtime check for 32-bit
+// versus 64-bit target.
+
+// non-divergent
+int intVar;
+
+// non-divergent
+int intArray[10];
+
+// non-divergent
+rs_matrix2x2 matVar;
+
+// non-divergent
+rs_matrix2x2 matArray[10];
+
+// divergent
+rs_allocation allocVar;
+
+// divergent
+rs_allocation allocArray[10];
+
+struct NonDivergent {
+  int i;
+  int j;
+};
+
+struct NonDivergent ndVar;
+
+struct NonDivergent ndArray[10];
+
+// 32-bit: 12 bytes; 64-bit: 48 bytes
+struct Divergent {
+  int i;
+  rs_allocation a;
+  int j;
+};
+
+struct Divergent dVar;
+
+struct Divergent dArray[10];
+
+// 32-bit: 20 bytes; 64-bit: 64 bytes
+struct DivergentNest {
+  int x;
+  struct Divergent d;
+  int y;
+};
+
+struct DivergentNest dnVar;
+
+struct DivergentNest dnArray[10];
+
+void intFe(const int *in, int *out, const int *data) { }
+
+void matFe(const int *in, int *out, const rs_matrix2x2 *data) { }
+
+void allocFe(const int *in, int *out, const rs_allocation *data) { }
+
+void ndFe(const int *in, int *out, const struct NonDivergent *data) { }
+
+void dFe(const int *in, int *out, const struct Divergent *data) { }
+
+void dnFe(const int *in, int *out, const struct DivergentNest *data) { }
+
+// for arguments, should get a helper struct that looks like struct NonDivergent
+void ndInv(int i, int j) { }
+
+// for arguments, should get a helper struct that looks like struct Divergent
+void dInv(int i, rs_allocation a, int j) { }
+
+// for arguments, should get a helper struct that looks like struct DivergentNest
+void dnInv(int x, struct Divergent d, int y) { }
diff --git a/tests/P_reflection3264_divergent/stderr.txt.expect b/tests/P_reflection3264_divergent/stderr.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_reflection3264_divergent/stderr.txt.expect
diff --git a/tests/P_reflection3264_divergent/stdout.txt.expect b/tests/P_reflection3264_divergent/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_reflection3264_divergent/stdout.txt.expect
diff --git a/tests/P_reflection3264_divergent_support/ScriptC_reflection3264_divergent.java.expect b/tests/P_reflection3264_divergent_support/ScriptC_reflection3264_divergent.java.expect
new file mode 100644
index 0000000..6d68c35
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/ScriptC_reflection3264_divergent.java.expect
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.support.v8.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptC_reflection3264_divergent extends ScriptC {
+    private static final String __rs_resource_name = "reflection3264_divergent";
+    // Constructor
+    public  ScriptC_reflection3264_divergent(RenderScript rs) {
+        super(rs,
+              __rs_resource_name,
+              reflection3264_divergentBitCode.getBitCode32(),
+              reflection3264_divergentBitCode.getBitCode64());
+        __I32 = Element.I32(rs);
+        __@@INVALID@@ = Element.@@INVALID@@(rs);
+        __ALLOCATION = Element.ALLOCATION(rs);
+        __ScriptField_NonDivergent = ScriptField_NonDivergent.createElement(rs);
+        __ScriptField_Divergent = ScriptField_Divergent.createElement(rs);
+        __ScriptField_DivergentNest = ScriptField_DivergentNest.createElement(rs);
+    }
+
+    private Element __@@INVALID@@;
+    private Element __ALLOCATION;
+    private Element __I32;
+    private Element __ScriptField_Divergent;
+    private Element __ScriptField_DivergentNest;
+    private Element __ScriptField_NonDivergent;
+    private FieldPacker __rs_fp_@@INVALID@@;
+    private FieldPacker __rs_fp_ALLOCATION;
+    private FieldPacker __rs_fp_I32;
+    private FieldPacker __rs_fp_ScriptField_Divergent;
+    private FieldPacker __rs_fp_ScriptField_DivergentNest;
+    private FieldPacker __rs_fp_ScriptField_NonDivergent;
+    private final static int mExportVarIdx_intVar = 0;
+    private int mExportVar_intVar;
+    public synchronized void set_intVar(int v) {
+        setVar(mExportVarIdx_intVar, v);
+        mExportVar_intVar = v;
+    }
+
+    public int get_intVar() {
+        return mExportVar_intVar;
+    }
+
+    public Script.FieldID getFieldID_intVar() {
+        return createFieldID(mExportVarIdx_intVar, null);
+    }
+
+    private final static int mExportVarIdx_intArray = 1;
+    private int[] mExportVar_intArray;
+    public synchronized void set_intArray(int[] v) {
+        mExportVar_intArray = v;
+        FieldPacker fp = new FieldPacker(40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_intArray, fp, __I32, __dimArr);
+    }
+
+    public int[] get_intArray() {
+        return mExportVar_intArray;
+    }
+
+    public Script.FieldID getFieldID_intArray() {
+        return createFieldID(mExportVarIdx_intArray, null);
+    }
+
+    private final static int mExportVarIdx_matVar = 2;
+    private Matrix2f mExportVar_matVar;
+    public synchronized void set_matVar(Matrix2f v) {
+        mExportVar_matVar = v;
+        FieldPacker fp = new FieldPacker(16);
+        fp.addMatrix(v);
+        setVar(mExportVarIdx_matVar, fp);
+    }
+
+    public Matrix2f get_matVar() {
+        return mExportVar_matVar;
+    }
+
+    public Script.FieldID getFieldID_matVar() {
+        return createFieldID(mExportVarIdx_matVar, null);
+    }
+
+    private final static int mExportVarIdx_matArray = 3;
+    private Matrix2f[] mExportVar_matArray;
+    public synchronized void set_matArray(Matrix2f[] v) {
+        mExportVar_matArray = v;
+        FieldPacker fp = new FieldPacker(160);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addMatrix(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_matArray, fp, __@@INVALID@@, __dimArr);
+    }
+
+    public Matrix2f[] get_matArray() {
+        return mExportVar_matArray;
+    }
+
+    public Script.FieldID getFieldID_matArray() {
+        return createFieldID(mExportVarIdx_matArray, null);
+    }
+
+    private final static int mExportVarIdx_allocVar = 4;
+    private Allocation mExportVar_allocVar;
+    public synchronized void set_allocVar(Allocation v) {
+        setVar(mExportVarIdx_allocVar, v);
+        mExportVar_allocVar = v;
+    }
+
+    public Allocation get_allocVar() {
+        return mExportVar_allocVar;
+    }
+
+    public Script.FieldID getFieldID_allocVar() {
+        return createFieldID(mExportVarIdx_allocVar, null);
+    }
+
+    private final static int mExportVarIdx_allocArray = 5;
+    private Allocation[] mExportVar_allocArray;
+    public synchronized void set_allocArray(Allocation[] v) {
+        mExportVar_allocArray = v;
+        FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 320 : 40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addObj(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_allocArray, fp, __ALLOCATION, __dimArr);
+    }
+
+    public Allocation[] get_allocArray() {
+        return mExportVar_allocArray;
+    }
+
+    public Script.FieldID getFieldID_allocArray() {
+        return createFieldID(mExportVarIdx_allocArray, null);
+    }
+
+    private final static int mExportVarIdx_ndVar = 6;
+    private ScriptField_NonDivergent.Item mExportVar_ndVar;
+    public synchronized void set_ndVar(ScriptField_NonDivergent.Item v) {
+        mExportVar_ndVar = v;
+        FieldPacker fp = new FieldPacker(8);
+        fp.addI32(v.i);
+        fp.addI32(v.j);
+        int []__dimArr = new int[1];
+        __dimArr[0] = 1;
+        setVar(mExportVarIdx_ndVar, fp, __ScriptField_NonDivergent, __dimArr);
+    }
+
+    public ScriptField_NonDivergent.Item get_ndVar() {
+        return mExportVar_ndVar;
+    }
+
+    public Script.FieldID getFieldID_ndVar() {
+        return createFieldID(mExportVarIdx_ndVar, null);
+    }
+
+    private final static int mExportVarIdx_ndArray = 7;
+    private ScriptField_NonDivergent.Item[] mExportVar_ndArray;
+    public synchronized void set_ndArray(ScriptField_NonDivergent.Item[] v) {
+        mExportVar_ndArray = v;
+        FieldPacker fp = new FieldPacker(80);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1].i);
+            fp.addI32(v[ct1].j);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_ndArray, fp, __ScriptField_NonDivergent, __dimArr);
+    }
+
+    public ScriptField_NonDivergent.Item[] get_ndArray() {
+        return mExportVar_ndArray;
+    }
+
+    public Script.FieldID getFieldID_ndArray() {
+        return createFieldID(mExportVarIdx_ndArray, null);
+    }
+
+    private final static int mExportVarIdx_dVar = 8;
+    private ScriptField_Divergent.Item mExportVar_dVar;
+    public synchronized void set_dVar(ScriptField_Divergent.Item v) {
+        mExportVar_dVar = v;
+        FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 48 : 12);
+        fp.addI32(v.i);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addObj(v.a);
+        fp.addI32(v.j);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        int []__dimArr = new int[1];
+        __dimArr[0] = 1;
+        setVar(mExportVarIdx_dVar, fp, __ScriptField_Divergent, __dimArr);
+    }
+
+    public ScriptField_Divergent.Item get_dVar() {
+        return mExportVar_dVar;
+    }
+
+    public Script.FieldID getFieldID_dVar() {
+        return createFieldID(mExportVarIdx_dVar, null);
+    }
+
+    private final static int mExportVarIdx_dArray = 9;
+    private ScriptField_Divergent.Item[] mExportVar_dArray;
+    public synchronized void set_dArray(ScriptField_Divergent.Item[] v) {
+        mExportVar_dArray = v;
+        FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 400 : 120);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1].i);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            fp.addObj(v[ct1].a);
+            fp.addI32(v[ct1].j);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_dArray, fp, __ScriptField_Divergent, __dimArr);
+    }
+
+    public ScriptField_Divergent.Item[] get_dArray() {
+        return mExportVar_dArray;
+    }
+
+    public Script.FieldID getFieldID_dArray() {
+        return createFieldID(mExportVarIdx_dArray, null);
+    }
+
+    private final static int mExportVarIdx_dnVar = 10;
+    private ScriptField_DivergentNest.Item mExportVar_dnVar;
+    public synchronized void set_dnVar(ScriptField_DivergentNest.Item v) {
+        mExportVar_dnVar = v;
+        FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 64 : 20);
+        fp.addI32(v.x);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addI32(v.d.i);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addObj(v.d.a);
+        fp.addI32(v.d.j);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addI32(v.y);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        int []__dimArr = new int[1];
+        __dimArr[0] = 1;
+        setVar(mExportVarIdx_dnVar, fp, __ScriptField_DivergentNest, __dimArr);
+    }
+
+    public ScriptField_DivergentNest.Item get_dnVar() {
+        return mExportVar_dnVar;
+    }
+
+    public Script.FieldID getFieldID_dnVar() {
+        return createFieldID(mExportVarIdx_dnVar, null);
+    }
+
+    private final static int mExportVarIdx_dnArray = 11;
+    private ScriptField_DivergentNest.Item[] mExportVar_dnArray;
+    public synchronized void set_dnArray(ScriptField_DivergentNest.Item[] v) {
+        mExportVar_dnArray = v;
+        FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 480 : 200);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1].x);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            fp.addI32(v[ct1].d.i);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            fp.addObj(v[ct1].d.a);
+            fp.addI32(v[ct1].d.j);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            fp.addI32(v[ct1].y);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_dnArray, fp, __ScriptField_DivergentNest, __dimArr);
+    }
+
+    public ScriptField_DivergentNest.Item[] get_dnArray() {
+        return mExportVar_dnArray;
+    }
+
+    public Script.FieldID getFieldID_dnArray() {
+        return createFieldID(mExportVarIdx_dnArray, null);
+    }
+
+    //private final static int mExportForEachIdx_root = 0;
+    private final static int mExportForEachIdx_dnFe = 1;
+    public Script.KernelID getKernelID_dnFe() {
+        return createKernelID(mExportForEachIdx_dnFe, 7, null, null);
+    }
+
+    public void forEach_dnFe(Allocation ain, Allocation aout, ScriptField_DivergentNest.Item data) {
+        forEach_dnFe(ain, aout, data, null);
+    }
+
+    public void forEach_dnFe(Allocation ain, Allocation aout, ScriptField_DivergentNest.Item data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker dnFe_fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 64 : 20);
+        dnFe_fp.addI32(data.x);
+        dnFe_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dnFe_fp.addI32(data.d.i);
+        dnFe_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dnFe_fp.addObj(data.d.a);
+        dnFe_fp.addI32(data.d.j);
+        dnFe_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dnFe_fp.addI32(data.y);
+        dnFe_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        forEach(mExportForEachIdx_dnFe, ain, aout, dnFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_dFe = 2;
+    public Script.KernelID getKernelID_dFe() {
+        return createKernelID(mExportForEachIdx_dFe, 7, null, null);
+    }
+
+    public void forEach_dFe(Allocation ain, Allocation aout, ScriptField_Divergent.Item data) {
+        forEach_dFe(ain, aout, data, null);
+    }
+
+    public void forEach_dFe(Allocation ain, Allocation aout, ScriptField_Divergent.Item data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker dFe_fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 48 : 12);
+        dFe_fp.addI32(data.i);
+        dFe_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dFe_fp.addObj(data.a);
+        dFe_fp.addI32(data.j);
+        dFe_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        forEach(mExportForEachIdx_dFe, ain, aout, dFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_ndFe = 3;
+    public Script.KernelID getKernelID_ndFe() {
+        return createKernelID(mExportForEachIdx_ndFe, 7, null, null);
+    }
+
+    public void forEach_ndFe(Allocation ain, Allocation aout, ScriptField_NonDivergent.Item data) {
+        forEach_ndFe(ain, aout, data, null);
+    }
+
+    public void forEach_ndFe(Allocation ain, Allocation aout, ScriptField_NonDivergent.Item data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker ndFe_fp = new FieldPacker(8);
+        ndFe_fp.addI32(data.i);
+        ndFe_fp.addI32(data.j);
+        forEach(mExportForEachIdx_ndFe, ain, aout, ndFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_allocFe = 4;
+    public Script.KernelID getKernelID_allocFe() {
+        return createKernelID(mExportForEachIdx_allocFe, 7, null, null);
+    }
+
+    public void forEach_allocFe(Allocation ain, Allocation aout, Allocation data) {
+        forEach_allocFe(ain, aout, data, null);
+    }
+
+    public void forEach_allocFe(Allocation ain, Allocation aout, Allocation data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker allocFe_fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 32 : 4);
+        allocFe_fp.addObj(data);
+        forEach(mExportForEachIdx_allocFe, ain, aout, allocFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_matFe = 5;
+    public Script.KernelID getKernelID_matFe() {
+        return createKernelID(mExportForEachIdx_matFe, 7, null, null);
+    }
+
+    public void forEach_matFe(Allocation ain, Allocation aout, Matrix2f data) {
+        forEach_matFe(ain, aout, data, null);
+    }
+
+    public void forEach_matFe(Allocation ain, Allocation aout, Matrix2f data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker matFe_fp = new FieldPacker(16);
+        matFe_fp.addMatrix(data);
+        forEach(mExportForEachIdx_matFe, ain, aout, matFe_fp, sc);
+    }
+
+    private final static int mExportForEachIdx_intFe = 6;
+    public Script.KernelID getKernelID_intFe() {
+        return createKernelID(mExportForEachIdx_intFe, 7, null, null);
+    }
+
+    public void forEach_intFe(Allocation ain, Allocation aout, int data) {
+        forEach_intFe(ain, aout, data, null);
+    }
+
+    public void forEach_intFe(Allocation ain, Allocation aout, int data, Script.LaunchOptions sc) {
+        // check ain
+        if (!ain.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        // check aout
+        if (!aout.getType().getElement().isCompatible(__I32)) {
+            throw new RSRuntimeException("Type mismatch with I32!");
+        }
+        Type t0, t1;        // Verify dimensions
+        t0 = ain.getType();
+        t1 = aout.getType();
+        if ((t0.getCount() != t1.getCount()) ||
+            (t0.getX() != t1.getX()) ||
+            (t0.getY() != t1.getY()) ||
+            (t0.getZ() != t1.getZ()) ||
+            (t0.hasFaces()   != t1.hasFaces()) ||
+            (t0.hasMipmaps() != t1.hasMipmaps())) {
+            throw new RSRuntimeException("Dimension mismatch between parameters ain and aout!");
+        }
+
+        FieldPacker intFe_fp = new FieldPacker(4);
+        intFe_fp.addI32(data);
+        forEach(mExportForEachIdx_intFe, ain, aout, intFe_fp, sc);
+    }
+
+    private final static int mExportFuncIdx_ndInv = 0;
+    public Script.InvokeID getInvokeID_ndInv() {
+        return createInvokeID(mExportFuncIdx_ndInv);
+    }
+
+    public void invoke_ndInv(int i, int j) {
+        FieldPacker ndInv_fp = new FieldPacker(8);
+        ndInv_fp.addI32(i);
+        ndInv_fp.addI32(j);
+        invoke(mExportFuncIdx_ndInv, ndInv_fp);
+    }
+
+    private final static int mExportFuncIdx_dInv = 1;
+    public Script.InvokeID getInvokeID_dInv() {
+        return createInvokeID(mExportFuncIdx_dInv);
+    }
+
+    public void invoke_dInv(int i, Allocation a, int j) {
+        FieldPacker dInv_fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 48 : 12);
+        dInv_fp.addI32(i);
+        dInv_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dInv_fp.addObj(a);
+        dInv_fp.addI32(j);
+        dInv_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        invoke(mExportFuncIdx_dInv, dInv_fp);
+    }
+
+    private final static int mExportFuncIdx_dnInv = 2;
+    public Script.InvokeID getInvokeID_dnInv() {
+        return createInvokeID(mExportFuncIdx_dnInv);
+    }
+
+    public void invoke_dnInv(int x, ScriptField_Divergent.Item d, int y) {
+        FieldPacker dnInv_fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 64 : 20);
+        dnInv_fp.addI32(x);
+        dnInv_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dnInv_fp.addI32(d.i);
+        dnInv_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dnInv_fp.addObj(d.a);
+        dnInv_fp.addI32(d.j);
+        dnInv_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        dnInv_fp.addI32(y);
+        dnInv_fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        invoke(mExportFuncIdx_dnInv, dnInv_fp);
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent_support/ScriptField_Divergent.java.expect b/tests/P_reflection3264_divergent_support/ScriptField_Divergent.java.expect
new file mode 100644
index 0000000..dc5e6c0
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/ScriptField_Divergent.java.expect
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.support.v8.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptField_Divergent extends android.support.v8.renderscript.Script.FieldBase {
+    static public class Item {
+
+        int i;
+        Allocation a;
+        int j;
+
+        Item() {
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    private static java.lang.ref.WeakReference<Element> mElementCache = new java.lang.ref.WeakReference<Element>(null);
+    public static Element createElement(RenderScript rs) {
+        Element.Builder eb = new Element.Builder(rs);
+        eb.add(Element.I32(rs), "i");
+        if (RenderScript.getPointerSize() == 8) {
+            eb.add(Element.U32(rs), "#rs_padding_1");
+        }
+
+        eb.add(Element.ALLOCATION(rs), "a");
+        eb.add(Element.I32(rs), "j");
+        if (RenderScript.getPointerSize() == 8) {
+            eb.add(Element.U32(rs), "#rs_padding_2");
+        }
+
+        return eb.create();
+    }
+
+    private  ScriptField_Divergent(RenderScript rs) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+    }
+
+    public  ScriptField_Divergent(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count);
+    }
+
+    public  ScriptField_Divergent(RenderScript rs, int count, int usages) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count, usages);
+    }
+
+    public static ScriptField_Divergent create1D(RenderScript rs, int dimX, int usages) {
+        ScriptField_Divergent obj = new ScriptField_Divergent(rs);
+        obj.mAllocation = Allocation.createSized(rs, obj.mElement, dimX, usages);
+        return obj;
+    }
+
+    public static ScriptField_Divergent create1D(RenderScript rs, int dimX) {
+        return create1D(rs, dimX, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_Divergent create2D(RenderScript rs, int dimX, int dimY) {
+        return create2D(rs, dimX, dimY, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_Divergent create2D(RenderScript rs, int dimX, int dimY, int usages) {
+        ScriptField_Divergent obj = new ScriptField_Divergent(rs);
+        Type.Builder b = new Type.Builder(rs, obj.mElement);
+        b.setX(dimX);
+        b.setY(dimY);
+        Type t = b.create();
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    public static Type.Builder createTypeBuilder(RenderScript rs) {
+        Element e = createElement(rs);
+        return new Type.Builder(rs, e);
+    }
+
+    public static ScriptField_Divergent createCustom(RenderScript rs, Type.Builder tb, int usages) {
+        ScriptField_Divergent obj = new ScriptField_Divergent(rs);
+        Type t = tb.create();
+        if (t.getElement() != obj.mElement) {
+            throw new RSIllegalArgumentException("Type.Builder did not match expected element type.");
+        }
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    private void copyToArrayLocal(Item i, FieldPacker fp) {
+        fp.addI32(i.i);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addObj(i.a);
+        fp.addI32(i.j);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        mIOBuffer.reset(index * mElement.getBytesSize());
+        copyToArrayLocal(i, mIOBuffer);
+    }
+
+    public synchronized void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            FieldPacker fp = new FieldPacker(mElement.getBytesSize());
+            copyToArrayLocal(i, fp);
+            mAllocation.setFromFieldPacker(index, fp);
+        }
+
+    }
+
+    public synchronized Item get(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index];
+    }
+
+    public synchronized void set_i(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].i = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize());
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 0, fp);
+        }
+
+    }
+
+    public synchronized void set_a(int index, Allocation v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].a = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + ((RenderScript.getPointerSize() == 8) ? 8 : 4));
+            mIOBuffer.addObj(v);
+            FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 32 : 4);
+            fp.addObj(v);
+            mAllocation.setFromFieldPacker(index, (RenderScript.getPointerSize() == 8) ? 2 : 1, fp);
+        }
+
+    }
+
+    public synchronized void set_j(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].j = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + ((RenderScript.getPointerSize() == 8) ? 40 : 8));
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, (RenderScript.getPointerSize() == 8) ? 3 : 2, fp);
+        }
+
+    }
+
+    public synchronized int get_i(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].i;
+    }
+
+    public synchronized Allocation get_a(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index].a;
+    }
+
+    public synchronized int get_j(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].j;
+    }
+
+    public synchronized void copyAll() {
+        for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.setFromFieldPacker(0, mIOBuffer);
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent_support/ScriptField_DivergentNest.java.expect b/tests/P_reflection3264_divergent_support/ScriptField_DivergentNest.java.expect
new file mode 100644
index 0000000..80df1cd
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/ScriptField_DivergentNest.java.expect
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.support.v8.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptField_DivergentNest extends android.support.v8.renderscript.Script.FieldBase {
+    static public class Item {
+
+        int x;
+        ScriptField_Divergent.Item d;
+        int y;
+
+        Item() {
+            d = new ScriptField_Divergent.Item();
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    private static java.lang.ref.WeakReference<Element> mElementCache = new java.lang.ref.WeakReference<Element>(null);
+    public static Element createElement(RenderScript rs) {
+        Element.Builder eb = new Element.Builder(rs);
+        eb.add(Element.I32(rs), "x");
+        if (RenderScript.getPointerSize() == 8) {
+            eb.add(Element.U32(rs), "#rs_padding_1");
+        }
+
+        eb.add(ScriptField_Divergent.createElement(rs), "d");
+        eb.add(Element.I32(rs), "y");
+        if (RenderScript.getPointerSize() == 8) {
+            eb.add(Element.U32(rs), "#rs_padding_2");
+        }
+
+        return eb.create();
+    }
+
+    private  ScriptField_DivergentNest(RenderScript rs) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+    }
+
+    public  ScriptField_DivergentNest(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count);
+    }
+
+    public  ScriptField_DivergentNest(RenderScript rs, int count, int usages) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count, usages);
+    }
+
+    public static ScriptField_DivergentNest create1D(RenderScript rs, int dimX, int usages) {
+        ScriptField_DivergentNest obj = new ScriptField_DivergentNest(rs);
+        obj.mAllocation = Allocation.createSized(rs, obj.mElement, dimX, usages);
+        return obj;
+    }
+
+    public static ScriptField_DivergentNest create1D(RenderScript rs, int dimX) {
+        return create1D(rs, dimX, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_DivergentNest create2D(RenderScript rs, int dimX, int dimY) {
+        return create2D(rs, dimX, dimY, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_DivergentNest create2D(RenderScript rs, int dimX, int dimY, int usages) {
+        ScriptField_DivergentNest obj = new ScriptField_DivergentNest(rs);
+        Type.Builder b = new Type.Builder(rs, obj.mElement);
+        b.setX(dimX);
+        b.setY(dimY);
+        Type t = b.create();
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    public static Type.Builder createTypeBuilder(RenderScript rs) {
+        Element e = createElement(rs);
+        return new Type.Builder(rs, e);
+    }
+
+    public static ScriptField_DivergentNest createCustom(RenderScript rs, Type.Builder tb, int usages) {
+        ScriptField_DivergentNest obj = new ScriptField_DivergentNest(rs);
+        Type t = tb.create();
+        if (t.getElement() != obj.mElement) {
+            throw new RSIllegalArgumentException("Type.Builder did not match expected element type.");
+        }
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    private void copyToArrayLocal(Item i, FieldPacker fp) {
+        fp.addI32(i.x);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addI32(i.d.i);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addObj(i.d.a);
+        fp.addI32(i.d.j);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+        fp.addI32(i.y);
+        fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        mIOBuffer.reset(index * mElement.getBytesSize());
+        copyToArrayLocal(i, mIOBuffer);
+    }
+
+    public synchronized void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            FieldPacker fp = new FieldPacker(mElement.getBytesSize());
+            copyToArrayLocal(i, fp);
+            mAllocation.setFromFieldPacker(index, fp);
+        }
+
+    }
+
+    public synchronized Item get(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index];
+    }
+
+    public synchronized void set_x(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].x = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize());
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 0, fp);
+        }
+
+    }
+
+    public synchronized void set_d(int index, ScriptField_Divergent.Item v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].d = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + ((RenderScript.getPointerSize() == 8) ? 8 : 4));
+            mIOBuffer.addI32(v.i);
+            mIOBuffer.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            mIOBuffer.addObj(v.a);
+            mIOBuffer.addI32(v.j);
+            mIOBuffer.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            FieldPacker fp = new FieldPacker((RenderScript.getPointerSize() == 8) ? 48 : 12);
+            fp.addI32(v.i);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            fp.addObj(v.a);
+            fp.addI32(v.j);
+            fp.skip((RenderScript.getPointerSize() == 8) ? 4 : 0);
+            mAllocation.setFromFieldPacker(index, (RenderScript.getPointerSize() == 8) ? 2 : 1, fp);
+        }
+
+    }
+
+    public synchronized void set_y(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].y = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + ((RenderScript.getPointerSize() == 8) ? 56 : 16));
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, (RenderScript.getPointerSize() == 8) ? 3 : 2, fp);
+        }
+
+    }
+
+    public synchronized int get_x(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].x;
+    }
+
+    public synchronized ScriptField_Divergent.Item get_d(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index].d;
+    }
+
+    public synchronized int get_y(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].y;
+    }
+
+    public synchronized void copyAll() {
+        for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.setFromFieldPacker(0, mIOBuffer);
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent_support/ScriptField_NonDivergent.java.expect b/tests/P_reflection3264_divergent_support/ScriptField_NonDivergent.java.expect
new file mode 100644
index 0000000..64559c3
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/ScriptField_NonDivergent.java.expect
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_divergent.rs
+ */
+
+package foo;
+
+import android.support.v8.renderscript.*;
+import foo.reflection3264_divergentBitCode;
+
+/**
+ * @hide
+ */
+public class ScriptField_NonDivergent extends android.support.v8.renderscript.Script.FieldBase {
+    static public class Item {
+
+        int i;
+        int j;
+
+        Item() {
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    private static java.lang.ref.WeakReference<Element> mElementCache = new java.lang.ref.WeakReference<Element>(null);
+    public static Element createElement(RenderScript rs) {
+        Element.Builder eb = new Element.Builder(rs);
+        eb.add(Element.I32(rs), "i");
+        eb.add(Element.I32(rs), "j");
+        return eb.create();
+    }
+
+    private  ScriptField_NonDivergent(RenderScript rs) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+    }
+
+    public  ScriptField_NonDivergent(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count);
+    }
+
+    public  ScriptField_NonDivergent(RenderScript rs, int count, int usages) {
+        mItemArray = null;
+        mIOBuffer = null;
+        mElement = createElement(rs);
+        init(rs, count, usages);
+    }
+
+    public static ScriptField_NonDivergent create1D(RenderScript rs, int dimX, int usages) {
+        ScriptField_NonDivergent obj = new ScriptField_NonDivergent(rs);
+        obj.mAllocation = Allocation.createSized(rs, obj.mElement, dimX, usages);
+        return obj;
+    }
+
+    public static ScriptField_NonDivergent create1D(RenderScript rs, int dimX) {
+        return create1D(rs, dimX, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_NonDivergent create2D(RenderScript rs, int dimX, int dimY) {
+        return create2D(rs, dimX, dimY, Allocation.USAGE_SCRIPT);
+    }
+
+    public static ScriptField_NonDivergent create2D(RenderScript rs, int dimX, int dimY, int usages) {
+        ScriptField_NonDivergent obj = new ScriptField_NonDivergent(rs);
+        Type.Builder b = new Type.Builder(rs, obj.mElement);
+        b.setX(dimX);
+        b.setY(dimY);
+        Type t = b.create();
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    public static Type.Builder createTypeBuilder(RenderScript rs) {
+        Element e = createElement(rs);
+        return new Type.Builder(rs, e);
+    }
+
+    public static ScriptField_NonDivergent createCustom(RenderScript rs, Type.Builder tb, int usages) {
+        ScriptField_NonDivergent obj = new ScriptField_NonDivergent(rs);
+        Type t = tb.create();
+        if (t.getElement() != obj.mElement) {
+            throw new RSIllegalArgumentException("Type.Builder did not match expected element type.");
+        }
+        obj.mAllocation = Allocation.createTyped(rs, t, usages);
+        return obj;
+    }
+
+    private void copyToArrayLocal(Item i, FieldPacker fp) {
+        fp.addI32(i.i);
+        fp.addI32(i.j);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        mIOBuffer.reset(index * mElement.getBytesSize());
+        copyToArrayLocal(i, mIOBuffer);
+    }
+
+    public synchronized void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            FieldPacker fp = new FieldPacker(mElement.getBytesSize());
+            copyToArrayLocal(i, fp);
+            mAllocation.setFromFieldPacker(index, fp);
+        }
+
+    }
+
+    public synchronized Item get(int index) {
+        if (mItemArray == null) return null;
+        return mItemArray[index];
+    }
+
+    public synchronized void set_i(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].i = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize());
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 0, fp);
+        }
+
+    }
+
+    public synchronized void set_j(int index, int v, boolean copyNow) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(mElement.getBytesSize() * getType().getX()/* count */);
+        if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+        if (mItemArray[index] == null) mItemArray[index] = new Item();
+        mItemArray[index].j = v;
+        if (copyNow)  {
+            mIOBuffer.reset(index * mElement.getBytesSize() + 4);
+            mIOBuffer.addI32(v);
+            FieldPacker fp = new FieldPacker(4);
+            fp.addI32(v);
+            mAllocation.setFromFieldPacker(index, 1, fp);
+        }
+
+    }
+
+    public synchronized int get_i(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].i;
+    }
+
+    public synchronized int get_j(int index) {
+        if (mItemArray == null) return 0;
+        return mItemArray[index].j;
+    }
+
+    public synchronized void copyAll() {
+        for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.setFromFieldPacker(0, mIOBuffer);
+    }
+
+}
+
diff --git a/tests/P_reflection3264_divergent_support/reflection3264_divergent.rs b/tests/P_reflection3264_divergent_support/reflection3264_divergent.rs
new file mode 100644
index 0000000..4dff5df
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/reflection3264_divergent.rs
@@ -0,0 +1,77 @@
+// -rs-package-name android.support.v8.renderscript
+
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// "Divergent" = reflected code must have a runtime check for 32-bit
+// versus 64-bit target.
+
+// non-divergent
+int intVar;
+
+// non-divergent
+int intArray[10];
+
+// non-divergent
+rs_matrix2x2 matVar;
+
+// non-divergent
+rs_matrix2x2 matArray[10];
+
+// divergent
+rs_allocation allocVar;
+
+// divergent
+rs_allocation allocArray[10];
+
+struct NonDivergent {
+  int i;
+  int j;
+};
+
+struct NonDivergent ndVar;
+
+struct NonDivergent ndArray[10];
+
+// 32-bit: 12 bytes; 64-bit: 48 bytes
+struct Divergent {
+  int i;
+  rs_allocation a;
+  int j;
+};
+
+struct Divergent dVar;
+
+struct Divergent dArray[10];
+
+// 32-bit: 20 bytes; 64-bit: 64 bytes
+struct DivergentNest {
+  int x;
+  struct Divergent d;
+  int y;
+};
+
+struct DivergentNest dnVar;
+
+struct DivergentNest dnArray[10];
+
+void intFe(const int *in, int *out, const int *data) { }
+
+void matFe(const int *in, int *out, const rs_matrix2x2 *data) { }
+
+void allocFe(const int *in, int *out, const rs_allocation *data) { }
+
+void ndFe(const int *in, int *out, const struct NonDivergent *data) { }
+
+void dFe(const int *in, int *out, const struct Divergent *data) { }
+
+void dnFe(const int *in, int *out, const struct DivergentNest *data) { }
+
+// for arguments, should get a helper struct that looks like struct NonDivergent
+void ndInv(int i, int j) { }
+
+// for arguments, should get a helper struct that looks like struct Divergent
+void dInv(int i, rs_allocation a, int j) { }
+
+// for arguments, should get a helper struct that looks like struct DivergentNest
+void dnInv(int x, struct Divergent d, int y) { }
diff --git a/tests/P_reflection3264_divergent_support/stderr.txt.expect b/tests/P_reflection3264_divergent_support/stderr.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/stderr.txt.expect
diff --git a/tests/P_reflection3264_divergent_support/stdout.txt.expect b/tests/P_reflection3264_divergent_support/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_reflection3264_divergent_support/stdout.txt.expect
diff --git a/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_1.java.expect b/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_1.java.expect
new file mode 100644
index 0000000..9637753
--- /dev/null
+++ b/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_1.java.expect
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_multifile_1.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_multifile_1BitCode;
+
+/**
+ * @hide
+ */
+public class ScriptC_reflection3264_multifile_1 extends ScriptC {
+    private static final String __rs_resource_name = "reflection3264_multifile_1";
+    // Constructor
+    public  ScriptC_reflection3264_multifile_1(RenderScript rs) {
+        super(rs,
+              __rs_resource_name,
+              reflection3264_multifile_1BitCode.getBitCode32(),
+              reflection3264_multifile_1BitCode.getBitCode64());
+        __I32 = Element.I32(rs);
+        __ALLOCATION = Element.ALLOCATION(rs);
+    }
+
+    private Element __ALLOCATION;
+    private Element __I32;
+    private FieldPacker __rs_fp_ALLOCATION;
+    private FieldPacker __rs_fp_I32;
+    private final static int mExportVarIdx_a = 0;
+    private int[] mExportVar_a;
+    public synchronized void set_a(int[] v) {
+        mExportVar_a = v;
+        FieldPacker fp = new FieldPacker(40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_a, fp, __I32, __dimArr);
+    }
+
+    public int[] get_a() {
+        return mExportVar_a;
+    }
+
+    public Script.FieldID getFieldID_a() {
+        return createFieldID(mExportVarIdx_a, null);
+    }
+
+    private final static int mExportVarIdx_b = 1;
+    private Allocation[] mExportVar_b;
+    public synchronized void set_b(Allocation[] v) {
+        mExportVar_b = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 320 : 40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addObj(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_b, fp, __ALLOCATION, __dimArr);
+    }
+
+    public Allocation[] get_b() {
+        return mExportVar_b;
+    }
+
+    public Script.FieldID getFieldID_b() {
+        return createFieldID(mExportVarIdx_b, null);
+    }
+
+    private final static int mExportFuncIdx_f = 0;
+    public Script.InvokeID getInvokeID_f() {
+        return createInvokeID(mExportFuncIdx_f);
+    }
+
+    public void invoke_f(int c, Allocation d, int e) {
+        FieldPacker f_fp = new FieldPacker(sIs64Bit ? 48 : 12);
+        f_fp.addI32(c);
+        f_fp.skip(sIs64Bit ? 4 : 0);
+        f_fp.addObj(d);
+        f_fp.addI32(e);
+        f_fp.skip(sIs64Bit ? 4 : 0);
+        invoke(mExportFuncIdx_f, f_fp);
+    }
+
+    private static boolean sIs64Bit;
+
+    static {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            sIs64Bit = Process.is64Bit();
+        }
+
+        else {
+            try {
+                Field f = RenderScript.class.getDeclaredField("sPointerSize");
+                f.setAccessible(true);
+                sIs64Bit = (f.getInt(null) == 8);
+            }
+
+            catch (Throwable e) {
+                sIs64Bit = false;
+            }
+
+        }
+
+    }
+
+}
+
diff --git a/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_2.java.expect b/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_2.java.expect
new file mode 100644
index 0000000..4464559
--- /dev/null
+++ b/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_2.java.expect
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_multifile_2.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_multifile_2BitCode;
+
+/**
+ * @hide
+ */
+public class ScriptC_reflection3264_multifile_2 extends ScriptC {
+    private static final String __rs_resource_name = "reflection3264_multifile_2";
+    // Constructor
+    public  ScriptC_reflection3264_multifile_2(RenderScript rs) {
+        super(rs,
+              __rs_resource_name,
+              reflection3264_multifile_2BitCode.getBitCode32(),
+              reflection3264_multifile_2BitCode.getBitCode64());
+        __I16 = Element.I16(rs);
+        __I64 = Element.I64(rs);
+    }
+
+    private Element __I16;
+    private Element __I64;
+    private FieldPacker __rs_fp_I16;
+    private FieldPacker __rs_fp_I64;
+    private final static int mExportVarIdx_a = 0;
+    private short[] mExportVar_a;
+    public synchronized void set_a(short[] v) {
+        mExportVar_a = v;
+        FieldPacker fp = new FieldPacker(20);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI16(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_a, fp, __I16, __dimArr);
+    }
+
+    public short[] get_a() {
+        return mExportVar_a;
+    }
+
+    public Script.FieldID getFieldID_a() {
+        return createFieldID(mExportVarIdx_a, null);
+    }
+
+    private final static int mExportVarIdx_b = 1;
+    private long[] mExportVar_b;
+    public synchronized void set_b(long[] v) {
+        mExportVar_b = v;
+        FieldPacker fp = new FieldPacker(80);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI64(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_b, fp, __I64, __dimArr);
+    }
+
+    public long[] get_b() {
+        return mExportVar_b;
+    }
+
+    public Script.FieldID getFieldID_b() {
+        return createFieldID(mExportVarIdx_b, null);
+    }
+
+    private final static int mExportFuncIdx_g = 0;
+    public Script.InvokeID getInvokeID_g() {
+        return createInvokeID(mExportFuncIdx_g);
+    }
+
+    public void invoke_g(int c) {
+        FieldPacker g_fp = new FieldPacker(4);
+        g_fp.addI32(c);
+        invoke(mExportFuncIdx_g, g_fp);
+    }
+
+}
+
diff --git a/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_3.java.expect b/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_3.java.expect
new file mode 100644
index 0000000..7740bb5
--- /dev/null
+++ b/tests/P_reflection3264_multifile/ScriptC_reflection3264_multifile_3.java.expect
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011-2014 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.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: reflection3264_multifile_3.rs
+ */
+
+package foo;
+
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
+import android.renderscript.*;
+import foo.reflection3264_multifile_3BitCode;
+
+/**
+ * @hide
+ */
+public class ScriptC_reflection3264_multifile_3 extends ScriptC {
+    private static final String __rs_resource_name = "reflection3264_multifile_3";
+    // Constructor
+    public  ScriptC_reflection3264_multifile_3(RenderScript rs) {
+        super(rs,
+              __rs_resource_name,
+              reflection3264_multifile_3BitCode.getBitCode32(),
+              reflection3264_multifile_3BitCode.getBitCode64());
+        __ALLOCATION = Element.ALLOCATION(rs);
+        __I32 = Element.I32(rs);
+    }
+
+    private Element __ALLOCATION;
+    private Element __I32;
+    private FieldPacker __rs_fp_ALLOCATION;
+    private FieldPacker __rs_fp_I32;
+    private final static int mExportVarIdx_a = 0;
+    private Allocation[] mExportVar_a;
+    public synchronized void set_a(Allocation[] v) {
+        mExportVar_a = v;
+        FieldPacker fp = new FieldPacker(sIs64Bit ? 320 : 40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addObj(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_a, fp, __ALLOCATION, __dimArr);
+    }
+
+    public Allocation[] get_a() {
+        return mExportVar_a;
+    }
+
+    public Script.FieldID getFieldID_a() {
+        return createFieldID(mExportVarIdx_a, null);
+    }
+
+    private final static int mExportVarIdx_b = 1;
+    private int[] mExportVar_b;
+    public synchronized void set_b(int[] v) {
+        mExportVar_b = v;
+        FieldPacker fp = new FieldPacker(40);
+        for (int ct1 = 0; ct1 < 10; ct1++) {
+            fp.addI32(v[ct1]);
+        }
+
+        int []__dimArr = new int[1];
+        __dimArr[0] = 10;
+        setVar(mExportVarIdx_b, fp, __I32, __dimArr);
+    }
+
+    public int[] get_b() {
+        return mExportVar_b;
+    }
+
+    public Script.FieldID getFieldID_b() {
+        return createFieldID(mExportVarIdx_b, null);
+    }
+
+    private final static int mExportFuncIdx_h = 0;
+    public Script.InvokeID getInvokeID_h() {
+        return createInvokeID(mExportFuncIdx_h);
+    }
+
+    public void invoke_h(Allocation c, int d, Allocation e) {
+        FieldPacker h_fp = new FieldPacker(sIs64Bit ? 72 : 12);
+        h_fp.addObj(c);
+        h_fp.addI32(d);
+        h_fp.skip(sIs64Bit ? 4 : 0);
+        h_fp.addObj(e);
+        invoke(mExportFuncIdx_h, h_fp);
+    }
+
+    private static boolean sIs64Bit;
+
+    static {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            sIs64Bit = Process.is64Bit();
+        }
+
+        else {
+            try {
+                Field f = RenderScript.class.getDeclaredField("sPointerSize");
+                f.setAccessible(true);
+                sIs64Bit = (f.getInt(null) == 8);
+            }
+
+            catch (Throwable e) {
+                sIs64Bit = false;
+            }
+
+        }
+
+    }
+
+}
+
diff --git a/tests/P_reflection3264_multifile/reflection3264_multifile_1.rs b/tests/P_reflection3264_multifile/reflection3264_multifile_1.rs
new file mode 100644
index 0000000..c8bcd16
--- /dev/null
+++ b/tests/P_reflection3264_multifile/reflection3264_multifile_1.rs
@@ -0,0 +1,7 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+int a[10];
+rs_allocation b[10];
+
+void f(int c, rs_allocation d, int e) { }
diff --git a/tests/P_reflection3264_multifile/reflection3264_multifile_2.rs b/tests/P_reflection3264_multifile/reflection3264_multifile_2.rs
new file mode 100644
index 0000000..2b54e08
--- /dev/null
+++ b/tests/P_reflection3264_multifile/reflection3264_multifile_2.rs
@@ -0,0 +1,10 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+// no 32-bit versus 64-bit differences
+
+short a[10];
+long b[10];
+
+void g(int c) { }
+
diff --git a/tests/P_reflection3264_multifile/reflection3264_multifile_3.rs b/tests/P_reflection3264_multifile/reflection3264_multifile_3.rs
new file mode 100644
index 0000000..2a9785b
--- /dev/null
+++ b/tests/P_reflection3264_multifile/reflection3264_multifile_3.rs
@@ -0,0 +1,7 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+rs_allocation a[10];
+int b[10];
+
+void h(rs_allocation c, int d, rs_allocation e) { }
diff --git a/tests/P_reflection3264_multifile/stderr.txt.expect b/tests/P_reflection3264_multifile/stderr.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_reflection3264_multifile/stderr.txt.expect
diff --git a/tests/P_reflection3264_multifile/stdout.txt.expect b/tests/P_reflection3264_multifile/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_reflection3264_multifile/stdout.txt.expect
diff --git a/tests/P_struct_field/ScriptC_struct_field.java.expect b/tests/P_struct_field/ScriptC_struct_field.java.expect
index 2134315..9729da8 100644
--- a/tests/P_struct_field/ScriptC_struct_field.java.expect
+++ b/tests/P_struct_field/ScriptC_struct_field.java.expect
@@ -21,6 +21,9 @@
 
 package struct_field;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import struct_field.struct_fieldBitCode;
 
diff --git a/tests/P_struct_field/ScriptField_InnerOne.java.expect b/tests/P_struct_field/ScriptField_InnerOne.java.expect
index 54bcafe..8ceea0a 100644
--- a/tests/P_struct_field/ScriptField_InnerOne.java.expect
+++ b/tests/P_struct_field/ScriptField_InnerOne.java.expect
@@ -21,6 +21,9 @@
 
 package struct_field;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import struct_field.struct_fieldBitCode;
 
diff --git a/tests/P_struct_field/ScriptField_InnerTwo.java.expect b/tests/P_struct_field/ScriptField_InnerTwo.java.expect
index da7c768..f28d9cd 100644
--- a/tests/P_struct_field/ScriptField_InnerTwo.java.expect
+++ b/tests/P_struct_field/ScriptField_InnerTwo.java.expect
@@ -21,6 +21,9 @@
 
 package struct_field;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import struct_field.struct_fieldBitCode;
 
diff --git a/tests/P_struct_field/ScriptField_Outer.java.expect b/tests/P_struct_field/ScriptField_Outer.java.expect
index 6ee82e8..7d9b5c7 100644
--- a/tests/P_struct_field/ScriptField_Outer.java.expect
+++ b/tests/P_struct_field/ScriptField_Outer.java.expect
@@ -21,6 +21,9 @@
 
 package struct_field;
 
+import android.os.Build;
+import android.os.Process;
+import java.lang.reflect.Field;
 import android.renderscript.*;
 import struct_field.struct_fieldBitCode;