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