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