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