Home | History | Annotate | Download | only in slang
      1 
      2 /*
      3  * Copyright 2010-2014, The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include "slang_rs_reflection.h"
     19 
     20 #include <sys/stat.h>
     21 
     22 #include <cstdarg>
     23 #include <cctype>
     24 
     25 #include <algorithm>
     26 #include <sstream>
     27 #include <string>
     28 #include <utility>
     29 
     30 #include "llvm/ADT/APFloat.h"
     31 #include "llvm/ADT/StringExtras.h"
     32 
     33 #include "os_sep.h"
     34 #include "slang_rs_context.h"
     35 #include "slang_rs_export_var.h"
     36 #include "slang_rs_export_foreach.h"
     37 #include "slang_rs_export_func.h"
     38 #include "slang_rs_reflect_utils.h"
     39 #include "slang_version.h"
     40 
     41 #define RS_SCRIPT_CLASS_NAME_PREFIX "ScriptC_"
     42 #define RS_SCRIPT_CLASS_SUPER_CLASS_NAME "ScriptC"
     43 
     44 #define RS_TYPE_CLASS_SUPER_CLASS_NAME ".Script.FieldBase"
     45 
     46 #define RS_TYPE_ITEM_CLASS_NAME "Item"
     47 
     48 #define RS_TYPE_ITEM_SIZEOF_LEGACY "Item.sizeof"
     49 #define RS_TYPE_ITEM_SIZEOF_CURRENT "mElement.getBytesSize()"
     50 
     51 #define RS_TYPE_ITEM_BUFFER_NAME "mItemArray"
     52 #define RS_TYPE_ITEM_BUFFER_PACKER_NAME "mIOBuffer"
     53 #define RS_TYPE_ELEMENT_REF_NAME "mElementCache"
     54 
     55 #define RS_EXPORT_VAR_INDEX_PREFIX "mExportVarIdx_"
     56 #define RS_EXPORT_VAR_PREFIX "mExportVar_"
     57 #define RS_EXPORT_VAR_ELEM_PREFIX "mExportVarElem_"
     58 #define RS_EXPORT_VAR_DIM_PREFIX "mExportVarDim_"
     59 #define RS_EXPORT_VAR_CONST_PREFIX "const_"
     60 
     61 #define RS_ELEM_PREFIX "__"
     62 
     63 #define RS_FP_PREFIX "__rs_fp_"
     64 
     65 #define RS_RESOURCE_NAME "__rs_resource_name"
     66 
     67 #define RS_EXPORT_FUNC_INDEX_PREFIX "mExportFuncIdx_"
     68 #define RS_EXPORT_FOREACH_INDEX_PREFIX "mExportForEachIdx_"
     69 
     70 #define RS_EXPORT_VAR_ALLOCATION_PREFIX "mAlloction_"
     71 #define RS_EXPORT_VAR_DATA_STORAGE_PREFIX "mData_"
     72 
     73 namespace slang {
     74 
     75 class RSReflectionJavaElementBuilder {
     76 public:
     77   RSReflectionJavaElementBuilder(const char *ElementBuilderName,
     78                                  const RSExportRecordType *ERT,
     79                                  const char *RenderScriptVar,
     80                                  GeneratedFile *Out, const RSContext *RSContext,
     81                                  RSReflectionJava *Reflection);
     82   void generate();
     83 
     84 private:
     85   void genAddElement(const RSExportType *ET, const std::string &VarName,
     86                      unsigned ArraySize);
     87   void genAddStatementStart();
     88   void genAddStatementEnd(const std::string &VarName, unsigned ArraySize);
     89   void genAddPadding(int PaddingSize);
     90   // TODO Will remove later due to field name information is not necessary for
     91   // C-reflect-to-Java
     92   std::string createPaddingField() {
     93     return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++);
     94   }
     95 
     96   const char *mElementBuilderName;
     97   const RSExportRecordType *mERT;
     98   const char *mRenderScriptVar;
     99   GeneratedFile *mOut;
    100   std::string mPaddingPrefix;
    101   int mPaddingFieldIndex;
    102   const RSContext *mRSContext;
    103   RSReflectionJava *mReflection;
    104 };
    105 
    106 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
    107   static const char *MatrixTypeJavaNameMap[] = {/* 2x2 */ "Matrix2f",
    108                                                 /* 3x3 */ "Matrix3f",
    109                                                 /* 4x4 */ "Matrix4f",
    110   };
    111   unsigned Dim = EMT->getDim();
    112 
    113   if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char *)))
    114     return MatrixTypeJavaNameMap[EMT->getDim() - 2];
    115 
    116   slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
    117   return nullptr;
    118 }
    119 
    120 static const char *GetVectorAccessor(unsigned Index) {
    121   static const char *VectorAccessorMap[] = {/* 0 */ "x",
    122                                             /* 1 */ "y",
    123                                             /* 2 */ "z",
    124                                             /* 3 */ "w",
    125   };
    126 
    127   slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
    128               "Out-of-bound index to access vector member");
    129 
    130   return VectorAccessorMap[Index];
    131 }
    132 
    133 static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) {
    134   static const char *PrimitiveTypePackerAPINameMap[] = {
    135       "addF16",     // DataTypeFloat16
    136       "addF32",     // DataTypeFloat32
    137       "addF64",     // DataTypeFloat64
    138       "addI8",      // DataTypeSigned8
    139       "addI16",     // DataTypeSigned16
    140       "addI32",     // DataTypeSigned32
    141       "addI64",     // DataTypeSigned64
    142       "addU8",      // DataTypeUnsigned8
    143       "addU16",     // DataTypeUnsigned16
    144       "addU32",     // DataTypeUnsigned32
    145       "addU64",     // DataTypeUnsigned64
    146       "addBoolean", // DataTypeBoolean
    147       "addU16",     // DataTypeUnsigned565
    148       "addU16",     // DataTypeUnsigned5551
    149       "addU16",     // DataTypeUnsigned4444
    150       "addMatrix",  // DataTypeRSMatrix2x2
    151       "addMatrix",  // DataTypeRSMatrix3x3
    152       "addMatrix",  // DataTypeRSMatrix4x4
    153       "addObj",     // DataTypeRSElement
    154       "addObj",     // DataTypeRSType
    155       "addObj",     // DataTypeRSAllocation
    156       "addObj",     // DataTypeRSSampler
    157       "addObj",     // DataTypeRSScript
    158       "addObj",     // DataTypeRSMesh
    159       "addObj",     // DataTypeRSPath
    160       "addObj",     // DataTypeRSProgramFragment
    161       "addObj",     // DataTypeRSProgramVertex
    162       "addObj",     // DataTypeRSProgramRaster
    163       "addObj",     // DataTypeRSProgramStore
    164       "addObj",     // DataTypeRSFont
    165   };
    166   unsigned TypeId = EPT->getType();
    167 
    168   if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char *)))
    169     return PrimitiveTypePackerAPINameMap[EPT->getType()];
    170 
    171   slangAssert(false && "GetPackerAPIName : Unknown primitive data type");
    172   return nullptr;
    173 }
    174 
    175 static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
    176   switch (ET->getClass()) {
    177   case RSExportType::ExportClassPrimitive: {
    178     return RSExportPrimitiveType::getRSReflectionType(
    179                static_cast<const RSExportPrimitiveType *>(ET))->java_name;
    180   }
    181   case RSExportType::ExportClassPointer: {
    182     const RSExportType *PointeeType =
    183         static_cast<const RSExportPointerType *>(ET)->getPointeeType();
    184 
    185     if (PointeeType->getClass() != RSExportType::ExportClassRecord)
    186       return "Allocation";
    187     else
    188       return PointeeType->getElementName();
    189   }
    190   case RSExportType::ExportClassVector: {
    191     const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
    192     std::stringstream VecName;
    193     VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix
    194             << EVT->getNumElement();
    195     return VecName.str();
    196   }
    197   case RSExportType::ExportClassMatrix: {
    198     return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
    199   }
    200   case RSExportType::ExportClassConstantArray: {
    201     const RSExportConstantArrayType *CAT =
    202         static_cast<const RSExportConstantArrayType *>(ET);
    203     std::string ElementTypeName = GetTypeName(CAT->getElementType());
    204     if (Brackets) {
    205       ElementTypeName.append("[]");
    206     }
    207     return ElementTypeName;
    208   }
    209   case RSExportType::ExportClassRecord: {
    210     return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
    211   }
    212   default: { slangAssert(false && "Unknown class of type"); }
    213   }
    214 
    215   return "";
    216 }
    217 
    218 static const char *GetTypeNullValue(const RSExportType *ET) {
    219   switch (ET->getClass()) {
    220   case RSExportType::ExportClassPrimitive: {
    221     const RSExportPrimitiveType *EPT =
    222         static_cast<const RSExportPrimitiveType *>(ET);
    223     if (EPT->isRSObjectType())
    224       return "null";
    225     else if (EPT->getType() == DataTypeBoolean)
    226       return "false";
    227     else
    228       return "0";
    229     break;
    230   }
    231   case RSExportType::ExportClassPointer:
    232   case RSExportType::ExportClassVector:
    233   case RSExportType::ExportClassMatrix:
    234   case RSExportType::ExportClassConstantArray:
    235   case RSExportType::ExportClassRecord: {
    236     return "null";
    237     break;
    238   }
    239   default: { slangAssert(false && "Unknown class of type"); }
    240   }
    241   return "";
    242 }
    243 
    244 static std::string GetBuiltinElementConstruct(const RSExportType *ET) {
    245   if (ET->getClass() == RSExportType::ExportClassPrimitive) {
    246     return std::string("Element.") + ET->getElementName();
    247   } else if (ET->getClass() == RSExportType::ExportClassVector) {
    248     const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
    249     if (EVT->getType() == DataTypeFloat32) {
    250       if (EVT->getNumElement() == 2) {
    251         return "Element.F32_2";
    252       } else if (EVT->getNumElement() == 3) {
    253         return "Element.F32_3";
    254       } else if (EVT->getNumElement() == 4) {
    255         return "Element.F32_4";
    256       } else {
    257         slangAssert(false && "Vectors should be size 2, 3, 4");
    258       }
    259     } else if (EVT->getType() == DataTypeUnsigned8) {
    260       if (EVT->getNumElement() == 4)
    261         return "Element.U8_4";
    262     }
    263   } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
    264     const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType *>(ET);
    265     switch (EMT->getDim()) {
    266     case 2:
    267       return "Element.MATRIX_2X2";
    268     case 3:
    269       return "Element.MATRIX_3X3";
    270     case 4:
    271       return "Element.MATRIX_4X4";
    272     default:
    273       slangAssert(false && "Unsupported dimension of matrix");
    274     }
    275   }
    276   // RSExportType::ExportClassPointer can't be generated in a struct.
    277 
    278   return "";
    279 }
    280 
    281 /********************** Methods to generate script class **********************/
    282 RSReflectionJava::RSReflectionJava(const RSContext *Context,
    283                                    std::vector<std::string> *GeneratedFileNames,
    284                                    const std::string &OutputBaseDirectory,
    285                                    const std::string &RSSourceFileName,
    286                                    const std::string &BitCodeFileName,
    287                                    bool EmbedBitcodeInJava)
    288     : mRSContext(Context), mPackageName(Context->getReflectJavaPackageName()),
    289       mRSPackageName(Context->getRSPackageName()),
    290       mOutputBaseDirectory(OutputBaseDirectory),
    291       mRSSourceFileName(RSSourceFileName), mBitCodeFileName(BitCodeFileName),
    292       mResourceId(RSSlangReflectUtils::JavaClassNameFromRSFileName(
    293           mBitCodeFileName.c_str())),
    294       mScriptClassName(RS_SCRIPT_CLASS_NAME_PREFIX +
    295                        RSSlangReflectUtils::JavaClassNameFromRSFileName(
    296                            mRSSourceFileName.c_str())),
    297       mEmbedBitcodeInJava(EmbedBitcodeInJava), mNextExportVarSlot(0),
    298       mNextExportFuncSlot(0), mNextExportForEachSlot(0), mLastError(""),
    299       mGeneratedFileNames(GeneratedFileNames), mFieldIndex(0) {
    300   slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames");
    301   slangAssert(!mPackageName.empty() && mPackageName != "-");
    302 
    303   mOutputDirectory = RSSlangReflectUtils::ComputePackagedPath(
    304                          OutputBaseDirectory.c_str(), mPackageName.c_str()) +
    305                      OS_PATH_SEPARATOR_STR;
    306 
    307   // mElement.getBytesSize only exists on JB+
    308   if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) {
    309       mItemSizeof = RS_TYPE_ITEM_SIZEOF_CURRENT;
    310   } else {
    311       mItemSizeof = RS_TYPE_ITEM_SIZEOF_LEGACY;
    312   }
    313 }
    314 
    315 bool RSReflectionJava::genScriptClass(const std::string &ClassName,
    316                                       std::string &ErrorMsg) {
    317   if (!startClass(AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
    318                   ErrorMsg))
    319     return false;
    320 
    321   genScriptClassConstructor();
    322 
    323   // Reflect export variable
    324   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    325                                             E = mRSContext->export_vars_end();
    326        I != E; I++)
    327     genExportVariable(*I);
    328 
    329   // Reflect export for each functions (only available on ICS+)
    330   if (mRSContext->getTargetAPI() >= SLANG_ICS_TARGET_API) {
    331     for (RSContext::const_export_foreach_iterator
    332              I = mRSContext->export_foreach_begin(),
    333              E = mRSContext->export_foreach_end();
    334          I != E; I++)
    335       genExportForEach(*I);
    336   }
    337 
    338   // Reflect export function
    339   for (RSContext::const_export_func_iterator
    340            I = mRSContext->export_funcs_begin(),
    341            E = mRSContext->export_funcs_end();
    342        I != E; I++)
    343     genExportFunction(*I);
    344 
    345   endClass();
    346 
    347   return true;
    348 }
    349 
    350 void RSReflectionJava::genScriptClassConstructor() {
    351   std::string className(RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName(
    352       mRSSourceFileName.c_str()));
    353   // Provide a simple way to reference this object.
    354   mOut.indent() << "private static final String " RS_RESOURCE_NAME " = \""
    355                 << getResourceId() << "\";\n";
    356 
    357   // Generate a simple constructor with only a single parameter (the rest
    358   // can be inferred from information we already have).
    359   mOut.indent() << "// Constructor\n";
    360   startFunction(AM_Public, false, nullptr, getClassName(), 1, "RenderScript",
    361                 "rs");
    362 
    363   if (getEmbedBitcodeInJava()) {
    364     // Call new single argument Java-only constructor
    365     mOut.indent() << "super(rs,\n";
    366     mOut.indent() << "      " << RS_RESOURCE_NAME ",\n";
    367     mOut.indent() << "      " << className << ".getBitCode32(),\n";
    368     mOut.indent() << "      " << className << ".getBitCode64());\n";
    369   } else {
    370     // Call alternate constructor with required parameters.
    371     // Look up the proper raw bitcode resource id via the context.
    372     mOut.indent() << "this(rs,\n";
    373     mOut.indent() << "     rs.getApplicationContext().getResources(),\n";
    374     mOut.indent() << "     rs.getApplicationContext().getResources()."
    375                      "getIdentifier(\n";
    376     mOut.indent() << "         " RS_RESOURCE_NAME ", \"raw\",\n";
    377     mOut.indent()
    378         << "         rs.getApplicationContext().getPackageName()));\n";
    379     endFunction();
    380 
    381     // Alternate constructor (legacy) with 3 original parameters.
    382     startFunction(AM_Public, false, nullptr, getClassName(), 3, "RenderScript",
    383                   "rs", "Resources", "resources", "int", "id");
    384     // Call constructor of super class
    385     mOut.indent() << "super(rs, resources, id);\n";
    386   }
    387 
    388   // If an exported variable has initial value, reflect it
    389 
    390   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    391                                             E = mRSContext->export_vars_end();
    392        I != E; I++) {
    393     const RSExportVar *EV = *I;
    394     if (!EV->getInit().isUninit()) {
    395       genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
    396     } else if (EV->getArraySize()) {
    397       // Always create an initial zero-init array object.
    398       mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = new "
    399                     << GetTypeName(EV->getType(), false) << "["
    400                     << EV->getArraySize() << "];\n";
    401       size_t NumInits = EV->getNumInits();
    402       const RSExportConstantArrayType *ECAT =
    403           static_cast<const RSExportConstantArrayType *>(EV->getType());
    404       const RSExportType *ET = ECAT->getElementType();
    405       for (size_t i = 0; i < NumInits; i++) {
    406         std::stringstream Name;
    407         Name << EV->getName() << "[" << i << "]";
    408         genInitExportVariable(ET, Name.str(), EV->getInitArray(i));
    409       }
    410     }
    411     if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) {
    412       genTypeInstance(EV->getType());
    413     }
    414     genFieldPackerInstance(EV->getType());
    415   }
    416 
    417   for (RSContext::const_export_foreach_iterator
    418            I = mRSContext->export_foreach_begin(),
    419            E = mRSContext->export_foreach_end();
    420        I != E; I++) {
    421     const RSExportForEach *EF = *I;
    422 
    423     const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
    424     for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
    425          BI != EI; BI++) {
    426 
    427       if (*BI != nullptr) {
    428         genTypeInstanceFromPointer(*BI);
    429       }
    430     }
    431 
    432     const RSExportType *OET = EF->getOutType();
    433     if (OET) {
    434       genTypeInstanceFromPointer(OET);
    435     }
    436   }
    437 
    438   endFunction();
    439 
    440   for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
    441                                        E = mTypesToCheck.end();
    442        I != E; I++) {
    443     mOut.indent() << "private Element " RS_ELEM_PREFIX << *I << ";\n";
    444   }
    445 
    446   for (std::set<std::string>::iterator I = mFieldPackerTypes.begin(),
    447                                        E = mFieldPackerTypes.end();
    448        I != E; I++) {
    449     mOut.indent() << "private FieldPacker " RS_FP_PREFIX << *I << ";\n";
    450   }
    451 }
    452 
    453 void RSReflectionJava::genInitBoolExportVariable(const std::string &VarName,
    454                                                  const clang::APValue &Val) {
    455   slangAssert(!Val.isUninit() && "Not a valid initializer");
    456   slangAssert((Val.getKind() == clang::APValue::Int) &&
    457               "Bool type has wrong initial APValue");
    458 
    459   mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
    460 
    461   mOut << ((Val.getInt().getSExtValue() == 0) ? "false" : "true") << ";\n";
    462 }
    463 
    464 void
    465 RSReflectionJava::genInitPrimitiveExportVariable(const std::string &VarName,
    466                                                  const clang::APValue &Val) {
    467   slangAssert(!Val.isUninit() && "Not a valid initializer");
    468 
    469   mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
    470   genInitValue(Val, false);
    471   mOut << ";\n";
    472 }
    473 
    474 void RSReflectionJava::genInitExportVariable(const RSExportType *ET,
    475                                              const std::string &VarName,
    476                                              const clang::APValue &Val) {
    477   slangAssert(!Val.isUninit() && "Not a valid initializer");
    478 
    479   switch (ET->getClass()) {
    480   case RSExportType::ExportClassPrimitive: {
    481     const RSExportPrimitiveType *EPT =
    482         static_cast<const RSExportPrimitiveType *>(ET);
    483     if (EPT->getType() == DataTypeBoolean) {
    484       genInitBoolExportVariable(VarName, Val);
    485     } else {
    486       genInitPrimitiveExportVariable(VarName, Val);
    487     }
    488     break;
    489   }
    490   case RSExportType::ExportClassPointer: {
    491     if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
    492       std::cout << "Initializer which is non-NULL to pointer type variable "
    493                    "will be ignored\n";
    494     break;
    495   }
    496   case RSExportType::ExportClassVector: {
    497     const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
    498     switch (Val.getKind()) {
    499     case clang::APValue::Int:
    500     case clang::APValue::Float: {
    501       for (unsigned i = 0; i < EVT->getNumElement(); i++) {
    502         std::string Name = VarName + "." + GetVectorAccessor(i);
    503         genInitPrimitiveExportVariable(Name, Val);
    504       }
    505       break;
    506     }
    507     case clang::APValue::Vector: {
    508       std::stringstream VecName;
    509       VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix
    510               << EVT->getNumElement();
    511       mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "
    512                     << VecName.str() << "();\n";
    513 
    514       unsigned NumElements = std::min(
    515           static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
    516       for (unsigned i = 0; i < NumElements; i++) {
    517         const clang::APValue &ElementVal = Val.getVectorElt(i);
    518         std::string Name = VarName + "." + GetVectorAccessor(i);
    519         genInitPrimitiveExportVariable(Name, ElementVal);
    520       }
    521       break;
    522     }
    523     case clang::APValue::MemberPointer:
    524     case clang::APValue::Uninitialized:
    525     case clang::APValue::ComplexInt:
    526     case clang::APValue::ComplexFloat:
    527     case clang::APValue::LValue:
    528     case clang::APValue::Array:
    529     case clang::APValue::Struct:
    530     case clang::APValue::Union:
    531     case clang::APValue::AddrLabelDiff: {
    532       slangAssert(false && "Unexpected type of value of initializer.");
    533     }
    534     }
    535     break;
    536   }
    537   // TODO(zonr): Resolving initializer of a record (and matrix) type variable
    538   // is complex. It cannot obtain by just simply evaluating the initializer
    539   // expression.
    540   case RSExportType::ExportClassMatrix:
    541   case RSExportType::ExportClassConstantArray:
    542   case RSExportType::ExportClassRecord: {
    543 #if 0
    544       unsigned InitIndex = 0;
    545       const RSExportRecordType *ERT =
    546           static_cast<const RSExportRecordType*>(ET);
    547 
    548       slangAssert((Val.getKind() == clang::APValue::Vector) &&
    549           "Unexpected type of initializer for record type variable");
    550 
    551       mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName
    552                  << " = new " << ERT->getElementName()
    553                  <<  "." RS_TYPE_ITEM_CLASS_NAME"();\n";
    554 
    555       for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
    556                E = ERT->fields_end();
    557            I != E;
    558            I++) {
    559         const RSExportRecordType::Field *F = *I;
    560         std::string FieldName = VarName + "." + F->getName();
    561 
    562         if (InitIndex > Val.getVectorLength())
    563           break;
    564 
    565         genInitPrimitiveExportVariable(FieldName,
    566                                        Val.getVectorElt(InitIndex++));
    567       }
    568 #endif
    569     slangAssert(false && "Unsupported initializer for record/matrix/constant "
    570                          "array type variable currently");
    571     break;
    572   }
    573   default: { slangAssert(false && "Unknown class of type"); }
    574   }
    575 }
    576 
    577 void RSReflectionJava::genExportVariable(const RSExportVar *EV) {
    578   const RSExportType *ET = EV->getType();
    579 
    580   mOut.indent() << "private final static int " << RS_EXPORT_VAR_INDEX_PREFIX
    581                 << EV->getName() << " = " << getNextExportVarSlot() << ";\n";
    582 
    583   switch (ET->getClass()) {
    584   case RSExportType::ExportClassPrimitive: {
    585     genPrimitiveTypeExportVariable(EV);
    586     break;
    587   }
    588   case RSExportType::ExportClassPointer: {
    589     genPointerTypeExportVariable(EV);
    590     break;
    591   }
    592   case RSExportType::ExportClassVector: {
    593     genVectorTypeExportVariable(EV);
    594     break;
    595   }
    596   case RSExportType::ExportClassMatrix: {
    597     genMatrixTypeExportVariable(EV);
    598     break;
    599   }
    600   case RSExportType::ExportClassConstantArray: {
    601     genConstantArrayTypeExportVariable(EV);
    602     break;
    603   }
    604   case RSExportType::ExportClassRecord: {
    605     genRecordTypeExportVariable(EV);
    606     break;
    607   }
    608   default: { slangAssert(false && "Unknown class of type"); }
    609   }
    610 }
    611 
    612 void RSReflectionJava::genExportFunction(const RSExportFunc *EF) {
    613   mOut.indent() << "private final static int " << RS_EXPORT_FUNC_INDEX_PREFIX
    614                 << EF->getName() << " = " << getNextExportFuncSlot() << ";\n";
    615 
    616   // invoke_*()
    617   ArgTy Args;
    618 
    619   if (EF->hasParam()) {
    620     for (RSExportFunc::const_param_iterator I = EF->params_begin(),
    621                                             E = EF->params_end();
    622          I != E; I++) {
    623       Args.push_back(
    624           std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
    625     }
    626   }
    627 
    628   if (mRSContext->getTargetAPI() >= SLANG_M_TARGET_API) {
    629     startFunction(AM_Public, false, "Script.InvokeID",
    630                   "getInvokeID_" + EF->getName(), 0);
    631 
    632     mOut.indent() << "return createInvokeID(" << RS_EXPORT_FUNC_INDEX_PREFIX
    633                   << EF->getName() << ");\n";
    634 
    635     endFunction();
    636   }
    637 
    638   startFunction(AM_Public, false, "void",
    639                 "invoke_" + EF->getName(/*Mangle=*/false),
    640                 // We are using un-mangled name since Java
    641                 // supports method overloading.
    642                 Args);
    643 
    644   if (!EF->hasParam()) {
    645     mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
    646                   << ");\n";
    647   } else {
    648     const RSExportRecordType *ERT = EF->getParamPacketType();
    649     std::string FieldPackerName = EF->getName() + "_fp";
    650 
    651     if (genCreateFieldPacker(ERT, FieldPackerName.c_str()))
    652       genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
    653 
    654     mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
    655                   << ", " << FieldPackerName << ");\n";
    656   }
    657 
    658   endFunction();
    659 }
    660 
    661 void RSReflectionJava::genPairwiseDimCheck(std::string name0,
    662                                            std::string name1) {
    663 
    664   mOut.indent() << "// Verify dimensions\n";
    665   mOut.indent() << "t0 = " << name0 << ".getType();\n";
    666   mOut.indent() << "t1 = " << name1 << ".getType();\n";
    667   mOut.indent() << "if ((t0.getCount() != t1.getCount()) ||\n";
    668   mOut.indent() << "    (t0.getX() != t1.getX()) ||\n";
    669   mOut.indent() << "    (t0.getY() != t1.getY()) ||\n";
    670   mOut.indent() << "    (t0.getZ() != t1.getZ()) ||\n";
    671   mOut.indent() << "    (t0.hasFaces()   != t1.hasFaces()) ||\n";
    672   mOut.indent() << "    (t0.hasMipmaps() != t1.hasMipmaps())) {\n";
    673   mOut.indent() << "    throw new RSRuntimeException(\"Dimension mismatch "
    674                 << "between parameters " << name0 << " and " << name1
    675                 << "!\");\n";
    676   mOut.indent() << "}\n\n";
    677 }
    678 
    679 void RSReflectionJava::genExportForEach(const RSExportForEach *EF) {
    680   if (EF->isDummyRoot()) {
    681     // Skip reflection for dummy root() kernels. Note that we have to
    682     // advance the next slot number for ForEach, however.
    683     mOut.indent() << "//private final static int "
    684                   << RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName() << " = "
    685                   << getNextExportForEachSlot() << ";\n";
    686     return;
    687   }
    688 
    689   mOut.indent() << "private final static int " << RS_EXPORT_FOREACH_INDEX_PREFIX
    690                 << EF->getName() << " = " << getNextExportForEachSlot()
    691                 << ";\n";
    692 
    693   // forEach_*()
    694   ArgTy Args;
    695   bool HasAllocation = false; // at least one in/out allocation?
    696 
    697   const RSExportForEach::InVec     &Ins     = EF->getIns();
    698   const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
    699   const RSExportType               *OET     = EF->getOutType();
    700 
    701   if (Ins.size() == 1) {
    702     HasAllocation = true;
    703     Args.push_back(std::make_pair("Allocation", "ain"));
    704 
    705   } else if (Ins.size() > 1) {
    706     HasAllocation = true;
    707     for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
    708          BI++) {
    709 
    710       Args.push_back(std::make_pair("Allocation",
    711                                     "ain_" + (*BI)->getName().str()));
    712     }
    713   }
    714 
    715   if (EF->hasOut() || EF->hasReturn()) {
    716     HasAllocation = true;
    717     Args.push_back(std::make_pair("Allocation", "aout"));
    718   }
    719 
    720   const RSExportRecordType *ERT = EF->getParamPacketType();
    721   if (ERT) {
    722     for (RSExportForEach::const_param_iterator I = EF->params_begin(),
    723                                                E = EF->params_end();
    724          I != E; I++) {
    725       Args.push_back(
    726           std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
    727     }
    728   }
    729 
    730   if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
    731     startFunction(AM_Public, false, "Script.KernelID",
    732                   "getKernelID_" + EF->getName(), 0);
    733 
    734     // TODO: add element checking
    735     mOut.indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX
    736                   << EF->getName() << ", " << EF->getSignatureMetadata()
    737                   << ", null, null);\n";
    738 
    739     endFunction();
    740   }
    741 
    742   if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) {
    743     if (HasAllocation) {
    744       startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
    745 
    746       mOut.indent() << "forEach_" << EF->getName();
    747       mOut << "(";
    748 
    749       if (Ins.size() == 1) {
    750         mOut << "ain, ";
    751 
    752       } else if (Ins.size() > 1) {
    753         for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
    754              BI++) {
    755 
    756           mOut << "ain_" << (*BI)->getName().str() << ", ";
    757         }
    758       }
    759 
    760       if (EF->hasOut() || EF->hasReturn()) {
    761         mOut << "aout, ";
    762       }
    763 
    764       if (EF->hasUsrData()) {
    765         mOut << Args.back().second << ", ";
    766       }
    767 
    768       // No clipped bounds to pass in.
    769       mOut << "null);\n";
    770 
    771       endFunction();
    772     }
    773 
    774     // Add the clipped kernel parameters to the Args list.
    775     Args.push_back(std::make_pair("Script.LaunchOptions", "sc"));
    776   }
    777 
    778   startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
    779 
    780   if (InTypes.size() == 1) {
    781     if (InTypes.front() != nullptr) {
    782       genTypeCheck(InTypes.front(), "ain");
    783     }
    784 
    785   } else if (InTypes.size() > 1) {
    786     size_t Index = 0;
    787     for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
    788          BI != EI; BI++, ++Index) {
    789 
    790       if (*BI != nullptr) {
    791         genTypeCheck(*BI, ("ain_" + Ins[Index]->getName()).str().c_str());
    792       }
    793     }
    794   }
    795 
    796   if (OET) {
    797     genTypeCheck(OET, "aout");
    798   }
    799 
    800   if (Ins.size() == 1 && (EF->hasOut() || EF->hasReturn())) {
    801     mOut.indent() << "Type t0, t1;";
    802     genPairwiseDimCheck("ain", "aout");
    803 
    804   } else if (Ins.size() > 1) {
    805     mOut.indent() << "Type t0, t1;";
    806 
    807     std::string In0Name = "ain_" + Ins[0]->getName().str();
    808 
    809     for (size_t index = 1; index < Ins.size(); ++index) {
    810       genPairwiseDimCheck(In0Name, "ain_" + Ins[index]->getName().str());
    811     }
    812 
    813     if (EF->hasOut() || EF->hasReturn()) {
    814       genPairwiseDimCheck(In0Name, "aout");
    815     }
    816   }
    817 
    818   std::string FieldPackerName = EF->getName() + "_fp";
    819   if (ERT) {
    820     if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
    821       genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
    822     }
    823   }
    824   mOut.indent() << "forEach(" << RS_EXPORT_FOREACH_INDEX_PREFIX
    825                 << EF->getName();
    826 
    827   if (Ins.size() == 1) {
    828     mOut << ", ain";
    829   } else if (Ins.size() > 1) {
    830     mOut << ", new Allocation[]{ain_" << Ins[0]->getName().str();
    831 
    832     for (size_t index = 1; index < Ins.size(); ++index) {
    833       mOut << ", ain_" << Ins[index]->getName().str();
    834     }
    835 
    836     mOut << "}";
    837 
    838   } else {
    839     mOut << ", (Allocation) null";
    840   }
    841 
    842   if (EF->hasOut() || EF->hasReturn())
    843     mOut << ", aout";
    844   else
    845     mOut << ", null";
    846 
    847   if (EF->hasUsrData())
    848     mOut << ", " << FieldPackerName;
    849   else
    850     mOut << ", null";
    851 
    852   if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) {
    853     mOut << ", sc);\n";
    854   } else {
    855     mOut << ");\n";
    856   }
    857 
    858   endFunction();
    859 }
    860 
    861 void RSReflectionJava::genTypeInstanceFromPointer(const RSExportType *ET) {
    862   if (ET->getClass() == RSExportType::ExportClassPointer) {
    863     // For pointer parameters to original forEach kernels.
    864     const RSExportPointerType *EPT =
    865         static_cast<const RSExportPointerType *>(ET);
    866     genTypeInstance(EPT->getPointeeType());
    867   } else {
    868     // For handling pass-by-value kernel parameters.
    869     genTypeInstance(ET);
    870   }
    871 }
    872 
    873 void RSReflectionJava::genTypeInstance(const RSExportType *ET) {
    874   switch (ET->getClass()) {
    875   case RSExportType::ExportClassPrimitive:
    876   case RSExportType::ExportClassVector:
    877   case RSExportType::ExportClassConstantArray: {
    878     std::string TypeName = ET->getElementName();
    879     if (addTypeNameForElement(TypeName)) {
    880       mOut.indent() << RS_ELEM_PREFIX << TypeName << " = Element." << TypeName
    881                     << "(rs);\n";
    882     }
    883     break;
    884   }
    885 
    886   case RSExportType::ExportClassRecord: {
    887     std::string ClassName = ET->getElementName();
    888     if (addTypeNameForElement(ClassName)) {
    889       mOut.indent() << RS_ELEM_PREFIX << ClassName << " = " << ClassName
    890                     << ".createElement(rs);\n";
    891     }
    892     break;
    893   }
    894 
    895   default:
    896     break;
    897   }
    898 }
    899 
    900 void RSReflectionJava::genFieldPackerInstance(const RSExportType *ET) {
    901   switch (ET->getClass()) {
    902   case RSExportType::ExportClassPrimitive:
    903   case RSExportType::ExportClassVector:
    904   case RSExportType::ExportClassConstantArray:
    905   case RSExportType::ExportClassRecord: {
    906     std::string TypeName = ET->getElementName();
    907     addTypeNameForFieldPacker(TypeName);
    908     break;
    909   }
    910 
    911   default:
    912     break;
    913   }
    914 }
    915 
    916 void RSReflectionJava::genTypeCheck(const RSExportType *ET,
    917                                     const char *VarName) {
    918   mOut.indent() << "// check " << VarName << "\n";
    919 
    920   if (ET->getClass() == RSExportType::ExportClassPointer) {
    921     const RSExportPointerType *EPT =
    922         static_cast<const RSExportPointerType *>(ET);
    923     ET = EPT->getPointeeType();
    924   }
    925 
    926   std::string TypeName;
    927 
    928   switch (ET->getClass()) {
    929   case RSExportType::ExportClassPrimitive:
    930   case RSExportType::ExportClassVector:
    931   case RSExportType::ExportClassRecord: {
    932     TypeName = ET->getElementName();
    933     break;
    934   }
    935 
    936   default:
    937     break;
    938   }
    939 
    940   if (!TypeName.empty()) {
    941     mOut.indent() << "if (!" << VarName
    942                   << ".getType().getElement().isCompatible(" RS_ELEM_PREFIX
    943                   << TypeName << ")) {\n";
    944     mOut.indent() << "    throw new RSRuntimeException(\"Type mismatch with "
    945                   << TypeName << "!\");\n";
    946     mOut.indent() << "}\n";
    947   }
    948 }
    949 
    950 void RSReflectionJava::genPrimitiveTypeExportVariable(const RSExportVar *EV) {
    951   slangAssert(
    952       (EV->getType()->getClass() == RSExportType::ExportClassPrimitive) &&
    953       "Variable should be type of primitive here");
    954 
    955   const RSExportPrimitiveType *EPT =
    956       static_cast<const RSExportPrimitiveType *>(EV->getType());
    957   std::string TypeName = GetTypeName(EPT);
    958   std::string VarName = EV->getName();
    959 
    960   genPrivateExportVariable(TypeName, EV->getName());
    961 
    962   if (EV->isConst()) {
    963     mOut.indent() << "public final static " << TypeName
    964                   << " " RS_EXPORT_VAR_CONST_PREFIX << VarName << " = ";
    965     const clang::APValue &Val = EV->getInit();
    966     genInitValue(Val, EPT->getType() == DataTypeBoolean);
    967     mOut << ";\n";
    968   } else {
    969     // set_*()
    970     // This must remain synchronized, since multiple Dalvik threads may
    971     // be calling setters.
    972     startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1,
    973                   TypeName.c_str(), "v");
    974     if ((EPT->getSize() < 4) || EV->isUnsigned()) {
    975       // We create/cache a per-type FieldPacker. This allows us to reuse the
    976       // validation logic (for catching negative inputs from Dalvik, as well
    977       // as inputs that are too large to be represented in the unsigned type).
    978       // Sub-integer types are also handled specially here, so that we don't
    979       // overwrite bytes accidentally.
    980       std::string ElemName = EPT->getElementName();
    981       std::string FPName;
    982       FPName = RS_FP_PREFIX + ElemName;
    983       mOut.indent() << "if (" << FPName << "!= null) {\n";
    984       mOut.increaseIndent();
    985       mOut.indent() << FPName << ".reset();\n";
    986       mOut.decreaseIndent();
    987       mOut.indent() << "} else {\n";
    988       mOut.increaseIndent();
    989       mOut.indent() << FPName << " = new FieldPacker(" << EPT->getSize()
    990                     << ");\n";
    991       mOut.decreaseIndent();
    992       mOut.indent() << "}\n";
    993 
    994       genPackVarOfType(EPT, "v", FPName.c_str());
    995       mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
    996                     << ", " << FPName << ");\n";
    997     } else {
    998       mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
    999                     << ", v);\n";
   1000     }
   1001 
   1002     // Dalvik update comes last, since the input may be invalid (and hence
   1003     // throw an exception).
   1004     mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
   1005 
   1006     endFunction();
   1007   }
   1008 
   1009   genGetExportVariable(TypeName, VarName);
   1010   genGetFieldID(VarName);
   1011 }
   1012 
   1013 void RSReflectionJava::genInitValue(const clang::APValue &Val, bool asBool) {
   1014   switch (Val.getKind()) {
   1015   case clang::APValue::Int: {
   1016     llvm::APInt api = Val.getInt();
   1017     if (asBool) {
   1018       mOut << ((api.getSExtValue() == 0) ? "false" : "true");
   1019     } else {
   1020       // TODO: Handle unsigned correctly
   1021       mOut << api.getSExtValue();
   1022       if (api.getBitWidth() > 32) {
   1023         mOut << "L";
   1024       }
   1025     }
   1026     break;
   1027   }
   1028 
   1029   case clang::APValue::Float: {
   1030     llvm::APFloat apf = Val.getFloat();
   1031     llvm::SmallString<30> s;
   1032     apf.toString(s);
   1033     mOut << s.c_str();
   1034     if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
   1035       if (s.count('.') == 0) {
   1036         mOut << ".f";
   1037       } else {
   1038         mOut << "f";
   1039       }
   1040     }
   1041     break;
   1042   }
   1043 
   1044   case clang::APValue::ComplexInt:
   1045   case clang::APValue::ComplexFloat:
   1046   case clang::APValue::LValue:
   1047   case clang::APValue::Vector: {
   1048     slangAssert(false && "Primitive type cannot have such kind of initializer");
   1049     break;
   1050   }
   1051 
   1052   default: { slangAssert(false && "Unknown kind of initializer"); }
   1053   }
   1054 }
   1055 
   1056 void RSReflectionJava::genPointerTypeExportVariable(const RSExportVar *EV) {
   1057   const RSExportType *ET = EV->getType();
   1058   const RSExportType *PointeeType;
   1059 
   1060   slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
   1061               "Variable should be type of pointer here");
   1062 
   1063   PointeeType = static_cast<const RSExportPointerType *>(ET)->getPointeeType();
   1064   std::string TypeName = GetTypeName(ET);
   1065   std::string VarName = EV->getName();
   1066 
   1067   genPrivateExportVariable(TypeName, VarName);
   1068 
   1069   // bind_*()
   1070   startFunction(AM_Public, false, "void", "bind_" + VarName, 1,
   1071                 TypeName.c_str(), "v");
   1072 
   1073   mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
   1074   mOut.indent() << "if (v == null) bindAllocation(null, "
   1075                 << RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");\n";
   1076 
   1077   if (PointeeType->getClass() == RSExportType::ExportClassRecord) {
   1078     mOut.indent() << "else bindAllocation(v.getAllocation(), "
   1079                   << RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");\n";
   1080   } else {
   1081     mOut.indent() << "else bindAllocation(v, " << RS_EXPORT_VAR_INDEX_PREFIX
   1082                   << VarName << ");\n";
   1083   }
   1084 
   1085   endFunction();
   1086 
   1087   genGetExportVariable(TypeName, VarName);
   1088 }
   1089 
   1090 void RSReflectionJava::genVectorTypeExportVariable(const RSExportVar *EV) {
   1091   slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) &&
   1092               "Variable should be type of vector here");
   1093 
   1094   std::string TypeName = GetTypeName(EV->getType());
   1095   std::string VarName = EV->getName();
   1096 
   1097   genPrivateExportVariable(TypeName, VarName);
   1098   genSetExportVariable(TypeName, EV);
   1099   genGetExportVariable(TypeName, VarName);
   1100   genGetFieldID(VarName);
   1101 }
   1102 
   1103 void RSReflectionJava::genMatrixTypeExportVariable(const RSExportVar *EV) {
   1104   slangAssert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) &&
   1105               "Variable should be type of matrix here");
   1106 
   1107   const RSExportType *ET = EV->getType();
   1108   std::string TypeName = GetTypeName(ET);
   1109   std::string VarName = EV->getName();
   1110 
   1111   genPrivateExportVariable(TypeName, VarName);
   1112 
   1113   // set_*()
   1114   if (!EV->isConst()) {
   1115     const char *FieldPackerName = "fp";
   1116     startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1,
   1117                   TypeName.c_str(), "v");
   1118     mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
   1119 
   1120     if (genCreateFieldPacker(ET, FieldPackerName))
   1121       genPackVarOfType(ET, "v", FieldPackerName);
   1122     mOut.indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", "
   1123                   << FieldPackerName << ");\n";
   1124 
   1125     endFunction();
   1126   }
   1127 
   1128   genGetExportVariable(TypeName, VarName);
   1129   genGetFieldID(VarName);
   1130 }
   1131 
   1132 void
   1133 RSReflectionJava::genConstantArrayTypeExportVariable(const RSExportVar *EV) {
   1134   slangAssert(
   1135       (EV->getType()->getClass() == RSExportType::ExportClassConstantArray) &&
   1136       "Variable should be type of constant array here");
   1137 
   1138   std::string TypeName = GetTypeName(EV->getType());
   1139   std::string VarName = EV->getName();
   1140 
   1141   genPrivateExportVariable(TypeName, VarName);
   1142   genSetExportVariable(TypeName, EV);
   1143   genGetExportVariable(TypeName, VarName);
   1144   genGetFieldID(VarName);
   1145 }
   1146 
   1147 void RSReflectionJava::genRecordTypeExportVariable(const RSExportVar *EV) {
   1148   slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
   1149               "Variable should be type of struct here");
   1150 
   1151   std::string TypeName = GetTypeName(EV->getType());
   1152   std::string VarName = EV->getName();
   1153 
   1154   genPrivateExportVariable(TypeName, VarName);
   1155   genSetExportVariable(TypeName, EV);
   1156   genGetExportVariable(TypeName, VarName);
   1157   genGetFieldID(VarName);
   1158 }
   1159 
   1160 void RSReflectionJava::genPrivateExportVariable(const std::string &TypeName,
   1161                                                 const std::string &VarName) {
   1162   mOut.indent() << "private " << TypeName << " " << RS_EXPORT_VAR_PREFIX
   1163                 << VarName << ";\n";
   1164 }
   1165 
   1166 void RSReflectionJava::genSetExportVariable(const std::string &TypeName,
   1167                                             const RSExportVar *EV) {
   1168   if (!EV->isConst()) {
   1169     const char *FieldPackerName = "fp";
   1170     std::string VarName = EV->getName();
   1171     const RSExportType *ET = EV->getType();
   1172     startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1,
   1173                   TypeName.c_str(), "v");
   1174     mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
   1175 
   1176     if (genCreateFieldPacker(ET, FieldPackerName))
   1177       genPackVarOfType(ET, "v", FieldPackerName);
   1178 
   1179     if (mRSContext->getTargetAPI() < SLANG_JB_TARGET_API) {
   1180       // Legacy apps must use the old setVar() without Element/dim components.
   1181       mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
   1182                     << ", " << FieldPackerName << ");\n";
   1183     } else {
   1184       // We only have support for one-dimensional array reflection today,
   1185       // but the entry point (i.e. setVar()) takes an array of dimensions.
   1186       mOut.indent() << "int []__dimArr = new int[1];\n";
   1187       mOut.indent() << "__dimArr[0] = " << ET->getSize() << ";\n";
   1188       mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
   1189                     << ", " << FieldPackerName << ", " << RS_ELEM_PREFIX
   1190                     << ET->getElementName() << ", __dimArr);\n";
   1191     }
   1192 
   1193     endFunction();
   1194   }
   1195 }
   1196 
   1197 void RSReflectionJava::genGetExportVariable(const std::string &TypeName,
   1198                                             const std::string &VarName) {
   1199   startFunction(AM_Public, false, TypeName.c_str(), "get_" + VarName, 0);
   1200 
   1201   mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
   1202 
   1203   endFunction();
   1204 }
   1205 
   1206 void RSReflectionJava::genGetFieldID(const std::string &VarName) {
   1207   // We only generate getFieldID_*() for non-Pointer (bind) types.
   1208   if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
   1209     startFunction(AM_Public, false, "Script.FieldID", "getFieldID_" + VarName,
   1210                   0);
   1211 
   1212     mOut.indent() << "return createFieldID(" << RS_EXPORT_VAR_INDEX_PREFIX
   1213                   << VarName << ", null);\n";
   1214 
   1215     endFunction();
   1216   }
   1217 }
   1218 
   1219 /******************* Methods to generate script class /end *******************/
   1220 
   1221 bool RSReflectionJava::genCreateFieldPacker(const RSExportType *ET,
   1222                                             const char *FieldPackerName) {
   1223   size_t AllocSize = ET->getAllocSize();
   1224   if (AllocSize > 0)
   1225     mOut.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
   1226                   << AllocSize << ");\n";
   1227   else
   1228     return false;
   1229   return true;
   1230 }
   1231 
   1232 void RSReflectionJava::genPackVarOfType(const RSExportType *ET,
   1233                                         const char *VarName,
   1234                                         const char *FieldPackerName) {
   1235   switch (ET->getClass()) {
   1236   case RSExportType::ExportClassPrimitive:
   1237   case RSExportType::ExportClassVector: {
   1238     mOut.indent() << FieldPackerName << "."
   1239                   << GetPackerAPIName(
   1240                          static_cast<const RSExportPrimitiveType *>(ET)) << "("
   1241                   << VarName << ");\n";
   1242     break;
   1243   }
   1244   case RSExportType::ExportClassPointer: {
   1245     // Must reflect as type Allocation in Java
   1246     const RSExportType *PointeeType =
   1247         static_cast<const RSExportPointerType *>(ET)->getPointeeType();
   1248 
   1249     if (PointeeType->getClass() != RSExportType::ExportClassRecord) {
   1250       mOut.indent() << FieldPackerName << ".addI32(" << VarName
   1251                     << ".getPtr());\n";
   1252     } else {
   1253       mOut.indent() << FieldPackerName << ".addI32(" << VarName
   1254                     << ".getAllocation().getPtr());\n";
   1255     }
   1256     break;
   1257   }
   1258   case RSExportType::ExportClassMatrix: {
   1259     mOut.indent() << FieldPackerName << ".addMatrix(" << VarName << ");\n";
   1260     break;
   1261   }
   1262   case RSExportType::ExportClassConstantArray: {
   1263     const RSExportConstantArrayType *ECAT =
   1264         static_cast<const RSExportConstantArrayType *>(ET);
   1265 
   1266     // TODO(zonr): more elegant way. Currently, we obtain the unique index
   1267     //             variable (this method involves recursive call which means
   1268     //             we may have more than one level loop, therefore we can't
   1269     //             always use the same index variable name here) name given
   1270     //             in the for-loop from counting the '.' in @VarName.
   1271     unsigned Level = 0;
   1272     size_t LastDotPos = 0;
   1273     std::string ElementVarName(VarName);
   1274 
   1275     while (LastDotPos != std::string::npos) {
   1276       LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
   1277       Level++;
   1278     }
   1279     std::string IndexVarName("ct");
   1280     IndexVarName.append(llvm::utostr_32(Level));
   1281 
   1282     mOut.indent() << "for (int " << IndexVarName << " = 0; " << IndexVarName
   1283                   << " < " << ECAT->getSize() << "; " << IndexVarName << "++)";
   1284     mOut.startBlock();
   1285 
   1286     ElementVarName.append("[" + IndexVarName + "]");
   1287     genPackVarOfType(ECAT->getElementType(), ElementVarName.c_str(),
   1288                      FieldPackerName);
   1289 
   1290     mOut.endBlock();
   1291     break;
   1292   }
   1293   case RSExportType::ExportClassRecord: {
   1294     const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
   1295     // Relative pos from now on in field packer
   1296     unsigned Pos = 0;
   1297 
   1298     for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
   1299                                                   E = ERT->fields_end();
   1300          I != E; I++) {
   1301       const RSExportRecordType::Field *F = *I;
   1302       std::string FieldName;
   1303       size_t FieldOffset = F->getOffsetInParent();
   1304       const RSExportType *T = F->getType();
   1305       size_t FieldStoreSize = T->getStoreSize();
   1306       size_t FieldAllocSize = T->getAllocSize();
   1307 
   1308       if (VarName != nullptr)
   1309         FieldName = VarName + ("." + F->getName());
   1310       else
   1311         FieldName = F->getName();
   1312 
   1313       if (FieldOffset > Pos) {
   1314         mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
   1315                       << ");\n";
   1316       }
   1317 
   1318       genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
   1319 
   1320       // There is padding in the field type
   1321       if (FieldAllocSize > FieldStoreSize) {
   1322         mOut.indent() << FieldPackerName << ".skip("
   1323                       << (FieldAllocSize - FieldStoreSize) << ");\n";
   1324       }
   1325 
   1326       Pos = FieldOffset + FieldAllocSize;
   1327     }
   1328 
   1329     // There maybe some padding after the struct
   1330     if (ERT->getAllocSize() > Pos) {
   1331       mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
   1332                     << ");\n";
   1333     }
   1334     break;
   1335   }
   1336   default: { slangAssert(false && "Unknown class of type"); }
   1337   }
   1338 }
   1339 
   1340 void RSReflectionJava::genAllocateVarOfType(const RSExportType *T,
   1341                                             const std::string &VarName) {
   1342   switch (T->getClass()) {
   1343   case RSExportType::ExportClassPrimitive: {
   1344     // Primitive type like int in Java has its own storage once it's declared.
   1345     //
   1346     // FIXME: Should we allocate storage for RS object?
   1347     // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType())
   1348     //  mOut.indent() << VarName << " = new " << GetTypeName(T) << "();\n";
   1349     break;
   1350   }
   1351   case RSExportType::ExportClassPointer: {
   1352     // Pointer type is an instance of Allocation or a TypeClass whose value is
   1353     // expected to be assigned by programmer later in Java program. Therefore
   1354     // we don't reflect things like [VarName] = new Allocation();
   1355     mOut.indent() << VarName << " = null;\n";
   1356     break;
   1357   }
   1358   case RSExportType::ExportClassConstantArray: {
   1359     const RSExportConstantArrayType *ECAT =
   1360         static_cast<const RSExportConstantArrayType *>(T);
   1361     const RSExportType *ElementType = ECAT->getElementType();
   1362 
   1363     mOut.indent() << VarName << " = new " << GetTypeName(ElementType) << "["
   1364                   << ECAT->getSize() << "];\n";
   1365 
   1366     // Primitive type element doesn't need allocation code.
   1367     if (ElementType->getClass() != RSExportType::ExportClassPrimitive) {
   1368       mOut.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize()
   1369                     << "; $ct++)";
   1370       mOut.startBlock();
   1371 
   1372       std::string ElementVarName(VarName);
   1373       ElementVarName.append("[$ct]");
   1374       genAllocateVarOfType(ElementType, ElementVarName);
   1375 
   1376       mOut.endBlock();
   1377     }
   1378     break;
   1379   }
   1380   case RSExportType::ExportClassVector:
   1381   case RSExportType::ExportClassMatrix:
   1382   case RSExportType::ExportClassRecord: {
   1383     mOut.indent() << VarName << " = new " << GetTypeName(T) << "();\n";
   1384     break;
   1385   }
   1386   }
   1387 }
   1388 
   1389 void RSReflectionJava::genNewItemBufferIfNull(const char *Index) {
   1390   mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME " == null) ";
   1391   mOut << RS_TYPE_ITEM_BUFFER_NAME << " = new " << RS_TYPE_ITEM_CLASS_NAME
   1392        << "[getType().getX() /* count */];\n";
   1393   if (Index != nullptr) {
   1394     mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME << "[" << Index
   1395                   << "] == null) ";
   1396     mOut << RS_TYPE_ITEM_BUFFER_NAME << "[" << Index << "] = new "
   1397          << RS_TYPE_ITEM_CLASS_NAME << "();\n";
   1398   }
   1399 }
   1400 
   1401 void RSReflectionJava::genNewItemBufferPackerIfNull() {
   1402   mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " == null) ";
   1403   mOut << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = new FieldPacker("
   1404        <<  mItemSizeof << " * getType().getX()/* count */);\n";
   1405 }
   1406 
   1407 /********************** Methods to generate type class  **********************/
   1408 bool RSReflectionJava::genTypeClass(const RSExportRecordType *ERT,
   1409                                     std::string &ErrorMsg) {
   1410   std::string ClassName = ERT->getElementName();
   1411   std::string superClassName = getRSPackageName();
   1412   superClassName += RS_TYPE_CLASS_SUPER_CLASS_NAME;
   1413 
   1414   if (!startClass(AM_Public, false, ClassName, superClassName.c_str(),
   1415                   ErrorMsg))
   1416     return false;
   1417 
   1418   mGeneratedFileNames->push_back(ClassName);
   1419 
   1420   genTypeItemClass(ERT);
   1421 
   1422   // Declare item buffer and item buffer packer
   1423   mOut.indent() << "private " << RS_TYPE_ITEM_CLASS_NAME << " "
   1424                 << RS_TYPE_ITEM_BUFFER_NAME << "[];\n";
   1425   mOut.indent() << "private FieldPacker " << RS_TYPE_ITEM_BUFFER_PACKER_NAME
   1426                 << ";\n";
   1427   mOut.indent() << "private static java.lang.ref.WeakReference<Element> "
   1428                 << RS_TYPE_ELEMENT_REF_NAME
   1429                 << " = new java.lang.ref.WeakReference<Element>(null);\n";
   1430 
   1431   genTypeClassConstructor(ERT);
   1432   genTypeClassCopyToArrayLocal(ERT);
   1433   genTypeClassCopyToArray(ERT);
   1434   genTypeClassItemSetter(ERT);
   1435   genTypeClassItemGetter(ERT);
   1436   genTypeClassComponentSetter(ERT);
   1437   genTypeClassComponentGetter(ERT);
   1438   genTypeClassCopyAll(ERT);
   1439   if (!mRSContext->isCompatLib()) {
   1440     // Skip the resize method if we are targeting a compatibility library.
   1441     genTypeClassResize();
   1442   }
   1443 
   1444   endClass();
   1445 
   1446   resetFieldIndex();
   1447   clearFieldIndexMap();
   1448 
   1449   return true;
   1450 }
   1451 
   1452 void RSReflectionJava::genTypeItemClass(const RSExportRecordType *ERT) {
   1453   mOut.indent() << "static public class " RS_TYPE_ITEM_CLASS_NAME;
   1454   mOut.startBlock();
   1455 
   1456   // Sizeof should not be exposed for 64-bit; it is not accurate
   1457   if (mRSContext->getTargetAPI() < 21) {
   1458       mOut.indent() << "public static final int sizeof = " << ERT->getAllocSize()
   1459                     << ";\n";
   1460   }
   1461 
   1462   // Member elements
   1463   mOut << "\n";
   1464   for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
   1465                                                 FE = ERT->fields_end();
   1466        FI != FE; FI++) {
   1467     mOut.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
   1468                   << ";\n";
   1469   }
   1470 
   1471   // Constructor
   1472   mOut << "\n";
   1473   mOut.indent() << RS_TYPE_ITEM_CLASS_NAME << "()";
   1474   mOut.startBlock();
   1475 
   1476   for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
   1477                                                 FE = ERT->fields_end();
   1478        FI != FE; FI++) {
   1479     const RSExportRecordType::Field *F = *FI;
   1480     genAllocateVarOfType(F->getType(), F->getName());
   1481   }
   1482 
   1483   // end Constructor
   1484   mOut.endBlock();
   1485 
   1486   // end Item class
   1487   mOut.endBlock();
   1488 }
   1489 
   1490 void RSReflectionJava::genTypeClassConstructor(const RSExportRecordType *ERT) {
   1491   const char *RenderScriptVar = "rs";
   1492 
   1493   startFunction(AM_Public, true, "Element", "createElement", 1, "RenderScript",
   1494                 RenderScriptVar);
   1495 
   1496   // TODO(all): Fix weak-refs + multi-context issue.
   1497   // mOut.indent() << "Element e = " << RS_TYPE_ELEMENT_REF_NAME
   1498   //            << ".get();\n";
   1499   // mOut.indent() << "if (e != null) return e;\n";
   1500   RSReflectionJavaElementBuilder builder("eb", ERT, RenderScriptVar, &mOut,
   1501                                          mRSContext, this);
   1502   builder.generate();
   1503 
   1504   mOut.indent() << "return eb.create();\n";
   1505   // mOut.indent() << "e = eb.create();\n";
   1506   // mOut.indent() << RS_TYPE_ELEMENT_REF_NAME
   1507   //            << " = new java.lang.ref.WeakReference<Element>(e);\n";
   1508   // mOut.indent() << "return e;\n";
   1509   endFunction();
   1510 
   1511   // private with element
   1512   startFunction(AM_Private, false, nullptr, getClassName(), 1, "RenderScript",
   1513                 RenderScriptVar);
   1514   mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n";
   1515   mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n";
   1516   mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n";
   1517   endFunction();
   1518 
   1519   // 1D without usage
   1520   startFunction(AM_Public, false, nullptr, getClassName(), 2, "RenderScript",
   1521                 RenderScriptVar, "int", "count");
   1522 
   1523   mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n";
   1524   mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n";
   1525   mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n";
   1526   // Call init() in super class
   1527   mOut.indent() << "init(" << RenderScriptVar << ", count);\n";
   1528   endFunction();
   1529 
   1530   // 1D with usage
   1531   startFunction(AM_Public, false, nullptr, getClassName(), 3, "RenderScript",
   1532                 RenderScriptVar, "int", "count", "int", "usages");
   1533 
   1534   mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n";
   1535   mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n";
   1536   mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n";
   1537   // Call init() in super class
   1538   mOut.indent() << "init(" << RenderScriptVar << ", count, usages);\n";
   1539   endFunction();
   1540 
   1541   // create1D with usage
   1542   startFunction(AM_Public, true, getClassName().c_str(), "create1D", 3,
   1543                 "RenderScript", RenderScriptVar, "int", "dimX", "int",
   1544                 "usages");
   1545   mOut.indent() << getClassName() << " obj = new " << getClassName() << "("
   1546                 << RenderScriptVar << ");\n";
   1547   mOut.indent() << "obj.mAllocation = Allocation.createSized("
   1548                    "rs, obj.mElement, dimX, usages);\n";
   1549   mOut.indent() << "return obj;\n";
   1550   endFunction();
   1551 
   1552   // create1D without usage
   1553   startFunction(AM_Public, true, getClassName().c_str(), "create1D", 2,
   1554                 "RenderScript", RenderScriptVar, "int", "dimX");
   1555   mOut.indent() << "return create1D(" << RenderScriptVar
   1556                 << ", dimX, Allocation.USAGE_SCRIPT);\n";
   1557   endFunction();
   1558 
   1559   // create2D without usage
   1560   startFunction(AM_Public, true, getClassName().c_str(), "create2D", 3,
   1561                 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY");
   1562   mOut.indent() << "return create2D(" << RenderScriptVar
   1563                 << ", dimX, dimY, Allocation.USAGE_SCRIPT);\n";
   1564   endFunction();
   1565 
   1566   // create2D with usage
   1567   startFunction(AM_Public, true, getClassName().c_str(), "create2D", 4,
   1568                 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY",
   1569                 "int", "usages");
   1570 
   1571   mOut.indent() << getClassName() << " obj = new " << getClassName() << "("
   1572                 << RenderScriptVar << ");\n";
   1573   mOut.indent() << "Type.Builder b = new Type.Builder(rs, obj.mElement);\n";
   1574   mOut.indent() << "b.setX(dimX);\n";
   1575   mOut.indent() << "b.setY(dimY);\n";
   1576   mOut.indent() << "Type t = b.create();\n";
   1577   mOut.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n";
   1578   mOut.indent() << "return obj;\n";
   1579   endFunction();
   1580 
   1581   // createTypeBuilder
   1582   startFunction(AM_Public, true, "Type.Builder", "createTypeBuilder", 1,
   1583                 "RenderScript", RenderScriptVar);
   1584   mOut.indent() << "Element e = createElement(" << RenderScriptVar << ");\n";
   1585   mOut.indent() << "return new Type.Builder(rs, e);\n";
   1586   endFunction();
   1587 
   1588   // createCustom with usage
   1589   startFunction(AM_Public, true, getClassName().c_str(), "createCustom", 3,
   1590                 "RenderScript", RenderScriptVar, "Type.Builder", "tb", "int",
   1591                 "usages");
   1592   mOut.indent() << getClassName() << " obj = new " << getClassName() << "("
   1593                 << RenderScriptVar << ");\n";
   1594   mOut.indent() << "Type t = tb.create();\n";
   1595   mOut.indent() << "if (t.getElement() != obj.mElement) {\n";
   1596   mOut.indent() << "    throw new RSIllegalArgumentException("
   1597                    "\"Type.Builder did not match expected element type.\");\n";
   1598   mOut.indent() << "}\n";
   1599   mOut.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n";
   1600   mOut.indent() << "return obj;\n";
   1601   endFunction();
   1602 }
   1603 
   1604 void RSReflectionJava::genTypeClassCopyToArray(const RSExportRecordType *ERT) {
   1605   startFunction(AM_Private, false, "void", "copyToArray", 2,
   1606                 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index");
   1607 
   1608   genNewItemBufferPackerIfNull();
   1609   mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
   1610                 << mItemSizeof << ");\n";
   1611 
   1612   mOut.indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME
   1613                    ");\n";
   1614 
   1615   endFunction();
   1616 }
   1617 
   1618 void
   1619 RSReflectionJava::genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT) {
   1620   startFunction(AM_Private, false, "void", "copyToArrayLocal", 2,
   1621                 RS_TYPE_ITEM_CLASS_NAME, "i", "FieldPacker", "fp");
   1622 
   1623   genPackVarOfType(ERT, "i", "fp");
   1624 
   1625   endFunction();
   1626 }
   1627 
   1628 void RSReflectionJava::genTypeClassItemSetter(const RSExportRecordType *ERT) {
   1629   startFunction(AM_PublicSynchronized, false, "void", "set", 3,
   1630                 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index", "boolean",
   1631                 "copyNow");
   1632   genNewItemBufferIfNull(nullptr);
   1633   mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << "[index] = i;\n";
   1634 
   1635   mOut.indent() << "if (copyNow) ";
   1636   mOut.startBlock();
   1637 
   1638   mOut.indent() << "copyToArray(i, index);\n";
   1639   mOut.indent() << "FieldPacker fp = new FieldPacker(" << mItemSizeof << ");\n";
   1640   mOut.indent() << "copyToArrayLocal(i, fp);\n";
   1641   mOut.indent() << "mAllocation.setFromFieldPacker(index, fp);\n";
   1642 
   1643   // End of if (copyNow)
   1644   mOut.endBlock();
   1645 
   1646   endFunction();
   1647 }
   1648 
   1649 void RSReflectionJava::genTypeClassItemGetter(const RSExportRecordType *ERT) {
   1650   startFunction(AM_PublicSynchronized, false, RS_TYPE_ITEM_CLASS_NAME, "get", 1,
   1651                 "int", "index");
   1652   mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME
   1653                 << " == null) return null;\n";
   1654   mOut.indent() << "return " << RS_TYPE_ITEM_BUFFER_NAME << "[index];\n";
   1655   endFunction();
   1656 }
   1657 
   1658 void
   1659 RSReflectionJava::genTypeClassComponentSetter(const RSExportRecordType *ERT) {
   1660   for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
   1661                                                 FE = ERT->fields_end();
   1662        FI != FE; FI++) {
   1663     const RSExportRecordType::Field *F = *FI;
   1664     size_t FieldOffset = F->getOffsetInParent();
   1665     size_t FieldStoreSize = F->getType()->getStoreSize();
   1666     unsigned FieldIndex = getFieldIndex(F);
   1667 
   1668     startFunction(AM_PublicSynchronized, false, "void", "set_" + F->getName(),
   1669                   3, "int", "index", GetTypeName(F->getType()).c_str(), "v",
   1670                   "boolean", "copyNow");
   1671     genNewItemBufferPackerIfNull();
   1672     genNewItemBufferIfNull("index");
   1673     mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << "[index]." << F->getName()
   1674                   << " = v;\n";
   1675 
   1676     mOut.indent() << "if (copyNow) ";
   1677     mOut.startBlock();
   1678 
   1679     if (FieldOffset > 0) {
   1680       mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
   1681                     << mItemSizeof << " + " << FieldOffset
   1682                     << ");\n";
   1683     } else {
   1684       mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
   1685                     << mItemSizeof << ");\n";
   1686     }
   1687     genPackVarOfType(F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
   1688 
   1689     mOut.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize
   1690                   << ");\n";
   1691     genPackVarOfType(F->getType(), "v", "fp");
   1692     mOut.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex
   1693                   << ", fp);\n";
   1694 
   1695     // End of if (copyNow)
   1696     mOut.endBlock();
   1697 
   1698     endFunction();
   1699   }
   1700 }
   1701 
   1702 void
   1703 RSReflectionJava::genTypeClassComponentGetter(const RSExportRecordType *ERT) {
   1704   for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
   1705                                                 FE = ERT->fields_end();
   1706        FI != FE; FI++) {
   1707     const RSExportRecordType::Field *F = *FI;
   1708     startFunction(AM_PublicSynchronized, false,
   1709                   GetTypeName(F->getType()).c_str(), "get_" + F->getName(), 1,
   1710                   "int", "index");
   1711     mOut.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME << " == null) return "
   1712                   << GetTypeNullValue(F->getType()) << ";\n";
   1713     mOut.indent() << "return " RS_TYPE_ITEM_BUFFER_NAME << "[index]."
   1714                   << F->getName() << ";\n";
   1715     endFunction();
   1716   }
   1717 }
   1718 
   1719 void RSReflectionJava::genTypeClassCopyAll(const RSExportRecordType *ERT) {
   1720   startFunction(AM_PublicSynchronized, false, "void", "copyAll", 0);
   1721 
   1722   mOut.indent() << "for (int ct = 0; ct < " << RS_TYPE_ITEM_BUFFER_NAME
   1723                 << ".length; ct++)"
   1724                 << " copyToArray(" << RS_TYPE_ITEM_BUFFER_NAME
   1725                 << "[ct], ct);\n";
   1726   mOut.indent() << "mAllocation.setFromFieldPacker(0, "
   1727                 << RS_TYPE_ITEM_BUFFER_PACKER_NAME ");\n";
   1728 
   1729   endFunction();
   1730 }
   1731 
   1732 void RSReflectionJava::genTypeClassResize() {
   1733   startFunction(AM_PublicSynchronized, false, "void", "resize", 1, "int",
   1734                 "newSize");
   1735 
   1736   mOut.indent() << "if (mItemArray != null) ";
   1737   mOut.startBlock();
   1738   mOut.indent() << "int oldSize = mItemArray.length;\n";
   1739   mOut.indent() << "int copySize = Math.min(oldSize, newSize);\n";
   1740   mOut.indent() << "if (newSize == oldSize) return;\n";
   1741   mOut.indent() << "Item ni[] = new Item[newSize];\n";
   1742   mOut.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);\n";
   1743   mOut.indent() << "mItemArray = ni;\n";
   1744   mOut.endBlock();
   1745   mOut.indent() << "mAllocation.resize(newSize);\n";
   1746 
   1747   mOut.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME
   1748                    " != null) " RS_TYPE_ITEM_BUFFER_PACKER_NAME " = "
   1749                    "new FieldPacker(" << mItemSizeof << " * getType().getX()/* count */);\n";
   1750 
   1751   endFunction();
   1752 }
   1753 
   1754 /******************** Methods to generate type class /end ********************/
   1755 
   1756 /********** Methods to create Element in Java of given record type ***********/
   1757 
   1758 RSReflectionJavaElementBuilder::RSReflectionJavaElementBuilder(
   1759     const char *ElementBuilderName, const RSExportRecordType *ERT,
   1760     const char *RenderScriptVar, GeneratedFile *Out, const RSContext *RSContext,
   1761     RSReflectionJava *Reflection)
   1762     : mElementBuilderName(ElementBuilderName), mERT(ERT),
   1763       mRenderScriptVar(RenderScriptVar), mOut(Out), mPaddingFieldIndex(1),
   1764       mRSContext(RSContext), mReflection(Reflection) {
   1765   if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
   1766     mPaddingPrefix = "#padding_";
   1767   } else {
   1768     mPaddingPrefix = "#rs_padding_";
   1769   }
   1770 }
   1771 
   1772 void RSReflectionJavaElementBuilder::generate() {
   1773   mOut->indent() << "Element.Builder " << mElementBuilderName
   1774                  << " = new Element.Builder(" << mRenderScriptVar << ");\n";
   1775   genAddElement(mERT, "", /* ArraySize = */ 0);
   1776 }
   1777 
   1778 void RSReflectionJavaElementBuilder::genAddElement(const RSExportType *ET,
   1779                                                    const std::string &VarName,
   1780                                                    unsigned ArraySize) {
   1781   std::string ElementConstruct = GetBuiltinElementConstruct(ET);
   1782 
   1783   if (ElementConstruct != "") {
   1784     genAddStatementStart();
   1785     *mOut << ElementConstruct << "(" << mRenderScriptVar << ")";
   1786     genAddStatementEnd(VarName, ArraySize);
   1787   } else {
   1788 
   1789     switch (ET->getClass()) {
   1790     case RSExportType::ExportClassPrimitive: {
   1791       const RSExportPrimitiveType *EPT =
   1792           static_cast<const RSExportPrimitiveType *>(ET);
   1793       const char *DataTypeName =
   1794           RSExportPrimitiveType::getRSReflectionType(EPT)->rs_type;
   1795       genAddStatementStart();
   1796       *mOut << "Element.createUser(" << mRenderScriptVar
   1797             << ", Element.DataType." << DataTypeName << ")";
   1798       genAddStatementEnd(VarName, ArraySize);
   1799       break;
   1800     }
   1801     case RSExportType::ExportClassVector: {
   1802       const RSExportVectorType *EVT =
   1803           static_cast<const RSExportVectorType *>(ET);
   1804       const char *DataTypeName =
   1805           RSExportPrimitiveType::getRSReflectionType(EVT)->rs_type;
   1806       genAddStatementStart();
   1807       *mOut << "Element.createVector(" << mRenderScriptVar
   1808             << ", Element.DataType." << DataTypeName << ", "
   1809             << EVT->getNumElement() << ")";
   1810       genAddStatementEnd(VarName, ArraySize);
   1811       break;
   1812     }
   1813     case RSExportType::ExportClassPointer:
   1814       // Pointer type variable should be resolved in
   1815       // GetBuiltinElementConstruct()
   1816       slangAssert(false && "??");
   1817       break;
   1818     case RSExportType::ExportClassMatrix:
   1819       // Matrix type variable should be resolved
   1820       // in GetBuiltinElementConstruct()
   1821       slangAssert(false && "??");
   1822       break;
   1823     case RSExportType::ExportClassConstantArray: {
   1824       const RSExportConstantArrayType *ECAT =
   1825           static_cast<const RSExportConstantArrayType *>(ET);
   1826 
   1827       const RSExportType *ElementType = ECAT->getElementType();
   1828       if (ElementType->getClass() != RSExportType::ExportClassRecord) {
   1829         genAddElement(ECAT->getElementType(), VarName, ECAT->getSize());
   1830       } else {
   1831         std::string NewElementBuilderName(mElementBuilderName);
   1832         NewElementBuilderName.append(1, '_');
   1833 
   1834         RSReflectionJavaElementBuilder builder(
   1835             NewElementBuilderName.c_str(),
   1836             static_cast<const RSExportRecordType *>(ElementType),
   1837             mRenderScriptVar, mOut, mRSContext, mReflection);
   1838         builder.generate();
   1839 
   1840         ArraySize = ECAT->getSize();
   1841         genAddStatementStart();
   1842         *mOut << NewElementBuilderName << ".create()";
   1843         genAddStatementEnd(VarName, ArraySize);
   1844       }
   1845       break;
   1846     }
   1847     case RSExportType::ExportClassRecord: {
   1848       // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
   1849       //
   1850       // TODO(zonr): Generalize these two function such that there's no
   1851       //             duplicated codes.
   1852       const RSExportRecordType *ERT =
   1853           static_cast<const RSExportRecordType *>(ET);
   1854       int Pos = 0; // relative pos from now on
   1855 
   1856       for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
   1857                                                     E = ERT->fields_end();
   1858            I != E; I++) {
   1859         const RSExportRecordType::Field *F = *I;
   1860         int FieldOffset = F->getOffsetInParent();
   1861         const RSExportType *T = F->getType();
   1862         int FieldStoreSize = T->getStoreSize();
   1863         int FieldAllocSize = T->getAllocSize();
   1864 
   1865         std::string FieldName;
   1866         if (!VarName.empty())
   1867           FieldName = VarName + "." + F->getName();
   1868         else
   1869           FieldName = F->getName();
   1870 
   1871         // Alignment
   1872         genAddPadding(FieldOffset - Pos);
   1873 
   1874         // eb.add(...)
   1875         mReflection->addFieldIndexMapping(F);
   1876         if (F->getType()->getClass() != RSExportType::ExportClassRecord) {
   1877           genAddElement(F->getType(), FieldName, 0);
   1878         } else {
   1879           std::string NewElementBuilderName(mElementBuilderName);
   1880           NewElementBuilderName.append(1, '_');
   1881 
   1882           RSReflectionJavaElementBuilder builder(
   1883               NewElementBuilderName.c_str(),
   1884               static_cast<const RSExportRecordType *>(F->getType()),
   1885               mRenderScriptVar, mOut, mRSContext, mReflection);
   1886           builder.generate();
   1887 
   1888           genAddStatementStart();
   1889           *mOut << NewElementBuilderName << ".create()";
   1890           genAddStatementEnd(FieldName, ArraySize);
   1891         }
   1892 
   1893         if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
   1894           // There is padding within the field type. This is only necessary
   1895           // for HC-targeted APIs.
   1896           genAddPadding(FieldAllocSize - FieldStoreSize);
   1897         }
   1898 
   1899         Pos = FieldOffset + FieldAllocSize;
   1900       }
   1901 
   1902       // There maybe some padding after the struct
   1903       size_t RecordAllocSize = ERT->getAllocSize();
   1904 
   1905       genAddPadding(RecordAllocSize - Pos);
   1906       break;
   1907     }
   1908     default:
   1909       slangAssert(false && "Unknown class of type");
   1910       break;
   1911     }
   1912   }
   1913 }
   1914 
   1915 void RSReflectionJavaElementBuilder::genAddPadding(int PaddingSize) {
   1916   while (PaddingSize > 0) {
   1917     const std::string &VarName = createPaddingField();
   1918     genAddStatementStart();
   1919     if (PaddingSize >= 4) {
   1920       *mOut << "Element.U32(" << mRenderScriptVar << ")";
   1921       PaddingSize -= 4;
   1922     } else if (PaddingSize >= 2) {
   1923       *mOut << "Element.U16(" << mRenderScriptVar << ")";
   1924       PaddingSize -= 2;
   1925     } else if (PaddingSize >= 1) {
   1926       *mOut << "Element.U8(" << mRenderScriptVar << ")";
   1927       PaddingSize -= 1;
   1928     }
   1929     genAddStatementEnd(VarName, 0);
   1930   }
   1931 }
   1932 
   1933 void RSReflectionJavaElementBuilder::genAddStatementStart() {
   1934   mOut->indent() << mElementBuilderName << ".add(";
   1935 }
   1936 
   1937 void
   1938 RSReflectionJavaElementBuilder::genAddStatementEnd(const std::string &VarName,
   1939                                                    unsigned ArraySize) {
   1940   *mOut << ", \"" << VarName << "\"";
   1941   if (ArraySize > 0) {
   1942     *mOut << ", " << ArraySize;
   1943   }
   1944   *mOut << ");\n";
   1945   // TODO Review incFieldIndex.  It's probably better to assign the numbers at
   1946   // the start rather
   1947   // than as we're generating the code.
   1948   mReflection->incFieldIndex();
   1949 }
   1950 
   1951 /******** Methods to create Element in Java of given record type /end ********/
   1952 
   1953 bool RSReflectionJava::reflect() {
   1954   std::string ErrorMsg;
   1955   if (!genScriptClass(mScriptClassName, ErrorMsg)) {
   1956     std::cerr << "Failed to generate class " << mScriptClassName << " ("
   1957               << ErrorMsg << ")\n";
   1958     return false;
   1959   }
   1960 
   1961   mGeneratedFileNames->push_back(mScriptClassName);
   1962 
   1963   // class ScriptField_<TypeName>
   1964   for (RSContext::const_export_type_iterator
   1965            TI = mRSContext->export_types_begin(),
   1966            TE = mRSContext->export_types_end();
   1967        TI != TE; TI++) {
   1968     const RSExportType *ET = TI->getValue();
   1969 
   1970     if (ET->getClass() == RSExportType::ExportClassRecord) {
   1971       const RSExportRecordType *ERT =
   1972           static_cast<const RSExportRecordType *>(ET);
   1973 
   1974       if (!ERT->isArtificial() && !genTypeClass(ERT, ErrorMsg)) {
   1975         std::cerr << "Failed to generate type class for struct '"
   1976                   << ERT->getName() << "' (" << ErrorMsg << ")\n";
   1977         return false;
   1978       }
   1979     }
   1980   }
   1981 
   1982   return true;
   1983 }
   1984 
   1985 const char *RSReflectionJava::AccessModifierStr(AccessModifier AM) {
   1986   switch (AM) {
   1987   case AM_Public:
   1988     return "public";
   1989     break;
   1990   case AM_Protected:
   1991     return "protected";
   1992     break;
   1993   case AM_Private:
   1994     return "private";
   1995     break;
   1996   case AM_PublicSynchronized:
   1997     return "public synchronized";
   1998     break;
   1999   default:
   2000     return "";
   2001     break;
   2002   }
   2003 }
   2004 
   2005 bool RSReflectionJava::startClass(AccessModifier AM, bool IsStatic,
   2006                                   const std::string &ClassName,
   2007                                   const char *SuperClassName,
   2008                                   std::string &ErrorMsg) {
   2009   // Open file for class
   2010   std::string FileName = ClassName + ".java";
   2011   if (!mOut.startFile(mOutputDirectory, FileName, mRSSourceFileName,
   2012                       mRSContext->getLicenseNote(), true,
   2013                       mRSContext->getVerbose())) {
   2014     return false;
   2015   }
   2016 
   2017   // Package
   2018   if (!mPackageName.empty()) {
   2019     mOut << "package " << mPackageName << ";\n";
   2020   }
   2021   mOut << "\n";
   2022 
   2023   // Imports
   2024   mOut << "import " << mRSPackageName << ".*;\n";
   2025   if (getEmbedBitcodeInJava()) {
   2026     mOut << "import " << mPackageName << "."
   2027           << RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName(
   2028                  mRSSourceFileName.c_str()) << ";\n";
   2029   } else {
   2030     mOut << "import android.content.res.Resources;\n";
   2031   }
   2032   mOut << "\n";
   2033 
   2034   // All reflected classes should be annotated as hidden, so that they won't
   2035   // be exposed in SDK.
   2036   mOut << "/**\n";
   2037   mOut << " * @hide\n";
   2038   mOut << " */\n";
   2039 
   2040   mOut << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
   2041        << ClassName;
   2042   if (SuperClassName != nullptr)
   2043     mOut << " extends " << SuperClassName;
   2044 
   2045   mOut.startBlock();
   2046 
   2047   mClassName = ClassName;
   2048 
   2049   return true;
   2050 }
   2051 
   2052 void RSReflectionJava::endClass() {
   2053   mOut.endBlock();
   2054   mOut.closeFile();
   2055   clear();
   2056 }
   2057 
   2058 void RSReflectionJava::startTypeClass(const std::string &ClassName) {
   2059   mOut.indent() << "public static class " << ClassName;
   2060   mOut.startBlock();
   2061 }
   2062 
   2063 void RSReflectionJava::endTypeClass() { mOut.endBlock(); }
   2064 
   2065 void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic,
   2066                                      const char *ReturnType,
   2067                                      const std::string &FunctionName, int Argc,
   2068                                      ...) {
   2069   ArgTy Args;
   2070   va_list vl;
   2071   va_start(vl, Argc);
   2072 
   2073   for (int i = 0; i < Argc; i++) {
   2074     const char *ArgType = va_arg(vl, const char *);
   2075     const char *ArgName = va_arg(vl, const char *);
   2076 
   2077     Args.push_back(std::make_pair(ArgType, ArgName));
   2078   }
   2079   va_end(vl);
   2080 
   2081   startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
   2082 }
   2083 
   2084 void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic,
   2085                                      const char *ReturnType,
   2086                                      const std::string &FunctionName,
   2087                                      const ArgTy &Args) {
   2088   mOut.indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
   2089                 << ((ReturnType) ? ReturnType : "") << " " << FunctionName
   2090                 << "(";
   2091 
   2092   bool FirstArg = true;
   2093   for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) {
   2094     if (!FirstArg)
   2095       mOut << ", ";
   2096     else
   2097       FirstArg = false;
   2098 
   2099     mOut << I->first << " " << I->second;
   2100   }
   2101 
   2102   mOut << ")";
   2103   mOut.startBlock();
   2104 }
   2105 
   2106 void RSReflectionJava::endFunction() { mOut.endBlock(); }
   2107 
   2108 bool RSReflectionJava::addTypeNameForElement(const std::string &TypeName) {
   2109   if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
   2110     mTypesToCheck.insert(TypeName);
   2111     return true;
   2112   } else {
   2113     return false;
   2114   }
   2115 }
   2116 
   2117 bool RSReflectionJava::addTypeNameForFieldPacker(const std::string &TypeName) {
   2118   if (mFieldPackerTypes.find(TypeName) == mFieldPackerTypes.end()) {
   2119     mFieldPackerTypes.insert(TypeName);
   2120     return true;
   2121   } else {
   2122     return false;
   2123   }
   2124 }
   2125 
   2126 } // namespace slang
   2127