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