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