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