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