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