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