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