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