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