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 ¶ms = 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;