slang_rs_reflection.cpp revision 66aa299de2b5e0b0c7bfae7628e29a3961247aed
1#include "slang_rs_reflection.h"
2
3#include <utility>
4#include <cstdarg>
5#include <cctype>
6#include <sys/stat.h>
7
8#include "llvm/ADT/APFloat.h"
9
10#include "slang_rs_context.h"
11#include "slang_rs_export_var.h"
12#include "slang_rs_export_func.h"
13#include "slang_rs_reflect_utils.h"
14
15#define RS_SCRIPT_CLASS_NAME_PREFIX      "ScriptC_"
16#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME "ScriptC"
17
18#define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
19#define RS_TYPE_CLASS_SUPER_CLASS_NAME   "android.renderscript.Script.FieldBase"
20
21#define RS_TYPE_ITEM_CLASS_NAME          "Item"
22
23#define RS_TYPE_ITEM_BUFFER_NAME         "mItemArray"
24#define RS_TYPE_ITEM_BUFFER_PACKER_NAME  "mIOBuffer"
25
26#define RS_EXPORT_VAR_INDEX_PREFIX       "mExportVarIdx_"
27#define RS_EXPORT_VAR_PREFIX             "mExportVar_"
28
29#define RS_EXPORT_FUNC_INDEX_PREFIX      "mExportFuncIdx_"
30
31#define RS_EXPORT_VAR_ALLOCATION_PREFIX  "mAlloction_"
32#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX "mData_"
33
34using namespace slang;
35
36// Some utility function using internal in RSReflection
37static bool GetClassNameFromFileName(const std::string &FileName,
38                                     std::string &ClassName) {
39  ClassName.clear();
40
41  if (FileName.empty() || (FileName == "-"))
42    return true;
43
44  ClassName =
45      RSSlangReflectUtils::JavaClassNameFromRSFileName(FileName.c_str());
46
47  return true;
48}
49
50static const char *GetPrimitiveTypeName(const RSExportPrimitiveType *EPT) {
51  static const char *PrimitiveTypeJavaNameMap[] = {
52    "",         // RSExportPrimitiveType::DataTypeFloat16
53    "float",    // RSExportPrimitiveType::DataTypeFloat32
54    "double",   // RSExportPrimitiveType::DataTypeFloat64
55    "byte",     // RSExportPrimitiveType::DataTypeSigned8
56    "short",    // RSExportPrimitiveType::DataTypeSigned16
57    "int",      // RSExportPrimitiveType::DataTypeSigned32
58    "long",     // RSExportPrimitiveType::DataTypeSigned64
59    "short",    // RSExportPrimitiveType::DataTypeUnsigned8
60    "int",      // RSExportPrimitiveType::DataTypeUnsigned16
61    "long",     // RSExportPrimitiveType::DataTypeUnsigned32
62    "long",     // RSExportPrimitiveType::DataTypeUnsigned64
63    "boolean",  // RSExportPrimitiveType::DataTypeBoolean
64
65    "int",      // RSExportPrimitiveType::DataTypeUnsigned565
66    "int",      // RSExportPrimitiveType::DataTypeUnsigned5551
67    "int",      // RSExportPrimitiveType::DataTypeUnsigned4444
68
69    "Matrix2f",     // RSExportPrimitiveType::DataTypeRSMatrix2x2
70    "Matrix3f",     // RSExportPrimitiveType::DataTypeRSMatrix3x3
71    "Matrix4f",     // RSExportPrimitiveType::DataTypeRSMatrix4x4
72
73    "Element",  // RSExportPrimitiveType::DataTypeRSElement
74    "Type",     // RSExportPrimitiveType::DataTypeRSType
75    "Allocation",   // RSExportPrimitiveType::DataTypeRSAllocation
76    "Sampler",  // RSExportPrimitiveType::DataTypeRSSampler
77    "Script",   // RSExportPrimitiveType::DataTypeRSScript
78    "Mesh",       // RSExportPrimitiveType::DataTypeRSMesh
79    "ProgramFragment",  // RSExportPrimitiveType::DataTypeRSProgramFragment
80    "ProgramVertex",    // RSExportPrimitiveType::DataTypeRSProgramVertex
81    "ProgramRaster",    // RSExportPrimitiveType::DataTypeRSProgramRaster
82    "ProgramStore",     // RSExportPrimitiveType::DataTypeRSProgramStore
83    "Font",     // RSExportPrimitiveType::DataTypeRSFont
84  };
85  unsigned TypeId = EPT->getType();
86
87  if (TypeId < (sizeof(PrimitiveTypeJavaNameMap) / sizeof(const char*))) {
88    return PrimitiveTypeJavaNameMap[ EPT->getType() ];
89  }
90
91  assert(false && "GetPrimitiveTypeName : Unknown primitive data type");
92  return NULL;
93}
94
95static const char *GetVectorTypeName(const RSExportVectorType *EVT) {
96  static const char *VectorTypeJavaNameMap[][3] = {
97    /* 0 */ { "Byte2",  "Byte3",    "Byte4" },
98    /* 1 */ { "Short2", "Short3",   "Short4" },
99    /* 2 */ { "Int2",   "Int3",     "Int4" },
100    /* 3 */ { "Long2",  "Long3",    "Long4" },
101    /* 4 */ { "Float2", "Float3",   "Float4" },
102  };
103
104  const char **BaseElement = NULL;
105
106  switch (EVT->getType()) {
107    case RSExportPrimitiveType::DataTypeSigned8:
108    case RSExportPrimitiveType::DataTypeBoolean: {
109      BaseElement = VectorTypeJavaNameMap[0];
110      break;
111    }
112    case RSExportPrimitiveType::DataTypeSigned16:
113    case RSExportPrimitiveType::DataTypeUnsigned8: {
114      BaseElement = VectorTypeJavaNameMap[1];
115      break;
116    }
117    case RSExportPrimitiveType::DataTypeSigned32:
118    case RSExportPrimitiveType::DataTypeUnsigned16: {
119      BaseElement = VectorTypeJavaNameMap[2];
120      break;
121    }
122    case RSExportPrimitiveType::DataTypeSigned64:
123    case RSExportPrimitiveType::DataTypeUnsigned32: {
124      BaseElement = VectorTypeJavaNameMap[3];
125      break;
126    }
127    case RSExportPrimitiveType::DataTypeFloat32: {
128      BaseElement = VectorTypeJavaNameMap[4];
129      break;
130    }
131    default: {
132      assert(false && "RSReflection::genElementTypeName : Unsupported vector "
133                      "element data type");
134      break;
135    }
136  }
137
138  assert((EVT->getNumElement() > 1) &&
139         (EVT->getNumElement() <= 4) &&
140         "Number of element in vector type is invalid");
141
142  return BaseElement[EVT->getNumElement() - 2];
143}
144
145static const char *GetVectorAccessor(int Index) {
146  static const char *VectorAccessorMap[] = {
147    /* 0 */ "x",
148    /* 1 */ "y",
149    /* 2 */ "z",
150    /* 3 */ "w",
151  };
152
153  assert((Index >= 0) &&
154         (Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) &&
155         "Out-of-bound index to access vector member");
156
157  return VectorAccessorMap[Index];
158}
159
160static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) {
161  static const char *PrimitiveTypePackerAPINameMap[] = {
162    "",         // RSExportPrimitiveType::DataTypeFloat16
163    "addF32",   // RSExportPrimitiveType::DataTypeFloat32
164    "addF64",   // RSExportPrimitiveType::DataTypeFloat64
165    "addI8",    // RSExportPrimitiveType::DataTypeSigned8
166    "addI16",   // RSExportPrimitiveType::DataTypeSigned16
167    "addI32",   // RSExportPrimitiveType::DataTypeSigned32
168    "addI64",   // RSExportPrimitiveType::DataTypeSigned64
169    "addU8",    // RSExportPrimitiveType::DataTypeUnsigned8
170    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned16
171    "addU32",   // RSExportPrimitiveType::DataTypeUnsigned32
172    "addU64",   // RSExportPrimitiveType::DataTypeUnsigned64
173    "addBoolean",  // RSExportPrimitiveType::DataTypeBoolean
174
175    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned565
176    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned5551
177    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned4444
178
179    "addObj",   // RSExportPrimitiveType::DataTypeRSMatrix2x2
180    "addObj",   // RSExportPrimitiveType::DataTypeRSMatrix3x3
181    "addObj",   // RSExportPrimitiveType::DataTypeRSMatrix4x4
182
183    "addObj",   // RSExportPrimitiveType::DataTypeRSElement
184    "addObj",   // RSExportPrimitiveType::DataTypeRSType
185    "addObj",   // RSExportPrimitiveType::DataTypeRSAllocation
186    "addObj",   // RSExportPrimitiveType::DataTypeRSSampler
187    "addObj",   // RSExportPrimitiveType::DataTypeRSScript
188    "addObj",   // RSExportPrimitiveType::DataTypeRSMesh
189    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramFragment
190    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramVertex
191    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramRaster
192    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramStore
193    "addObj",   // RSExportPrimitiveType::DataTypeRSFont
194  };
195  unsigned TypeId = EPT->getType();
196
197  if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*)))
198    return PrimitiveTypePackerAPINameMap[ EPT->getType() ];
199
200  assert(false && "GetPackerAPIName : Unknown primitive data type");
201  return NULL;
202}
203
204static std::string GetTypeName(const RSExportType *ET) {
205  switch (ET->getClass()) {
206    case RSExportType::ExportClassPrimitive:
207    case RSExportType::ExportClassConstantArray: {
208      return GetPrimitiveTypeName(
209                static_cast<const RSExportPrimitiveType*>(ET));
210      break;
211    }
212    case RSExportType::ExportClassPointer: {
213      const RSExportType *PointeeType =
214          static_cast<const RSExportPointerType*>(ET)->getPointeeType();
215
216      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
217        return "Allocation";
218      else
219        return RS_TYPE_CLASS_NAME_PREFIX + PointeeType->getName();
220      break;
221    }
222    case RSExportType::ExportClassVector: {
223      return GetVectorTypeName(static_cast<const RSExportVectorType*>(ET));
224      break;
225    }
226    case RSExportType::ExportClassRecord: {
227      return RS_TYPE_CLASS_NAME_PREFIX + ET->getName() +
228                 "."RS_TYPE_ITEM_CLASS_NAME;
229      break;
230    }
231    default: {
232      assert(false && "Unknown class of type");
233    }
234  }
235
236  return "";
237}
238
239static const char *GetBuiltinElementConstruct(const RSExportType *ET) {
240  if (ET->getClass() == RSExportType::ExportClassPrimitive ||
241      ET->getClass() == RSExportType::ExportClassConstantArray) {
242    const RSExportPrimitiveType *EPT =
243        static_cast<const RSExportPrimitiveType*>(ET);
244    if (EPT->getKind() == RSExportPrimitiveType::DataKindUser) {
245      static const char *PrimitiveBuiltinElementConstructMap[] = {
246        NULL,   // RSExportPrimitiveType::DataTypeFloat16
247        "F32",  // RSExportPrimitiveType::DataTypeFloat32
248        "F64",  // RSExportPrimitiveType::DataTypeFloat64
249        "I8",   // RSExportPrimitiveType::DataTypeSigned8
250        NULL,   // RSExportPrimitiveType::DataTypeSigned16
251        "I32",  // RSExportPrimitiveType::DataTypeSigned32
252        "I64",  // RSExportPrimitiveType::DataTypeSigned64
253        "U8",   // RSExportPrimitiveType::DataTypeUnsigned8
254        NULL,   // RSExportPrimitiveType::DataTypeUnsigned16
255        "U32",  // RSExportPrimitiveType::DataTypeUnsigned32
256        NULL,   // RSExportPrimitiveType::DataTypeUnsigned64
257        "BOOLEAN",  // RSExportPrimitiveType::DataTypeBoolean
258
259        NULL,   // RSExportPrimitiveType::DataTypeUnsigned565
260        NULL,   // RSExportPrimitiveType::DataTypeUnsigned5551
261        NULL,   // RSExportPrimitiveType::DataTypeUnsigned4444
262
263        "MATRIX_2X2",   // RSExportPrimitiveType::DataTypeRSMatrix2x2
264        "MATRIX_3X3",   // RSExportPrimitiveType::DataTypeRSMatrix3x3
265        "MATRIX_4X4",   // RSExportPrimitiveType::DataTypeRSMatrix4x4
266
267        "ELEMENT",      // RSExportPrimitiveType::DataTypeRSElement
268        "TYPE",         // RSExportPrimitiveType::DataTypeRSType
269        "ALLOCATION",   // RSExportPrimitiveType::DataTypeRSAllocation
270        "SAMPLER",      // RSExportPrimitiveType::DataTypeRSSampler
271        "SCRIPT",       // RSExportPrimitiveType::DataTypeRSScript
272        "MESH",         // RSExportPrimitiveType::DataTypeRSMesh
273        "PROGRAM_FRAGMENT",  // RSExportPrimitiveType::DataTypeRSProgramFragment
274        "PROGRAM_VERTEX",    // RSExportPrimitiveType::DataTypeRSProgramVertex
275        "PROGRAM_RASTER",    // RSExportPrimitiveType::DataTypeRSProgramRaster
276        "PROGRAM_STORE",     // RSExportPrimitiveType::DataTypeRSProgramStore
277        "FONT",       // RSExportPrimitiveType::DataTypeRSFont
278      };
279      unsigned TypeId = EPT->getType();
280
281      if (TypeId <
282          (sizeof(PrimitiveBuiltinElementConstructMap) / sizeof(const char*)))
283        return PrimitiveBuiltinElementConstructMap[ EPT->getType() ];
284    } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelA) {
285      if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
286        return "A_8";
287    } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGB) {
288      if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned565)
289        return "RGB_565";
290      else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
291        return "RGB_888";
292    } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGBA) {
293      if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned5551)
294        return "RGBA_5551";
295      else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned4444)
296        return "RGBA_4444";
297      else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
298        return "RGBA_8888";
299    }
300  } else if (ET->getClass() == RSExportType::ExportClassVector) {
301    const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(ET);
302    if (EVT->getKind() == RSExportPrimitiveType::DataKindUser) {
303      if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
304        if (EVT->getNumElement() == 2)
305          return "F32_2";
306        else if (EVT->getNumElement() == 3)
307          return "F32_3";
308        else if (EVT->getNumElement() == 4)
309          return "F32_4";
310      } else if (EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
311        if (EVT->getNumElement() == 4)
312          return "U8_4";
313      }
314    }
315  } else if (ET->getClass() == RSExportType::ExportClassPointer) {
316    // Treat pointer type variable as unsigned int
317    // TODO(zonr): this is target dependent
318    return "USER_I32";
319  }
320
321  return NULL;
322}
323
324static const char *GetElementDataKindName(RSExportPrimitiveType::DataKind DK) {
325  static const char *ElementDataKindNameMap[] = {
326    "Element.DataKind.USER",        // RSExportPrimitiveType::DataKindUser
327    "Element.DataKind.PIXEL_L",     // RSExportPrimitiveType::DataKindPixelL
328    "Element.DataKind.PIXEL_A",     // RSExportPrimitiveType::DataKindPixelA
329    "Element.DataKind.PIXEL_LA",    // RSExportPrimitiveType::DataKindPixelLA
330    "Element.DataKind.PIXEL_RGB",   // RSExportPrimitiveType::DataKindPixelRGB
331    "Element.DataKind.PIXEL_RGBA",  // RSExportPrimitiveType::DataKindPixelRGBA
332  };
333
334  if (static_cast<unsigned>(DK) <
335      (sizeof(ElementDataKindNameMap) / sizeof(const char*)))
336    return ElementDataKindNameMap[ DK ];
337  else
338    return NULL;
339}
340
341static const char *GetElementDataTypeName(RSExportPrimitiveType::DataType DT) {
342  static const char *ElementDataTypeNameMap[] = {
343    NULL,                           // RSExportPrimitiveType::DataTypeFloat16
344    "Element.DataType.FLOAT_32",    // RSExportPrimitiveType::DataTypeFloat32
345    "Element.DataType.FLOAT_64",    // RSExportPrimitiveType::DataTypeFloat64
346    "Element.DataType.SIGNED_8",    // RSExportPrimitiveType::DataTypeSigned8
347    "Element.DataType.SIGNED_16",   // RSExportPrimitiveType::DataTypeSigned16
348    "Element.DataType.SIGNED_32",   // RSExportPrimitiveType::DataTypeSigned32
349    "Element.DataType.SIGNED_64",   // RSExportPrimitiveType::DataTypeSigned64
350    "Element.DataType.UNSIGNED_8",  // RSExportPrimitiveType::DataTypeUnsigned8
351    "Element.DataType.UNSIGNED_16", // RSExportPrimitiveType::DataTypeUnsigned16
352    "Element.DataType.UNSIGNED_32", // RSExportPrimitiveType::DataTypeUnsigned32
353    NULL,                           // RSExportPrimitiveType::DataTypeUnsigned64
354    "Element.DataType.BOOLEAN",     // RSExportPrimitiveType::DataTypeBoolean
355
356    // RSExportPrimitiveType::DataTypeUnsigned565
357    "Element.DataType.UNSIGNED_5_6_5",
358    // RSExportPrimitiveType::DataTypeUnsigned5551
359    "Element.DataType.UNSIGNED_5_5_5_1",
360    // RSExportPrimitiveType::DataTypeUnsigned4444
361    "Element.DataType.UNSIGNED_4_4_4_4",
362
363    // RSExportPrimitiveType::DataTypeRSMatrix2x2
364    "Element.DataType.RS_MATRIX_2X2",
365    // RSExportPrimitiveType::DataTypeRSMatrix3x3
366    "Element.DataType.RS_MATRIX_3X3",
367    // RSExportPrimitiveType::DataTypeRSMatrix4x4
368    "Element.DataType.RS_MATRIX_4X4",
369
370    "Element.DataType.RS_ELEMENT",  // RSExportPrimitiveType::DataTypeRSElement
371    "Element.DataType.RS_TYPE",     // RSExportPrimitiveType::DataTypeRSType
372      // RSExportPrimitiveType::DataTypeRSAllocation
373    "Element.DataType.RS_ALLOCATION",
374      // RSExportPrimitiveType::DataTypeRSSampler
375    "Element.DataType.RS_SAMPLER",
376      // RSExportPrimitiveType::DataTypeRSScript
377    "Element.DataType.RS_SCRIPT",
378      // RSExportPrimitiveType::DataTypeRSMesh
379    "Element.DataType.RS_MESH",
380      // RSExportPrimitiveType::DataTypeRSProgramFragment
381    "Element.DataType.RS_PROGRAM_FRAGMENT",
382      // RSExportPrimitiveType::DataTypeRSProgramVertex
383    "Element.DataType.RS_PROGRAM_VERTEX",
384      // RSExportPrimitiveType::DataTypeRSProgramRaster
385    "Element.DataType.RS_PROGRAM_RASTER",
386      // RSExportPrimitiveType::DataTypeRSProgramStore
387    "Element.DataType.RS_PROGRAM_STORE",
388      // RSExportPrimitiveType::DataTypeRSFont
389    "Element.DataType.RS_FONT",
390  };
391
392  if (static_cast<unsigned>(DT) <
393      (sizeof(ElementDataTypeNameMap) / sizeof(const char*)))
394    return ElementDataTypeNameMap[ DT ];
395  else
396    return NULL;
397}
398
399bool RSReflection::openScriptFile(Context &C,
400                                  const std::string &ClassName,
401                                  std::string &ErrorMsg) {
402  if (!C.mUseStdout) {
403    C.mOF.clear();
404    std::string _path = RSSlangReflectUtils::ComputePackagedPath(
405        mRSContext->getReflectJavaPathName().c_str(),
406        C.getPackageName().c_str());
407
408    RSSlangReflectUtils::mkdir_p(_path.c_str());
409    C.mOF.open((_path + "/" + ClassName + ".java").c_str());
410    if (!C.mOF.good()) {
411      ErrorMsg = "failed to open file '" + _path + "/" + ClassName
412          + ".java' for write";
413
414      return false;
415    }
416  }
417  return true;
418}
419
420/********************** Methods to generate script class **********************/
421bool RSReflection::genScriptClass(Context &C,
422                                  const std::string &ClassName,
423                                  std::string &ErrorMsg) {
424  // Open the file
425  if (!openScriptFile(C, ClassName, ErrorMsg)) {
426    return false;
427  }
428
429  if (!C.startClass(Context::AM_Public,
430                    false,
431                    ClassName,
432                    RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
433                    ErrorMsg))
434    return false;
435
436  genScriptClassConstructor(C);
437
438  // Reflect export variable
439  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
440           E = mRSContext->export_vars_end();
441       I != E;
442       I++)
443    genExportVariable(C, *I);
444
445  // Reflect export function
446  for (RSContext::const_export_func_iterator
447           I = mRSContext->export_funcs_begin(),
448           E = mRSContext->export_funcs_end();
449       I != E; I++)
450    genExportFunction(C, *I);
451
452  C.endClass();
453
454  return true;
455}
456
457void RSReflection::genScriptClassConstructor(Context &C) {
458  C.indent() << "// Constructor" << std::endl;
459  C.startFunction(Context::AM_Public,
460                  false,
461                  NULL,
462                  C.getClassName(),
463                  4,
464                  "RenderScript",
465                  "rs",
466                  "Resources",
467                  "resources",
468                  "int",
469                  "id",
470                  "boolean",
471                  "isRoot");
472  // Call constructor of super class
473  C.indent() << "super(rs, resources, id, isRoot);" << std::endl;
474
475  // If an exported variable has initial value, reflect it
476
477  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
478           E = mRSContext->export_vars_end();
479       I != E;
480       I++) {
481    const RSExportVar *EV = *I;
482    if (!EV->getInit().isUninit())
483      genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
484  }
485
486  C.endFunction();
487  return;
488}
489
490void RSReflection::genInitBoolExportVariable(Context &C,
491                                             const std::string &VarName,
492                                             const clang::APValue &Val) {
493  assert(!Val.isUninit() && "Not a valid initializer");
494
495  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
496  assert((Val.getKind() == clang::APValue::Int) &&
497         "Bool type has wrong initial APValue");
498
499  if (Val.getInt().getSExtValue() == 0) {
500    C.out() << "false";
501  } else {
502    C.out() << "true";
503  }
504  C.out() << ";" << std::endl;
505
506  return;
507}
508
509void RSReflection::genInitPrimitiveExportVariable(Context &C,
510                                                  const std::string &VarName,
511                                                  const clang::APValue &Val) {
512  assert(!Val.isUninit() && "Not a valid initializer");
513
514  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
515  switch (Val.getKind()) {
516    case clang::APValue::Int: {
517      C.out() << Val.getInt().getSExtValue();
518      break;
519    }
520    case clang::APValue::Float: {
521      llvm::APFloat apf = Val.getFloat();
522      if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
523        C.out() << apf.convertToFloat() << "f";
524      } else {
525        C.out() << apf.convertToDouble();
526      }
527      break;
528    }
529
530    case clang::APValue::ComplexInt:
531    case clang::APValue::ComplexFloat:
532    case clang::APValue::LValue:
533    case clang::APValue::Vector: {
534      assert(false && "Primitive type cannot have such kind of initializer");
535      break;
536    }
537    default: {
538      assert(false && "Unknown kind of initializer");
539    }
540  }
541  C.out() << ";" << std::endl;
542
543  return;
544}
545
546void RSReflection::genInitExportVariable(Context &C,
547                                         const RSExportType *ET,
548                                         const std::string &VarName,
549                                         const clang::APValue &Val) {
550  assert(!Val.isUninit() && "Not a valid initializer");
551
552  switch (ET->getClass()) {
553    case RSExportType::ExportClassPrimitive:
554    case RSExportType::ExportClassConstantArray: {
555      const RSExportPrimitiveType *EPT =
556          static_cast<const RSExportPrimitiveType*>(ET);
557      if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) {
558        genInitBoolExportVariable(C, VarName, Val);
559      } else {
560        genInitPrimitiveExportVariable(C, VarName, Val);
561      }
562      break;
563    }
564
565    case RSExportType::ExportClassPointer: {
566      if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
567        std::cout << "Initializer which is non-NULL to pointer type variable "
568                     "will be ignored" << std::endl;
569      break;
570    }
571
572    case RSExportType::ExportClassVector: {
573      const RSExportVectorType *EVT =
574          static_cast<const RSExportVectorType*>(ET);
575      switch (Val.getKind()) {
576        case clang::APValue::Int:
577        case clang::APValue::Float: {
578          for (int i = 0; i < EVT->getNumElement(); i++) {
579            std::string Name =  VarName + "." + GetVectorAccessor(i);
580            genInitPrimitiveExportVariable(C, Name, Val);
581          }
582          break;
583        }
584
585        case clang::APValue::Vector: {
586          C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "
587                     << GetVectorTypeName(EVT) << "();" << std::endl;
588
589          unsigned NumElements =
590              std::min(static_cast<unsigned>(EVT->getNumElement()),
591                       Val.getVectorLength());
592          for (unsigned i = 0; i < NumElements; i++) {
593            const clang::APValue &ElementVal = Val.getVectorElt(i);
594            std::string Name = VarName + "." + GetVectorAccessor(i);
595            genInitPrimitiveExportVariable(C, Name, ElementVal);
596          }
597          break;
598        }
599
600        case clang::APValue::Uninitialized:
601        case clang::APValue::ComplexInt:
602        case clang::APValue::ComplexFloat:
603        case clang::APValue::LValue: {
604          assert(false && "Unexpected type of value of initializer.");
605        }
606      }
607      break;
608    }
609
610    // TODO(zonr): Resolving initializer of a record type variable is complex.
611    // It cannot obtain by just simply evaluating the initializer expression.
612    case RSExportType::ExportClassRecord: {
613#if 0
614      unsigned InitIndex = 0;
615      const RSExportRecordType *ERT =
616          static_cast<const RSExportRecordType*>(ET);
617
618      assert((Val.getKind() == clang::APValue::Vector) && "Unexpected type of "
619             "initializer for record type variable");
620
621      C.indent() << RS_EXPORT_VAR_PREFIX << VarName
622                 << " = new "RS_TYPE_CLASS_NAME_PREFIX << ERT->getName()
623                 <<  "."RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
624
625      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
626               E = ERT->fields_end();
627           I != E;
628           I++) {
629        const RSExportRecordType::Field *F = *I;
630        std::string FieldName = VarName + "." + F->getName();
631
632        if (InitIndex > Val.getVectorLength())
633          break;
634
635        genInitPrimitiveExportVariable(C,
636                                       FieldName,
637                                       Val.getVectorElt(InitIndex++));
638      }
639#endif
640      assert(false && "Unsupported initializer for record type variable "
641                      "currently");
642      break;
643    }
644
645    default: {
646      assert(false && "Unknown class of type");
647    }
648  }
649  return;
650}
651
652void RSReflection::genExportVariable(Context &C, const RSExportVar *EV) {
653  const RSExportType *ET = EV->getType();
654
655  C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX
656             << EV->getName() << " = " << C.getNextExportVarSlot() << ";"
657             << std::endl;
658
659  switch (ET->getClass()) {
660    case RSExportType::ExportClassPrimitive:
661    case RSExportType::ExportClassConstantArray: {
662      genPrimitiveTypeExportVariable(C, EV);
663      break;
664    }
665
666    case RSExportType::ExportClassPointer: {
667      genPointerTypeExportVariable(C, EV);
668      break;
669    }
670
671    case RSExportType::ExportClassVector: {
672      genVectorTypeExportVariable(C, EV);
673      break;
674    }
675
676    case RSExportType::ExportClassRecord: {
677      genRecordTypeExportVariable(C, EV);
678      break;
679    }
680
681    default: {
682      assert(false && "Unknown class of type");
683    }
684  }
685
686  return;
687}
688
689void RSReflection::genExportFunction(Context &C, const RSExportFunc *EF) {
690  C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX
691             << EF->getName() << " = " << C.getNextExportFuncSlot() << ";"
692             << std::endl;
693
694  // invoke_*()
695  Context::ArgTy Args;
696
697  for (RSExportFunc::const_param_iterator I = EF->params_begin(),
698           E = EF->params_end();
699       I != E;
700       I++) {
701    const RSExportFunc::Parameter *P = *I;
702    Args.push_back(make_pair(GetTypeName(P->getType()), P->getName()));
703  }
704
705  C.startFunction(Context::AM_Public,
706                  false,
707                  "void",
708                  "invoke_" + EF->getName(),
709                  Args);
710
711  if (!EF->hasParam()) {
712    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");"
713               << std::endl;
714  } else {
715    const RSExportRecordType *ERT = EF->getParamPacketType();
716    std::string FieldPackerName = EF->getName() + "_fp";
717
718    if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
719      genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
720
721    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", "
722               << FieldPackerName << ");" << std::endl;
723  }
724
725  C.endFunction();
726  return;
727}
728
729void RSReflection::genPrimitiveTypeExportVariable(Context &C,
730                                                  const RSExportVar *EV) {
731  assert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive ||
732          EV->getType()->getClass() == RSExportType::ExportClassConstantArray)
733         && "Variable should be type of primitive here");
734
735  const RSExportPrimitiveType *EPT =
736      static_cast<const RSExportPrimitiveType*>(EV->getType());
737  const char *TypeName = GetPrimitiveTypeName(EPT);
738
739  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
740             << EV->getName() << ";" << std::endl;
741
742  // set_*()
743  if (!EV->isConst()) {
744    C.startFunction(Context::AM_Public,
745                    false,
746                    "void",
747                    "set_" + EV->getName(),
748                    1,
749                    TypeName,
750                    "v");
751    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
752
753    if (EPT->isRSObjectType())
754      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
755                 << ", (v == null) ? 0 : v.getID());" << std::endl;
756    else
757      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
758                 << ", v);" << std::endl;
759
760    C.endFunction();
761  }
762
763  genGetExportVariable(C, TypeName, EV->getName());
764
765  return;
766}
767
768void RSReflection::genPointerTypeExportVariable(Context &C,
769                                                const RSExportVar *EV) {
770  const RSExportType *ET = EV->getType();
771  const RSExportType *PointeeType;
772  std::string TypeName;
773
774  assert((ET->getClass() == RSExportType::ExportClassPointer) &&
775         "Variable should be type of pointer here");
776
777  PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
778  TypeName = GetTypeName(ET);
779
780  // bind_*()
781  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
782             << EV->getName() << ";" << std::endl;
783
784  C.startFunction(Context::AM_Public,
785                  false,
786                  "void",
787                  "bind_" + EV->getName(),
788                  1,
789                  TypeName.c_str(),
790                  "v");
791
792  C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
793  C.indent() << "if (v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX
794             << EV->getName() << ");" << std::endl;
795
796  if (PointeeType->getClass() == RSExportType::ExportClassRecord)
797    C.indent() << "else bindAllocation(v.getAllocation(), "
798        RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");"
799               << std::endl;
800  else
801    C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX
802               << EV->getName() << ");" << std::endl;
803
804  C.endFunction();
805
806  genGetExportVariable(C, TypeName, EV->getName());
807
808  return;
809}
810
811void RSReflection::genVectorTypeExportVariable(Context &C,
812                                               const RSExportVar *EV) {
813  assert((EV->getType()->getClass() == RSExportType::ExportClassVector) &&
814         "Variable should be type of vector here");
815
816  const RSExportVectorType *EVT =
817      static_cast<const RSExportVectorType*>(EV->getType());
818  const char *TypeName = GetVectorTypeName(EVT);
819  const char *FieldPackerName = "fp";
820
821  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
822             << EV->getName() << ";" << std::endl;
823
824  // set_*()
825  if (!EV->isConst()) {
826    C.startFunction(Context::AM_Public,
827                    false,
828                    "void",
829                    "set_" + EV->getName(),
830                    1,
831                    TypeName,
832                    "v");
833    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
834
835    if (genCreateFieldPacker(C, EVT, FieldPackerName))
836      genPackVarOfType(C, EVT, "v", FieldPackerName);
837    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
838               << FieldPackerName << ");" << std::endl;
839
840    C.endFunction();
841  }
842
843  genGetExportVariable(C, TypeName, EV->getName());
844  return;
845}
846
847void RSReflection::genRecordTypeExportVariable(Context &C,
848                                               const RSExportVar *EV) {
849  assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
850         "Variable should be type of struct here");
851
852  const RSExportRecordType *ERT =
853      static_cast<const RSExportRecordType*>(EV->getType());
854  std::string TypeName =
855      RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
856  const char *FieldPackerName = "fp";
857
858  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
859             << EV->getName() << ";" << std::endl;
860
861  // set_*()
862  if (!EV->isConst()) {
863    C.startFunction(Context::AM_Public,
864                    false,
865                    "void",
866                    "set_" + EV->getName(),
867                    1,
868                    TypeName.c_str(),
869                    "v");
870    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
871
872    if (genCreateFieldPacker(C, ERT, FieldPackerName))
873      genPackVarOfType(C, ERT, "v", FieldPackerName);
874    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
875               << ", " << FieldPackerName << ");" << std::endl;
876
877    C.endFunction();
878  }
879
880  genGetExportVariable(C, TypeName.c_str(), EV->getName());
881  return;
882}
883
884void RSReflection::genGetExportVariable(Context &C,
885                                        const std::string &TypeName,
886                                        const std::string &VarName) {
887  C.startFunction(Context::AM_Public,
888                  false,
889                  TypeName.c_str(),
890                  "get_" + VarName,
891                  0);
892
893  C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << std::endl;
894
895  C.endFunction();
896  return;
897}
898
899/******************* Methods to generate script class /end *******************/
900
901bool RSReflection::genCreateFieldPacker(Context &C,
902                                        const RSExportType *ET,
903                                        const char *FieldPackerName) {
904  size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
905  if (AllocSize > 0)
906    C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
907               << AllocSize << ");" << std::endl;
908  else
909    return false;
910  return true;
911}
912
913void RSReflection::genPackVarOfType(Context &C,
914                                    const RSExportType *ET,
915                                    const char *VarName,
916                                    const char *FieldPackerName) {
917  switch (ET->getClass()) {
918    case RSExportType::ExportClassPrimitive:
919    case RSExportType::ExportClassVector: {
920      C.indent() << FieldPackerName << "."
921                 << GetPackerAPIName(
922                     static_cast<const RSExportPrimitiveType*>(ET))
923                 << "(" << VarName << ");" << std::endl;
924      break;
925    }
926    case RSExportType::ExportClassConstantArray: {
927      if (ET->getName().compare("addObj") == 0) {
928        C.indent() << FieldPackerName << "." << "addObj" << "("
929                   << VarName << ");" << std::endl;
930      } else {
931        C.indent() << FieldPackerName << "."
932                   << GetPackerAPIName(
933                       static_cast<const RSExportPrimitiveType*>(ET))
934                   << "(" << VarName << ");" << std::endl;
935      }
936      break;
937    }
938
939    case RSExportType::ExportClassPointer: {
940      // Must reflect as type Allocation in Java
941      const RSExportType *PointeeType =
942          static_cast<const RSExportPointerType*>(ET)->getPointeeType();
943
944      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
945        C.indent() << FieldPackerName << ".addI32(" << VarName
946                   << ".getPtr());" << std::endl;
947      else
948        C.indent() << FieldPackerName << ".addI32(" << VarName
949                   << ".getAllocation().getPtr());" << std::endl;
950      break;
951    }
952
953    case RSExportType::ExportClassRecord: {
954      const RSExportRecordType *ERT =
955          static_cast<const RSExportRecordType*>(ET);
956      // Relative pos from now on in field packer
957      unsigned Pos = 0;
958
959      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
960               E = ERT->fields_end();
961           I != E;
962           I++) {
963        const RSExportRecordType::Field *F = *I;
964        std::string FieldName;
965        size_t FieldOffset = F->getOffsetInParent();
966        size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
967        size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
968
969        if (VarName != NULL)
970          FieldName = VarName + ("." + F->getName());
971        else
972          FieldName = F->getName();
973
974        if (FieldOffset > Pos)
975          C.indent() << FieldPackerName << ".skip("
976                     << (FieldOffset - Pos) << ");" << std::endl;
977
978        genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
979
980        // There is padding in the field type
981        if (FieldAllocSize > FieldStoreSize)
982            C.indent() << FieldPackerName << ".skip("
983                       << (FieldAllocSize - FieldStoreSize)
984                       << ");" << std::endl;
985
986          Pos = FieldOffset + FieldAllocSize;
987      }
988
989      // There maybe some padding after the struct
990      size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
991      if (Padding > 0)
992        C.indent() << FieldPackerName << ".skip(" << Padding << ");"
993                   << std::endl;
994      break;
995    }
996    default: {
997      assert(false && "Unknown class of type");
998    }
999  }
1000
1001  return;
1002}
1003
1004void RSReflection::genNewItemBufferIfNull(Context &C, const char *Index) {
1005  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "
1006      RS_TYPE_ITEM_BUFFER_NAME" = "
1007      "new "RS_TYPE_ITEM_CLASS_NAME"[mType.getX() /* count */];"
1008             << std::endl;
1009  if (Index != NULL)
1010    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] == null) "
1011        RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = "
1012        "new "RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
1013  return;
1014}
1015
1016void RSReflection::genNewItemBufferPackerIfNull(Context &C) {
1017  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_PACKER_NAME" == null) "
1018      RS_TYPE_ITEM_BUFFER_PACKER_NAME" = "
1019      "new FieldPacker("
1020      RS_TYPE_ITEM_CLASS_NAME".sizeof * mType.getX() /* count */);"
1021             << std::endl;
1022  return;
1023}
1024
1025/********************** Methods to generate type class  **********************/
1026bool RSReflection::genTypeClass(Context &C,
1027                                const RSExportRecordType *ERT,
1028                                std::string &ErrorMsg) {
1029  std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
1030
1031  // Open the file
1032  if (!openScriptFile(C, ClassName, ErrorMsg)) {
1033    return false;
1034  }
1035
1036  if (!C.startClass(Context::AM_Public,
1037                    false,
1038                    ClassName,
1039                    RS_TYPE_CLASS_SUPER_CLASS_NAME,
1040                    ErrorMsg))
1041    return false;
1042
1043  if (!genTypeItemClass(C, ERT, ErrorMsg))
1044    return false;
1045
1046  // Declare item buffer and item buffer packer
1047  C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[]"
1048      ";" << std::endl;
1049  C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";"
1050             << std::endl;
1051
1052  genTypeClassConstructor(C, ERT);
1053  genTypeClassCopyToArray(C, ERT);
1054  genTypeClassItemSetter(C, ERT);
1055  genTypeClassItemGetter(C, ERT);
1056  genTypeClassComponentSetter(C, ERT);
1057  genTypeClassComponentGetter(C, ERT);
1058  genTypeClassCopyAll(C, ERT);
1059
1060  C.endClass();
1061
1062  C.resetFieldIndex();
1063  C.clearFieldIndexMap();
1064
1065  return true;
1066}
1067
1068bool RSReflection::genTypeItemClass(Context &C,
1069                                    const RSExportRecordType *ERT,
1070                                    std::string &ErrorMsg) {
1071  C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
1072  C.startBlock();
1073
1074  C.indent() << "public static final int sizeof = "
1075             << RSExportType::GetTypeAllocSize(ERT) << ";" << std::endl;
1076
1077  // Member elements
1078  C.out() << std::endl;
1079  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1080           FE = ERT->fields_end();
1081       FI != FE;
1082       FI++) {
1083    C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
1084               << ";" << std::endl;
1085  }
1086
1087  // Constructor
1088  C.out() << std::endl;
1089  C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
1090  C.startBlock();
1091
1092  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1093           FE = ERT->fields_end();
1094       FI != FE;
1095       FI++) {
1096    const RSExportRecordType::Field *F = *FI;
1097    if ((F->getType()->getClass() == RSExportType::ExportClassVector) ||
1098        (F->getType()->getClass() == RSExportType::ExportClassRecord) ||
1099        (F->getType()->getClass() == RSExportType::ExportClassConstantArray)) {
1100      C.indent() << F->getName() << " = new " << GetTypeName(F->getType())
1101                 << "();" << std::endl;
1102    }
1103  }
1104
1105  // end Constructor
1106  C.endBlock();
1107
1108  // end Item class
1109  C.endBlock();
1110
1111  return true;
1112}
1113
1114void RSReflection::genTypeClassConstructor(Context &C,
1115                                           const RSExportRecordType *ERT) {
1116  const char *RenderScriptVar = "rs";
1117
1118  C.startFunction(Context::AM_Public,
1119                  true,
1120                  "Element",
1121                  "createElement",
1122                  1,
1123                  "RenderScript",
1124                  RenderScriptVar);
1125  genBuildElement(C, ERT, RenderScriptVar);
1126  C.endFunction();
1127
1128  C.startFunction(Context::AM_Public,
1129                  false,
1130                  NULL,
1131                  C.getClassName(),
1132                  2,
1133                  "RenderScript",
1134                  RenderScriptVar,
1135                  "int",
1136                  "count");
1137
1138  C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl;
1139  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl;
1140  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
1141             << std::endl;
1142  // Call init() in super class
1143  C.indent() << "init(" << RenderScriptVar << ", count);" << std::endl;
1144  C.endFunction();
1145
1146  return;
1147}
1148
1149void RSReflection::genTypeClassCopyToArray(Context &C,
1150                                           const RSExportRecordType *ERT) {
1151  C.startFunction(Context::AM_Private,
1152                  false,
1153                  "void",
1154                  "copyToArray",
1155                  2,
1156                  RS_TYPE_ITEM_CLASS_NAME,
1157                  "i",
1158                  "int",
1159                  "index");
1160
1161  genNewItemBufferPackerIfNull(C);
1162  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1163      ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" << std::endl;
1164
1165  genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1166
1167  C.endFunction();
1168  return;
1169}
1170
1171void RSReflection::genTypeClassItemSetter(Context &C,
1172                                          const RSExportRecordType *ERT) {
1173  C.startFunction(Context::AM_Public,
1174                  false,
1175                  "void",
1176                  "set",
1177                  3,
1178                  RS_TYPE_ITEM_CLASS_NAME,
1179                  "i",
1180                  "int",
1181                  "index",
1182                  "boolean",
1183                  "copyNow");
1184  genNewItemBufferIfNull(C, NULL);
1185  C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << std::endl;
1186
1187  C.indent() << "if (copyNow) ";
1188  C.startBlock();
1189
1190  C.indent() << "copyToArray(i, index);" << std::endl;
1191  C.indent() << "mAllocation.subData1D(index, 1, "
1192      RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << std::endl;
1193
1194  // End of if (copyNow)
1195  C.endBlock();
1196
1197  C.endFunction();
1198  return;
1199}
1200
1201void RSReflection::genTypeClassItemGetter(Context &C,
1202                                          const RSExportRecordType *ERT) {
1203  C.startFunction(Context::AM_Public,
1204                  false,
1205                  RS_TYPE_ITEM_CLASS_NAME,
1206                  "get",
1207                  1,
1208                  "int",
1209                  "index");
1210  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;"
1211             << std::endl;
1212  C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index];" << std::endl;
1213  C.endFunction();
1214  return;
1215}
1216
1217void RSReflection::genTypeClassComponentSetter(Context &C,
1218                                               const RSExportRecordType *ERT) {
1219  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1220           FE = ERT->fields_end();
1221       FI != FE;
1222       FI++) {
1223    const RSExportRecordType::Field *F = *FI;
1224    size_t FieldOffset = F->getOffsetInParent();
1225    size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1226    unsigned FieldIndex = C.getFieldIndex(F);
1227
1228    C.startFunction(Context::AM_Public,
1229                    false,
1230                    "void",
1231                    "set_" + F->getName(), 3,
1232                    "int",
1233                    "index",
1234                    GetTypeName(F->getType()).c_str(),
1235                    "v",
1236                    "boolean",
1237                    "copyNow");
1238    genNewItemBufferPackerIfNull(C);
1239    genNewItemBufferIfNull(C, "index");
1240    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
1241               << " = v;" << std::endl;
1242
1243    C.indent() << "if (copyNow) ";
1244    C.startBlock();
1245
1246    if (FieldOffset > 0)
1247      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "
1248          RS_TYPE_ITEM_CLASS_NAME".sizeof + " << FieldOffset << ");"
1249                 << std::endl;
1250    else
1251      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "
1252          RS_TYPE_ITEM_CLASS_NAME".sizeof);" << std::endl;
1253    genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1254
1255    C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");"
1256               << std::endl;
1257    genPackVarOfType(C, F->getType(), "v", "fp");
1258    C.indent() << "mAllocation.subElementData(index, " << FieldIndex << ", fp);"
1259               << std::endl;
1260
1261    // End of if (copyNow)
1262    C.endBlock();
1263
1264    C.endFunction();
1265  }
1266  return;
1267}
1268
1269void RSReflection::genTypeClassComponentGetter(Context &C,
1270                                               const RSExportRecordType *ERT) {
1271  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1272           FE = ERT->fields_end();
1273       FI != FE;
1274       FI++) {
1275    const RSExportRecordType::Field *F = *FI;
1276    C.startFunction(Context::AM_Public,
1277                    false,
1278                    GetTypeName(F->getType()).c_str(),
1279                    "get_" + F->getName(),
1280                    1,
1281                    "int",
1282                    "index");
1283    C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
1284               << ";" << std::endl;
1285    C.endFunction();
1286  }
1287  return;
1288}
1289
1290void RSReflection::genTypeClassCopyAll(Context &C,
1291                                       const RSExportRecordType *ERT) {
1292  C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
1293
1294  C.indent() << "for (int ct=0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++) "
1295      "copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);"
1296             << std::endl;
1297  C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());"
1298             << std::endl;
1299
1300  C.endFunction();
1301  return;
1302}
1303
1304/******************** Methods to generate type class /end ********************/
1305
1306/********** Methods to create Element in Java of given record type ***********/
1307void RSReflection::genBuildElement(Context &C, const RSExportRecordType *ERT,
1308                                   const char *RenderScriptVar) {
1309  const char *ElementBuilderName = "eb";
1310
1311  // Create element builder
1312  //    C.startBlock(true);
1313
1314  C.indent() << "Element.Builder " << ElementBuilderName << " = "
1315      "new Element.Builder(" << RenderScriptVar << ");" << std::endl;
1316
1317  // eb.add(...)
1318  genAddElementToElementBuilder(C,
1319                                ERT,
1320                                "",
1321                                ElementBuilderName,
1322                                RenderScriptVar);
1323
1324  C.indent() << "return " << ElementBuilderName << ".create();" << std::endl;
1325
1326  //   C.endBlock();
1327  return;
1328}
1329
1330#define EB_ADD(x)                                                       \
1331  C.indent() << ElementBuilderName \
1332             << ".add(Element." << x << ", \"" << VarName << "\");" \
1333             << std::endl;                                               \
1334  C.incFieldIndex()
1335
1336void RSReflection::genAddElementToElementBuilder(Context &C,
1337                                                 const RSExportType *ET,
1338                                                 const std::string &VarName,
1339                                                 const char *ElementBuilderName,
1340                                                 const char *RenderScriptVar) {
1341  const char *ElementConstruct = GetBuiltinElementConstruct(ET);
1342
1343  if (ElementConstruct != NULL) {
1344    EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
1345  } else {
1346    if ((ET->getClass() == RSExportType::ExportClassPrimitive) ||
1347        (ET->getClass() == RSExportType::ExportClassVector)    ||
1348        (ET->getClass() == RSExportType::ExportClassConstantArray)
1349        ) {
1350      const RSExportPrimitiveType *EPT =
1351          static_cast<const RSExportPrimitiveType*>(ET);
1352      const char *DataKindName = GetElementDataKindName(EPT->getKind());
1353      const char *DataTypeName = GetElementDataTypeName(EPT->getType());
1354      int Size = (ET->getClass() == RSExportType::ExportClassVector) ?
1355          static_cast<const RSExportVectorType*>(ET)->getNumElement() :
1356          1;
1357
1358      switch (EPT->getKind()) {
1359        case RSExportPrimitiveType::DataKindPixelL:
1360        case RSExportPrimitiveType::DataKindPixelA:
1361        case RSExportPrimitiveType::DataKindPixelLA:
1362        case RSExportPrimitiveType::DataKindPixelRGB:
1363        case RSExportPrimitiveType::DataKindPixelRGBA: {
1364          // Element.createPixel()
1365          EB_ADD("createPixel(" << RenderScriptVar << ", "
1366                                << DataTypeName << ", "
1367                                << DataKindName << ")");
1368          break;
1369        }
1370        case RSExportPrimitiveType::DataKindUser:
1371        default: {
1372          if (EPT->getClass() == RSExportType::ExportClassPrimitive ||
1373              EPT->getClass() == RSExportType::ExportClassConstantArray) {
1374            // Element.createUser()
1375            EB_ADD("createUser(" << RenderScriptVar << ", "
1376                                 << DataTypeName << ")");
1377          } else {
1378            // ET->getClass() == RSExportType::ExportClassVector must hold here
1379            // Element.createVector()
1380            EB_ADD("createVector(" << RenderScriptVar << ", "
1381                                   << DataTypeName << ", "
1382                                   << Size << ")");
1383          }
1384          break;
1385        }
1386      }
1387    } else if (ET->getClass() == RSExportType::ExportClassPointer) {
1388      // Pointer type variable should be resolved in
1389      // GetBuiltinElementConstruct()
1390      assert(false && "??");
1391    } else if (ET->getClass() == RSExportType::ExportClassRecord) {
1392      // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
1393      //
1394      // TODO(zonr): Generalize these two function such that there's no
1395      //             duplicated codes.
1396      const RSExportRecordType *ERT =
1397          static_cast<const RSExportRecordType*>(ET);
1398      int Pos = 0;    // relative pos from now on
1399
1400      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1401               E = ERT->fields_end();
1402           I != E;
1403           I++) {
1404        const RSExportRecordType::Field *F = *I;
1405        std::string FieldName;
1406        int FieldOffset = F->getOffsetInParent();
1407        int FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1408        int FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1409
1410        if (!VarName.empty())
1411          FieldName = VarName + "." + F->getName();
1412        else
1413          FieldName = F->getName();
1414
1415        // Alignment
1416        genAddPaddingToElementBuiler(C,
1417                                     (FieldOffset - Pos),
1418                                     ElementBuilderName,
1419                                     RenderScriptVar);
1420
1421        // eb.add(...)
1422        C.addFieldIndexMapping(F);
1423        genAddElementToElementBuilder(C,
1424                                      F->getType(),
1425                                      FieldName,
1426                                      ElementBuilderName,
1427                                      RenderScriptVar);
1428
1429        // There is padding within the field type
1430        genAddPaddingToElementBuiler(C,
1431                                     (FieldAllocSize - FieldStoreSize),
1432                                     ElementBuilderName,
1433                                     RenderScriptVar);
1434
1435        Pos = FieldOffset + FieldAllocSize;
1436      }
1437
1438      // There maybe some padding after the struct
1439      //unsigned char align = RSExportType::GetTypeAlignment(ERT);
1440      //size_t siz = RSExportType::GetTypeAllocSize(ERT);
1441      size_t siz1 = RSExportType::GetTypeStoreSize(ERT);
1442
1443      genAddPaddingToElementBuiler(C,
1444                                   siz1 - Pos,
1445                                   ElementBuilderName,
1446                                   RenderScriptVar);
1447    } else {
1448      assert(false && "Unknown class of type");
1449    }
1450  }
1451}
1452
1453void RSReflection::genAddPaddingToElementBuiler(Context &C,
1454                                                int PaddingSize,
1455                                                const char *ElementBuilderName,
1456                                                const char *RenderScriptVar) {
1457  while (PaddingSize > 0) {
1458    const std::string &VarName = C.createPaddingField();
1459    if (PaddingSize >= 4) {
1460      EB_ADD("U32(" << RenderScriptVar << ")");
1461      PaddingSize -= 4;
1462    } else if (PaddingSize >= 2) {
1463      EB_ADD("U16(" << RenderScriptVar << ")");
1464      PaddingSize -= 2;
1465    } else if (PaddingSize >= 1) {
1466      EB_ADD("U8(" << RenderScriptVar << ")");
1467      PaddingSize -= 1;
1468    }
1469  }
1470  return;
1471}
1472
1473#undef EB_ADD
1474/******** Methods to create Element in Java of given record type /end ********/
1475
1476bool RSReflection::reflect(const char *OutputPackageName,
1477                           const std::string &InputFileName,
1478                           const std::string &OutputBCFileName) {
1479  Context *C = NULL;
1480  std::string ResourceId = "";
1481
1482  if (!GetClassNameFromFileName(OutputBCFileName, ResourceId))
1483    return false;
1484
1485  if (ResourceId.empty())
1486    ResourceId = "<Resource ID>";
1487
1488  if ((OutputPackageName == NULL) ||
1489      (*OutputPackageName == '\0') ||
1490      strcmp(OutputPackageName, "-") == 0)
1491    C = new Context(InputFileName, "<Package Name>", ResourceId, true);
1492  else
1493    C = new Context(InputFileName, OutputPackageName, ResourceId, false);
1494
1495  if (C != NULL) {
1496    std::string ErrorMsg, ScriptClassName;
1497    // class ScriptC_<ScriptName>
1498    if (!GetClassNameFromFileName(InputFileName, ScriptClassName))
1499      return false;
1500
1501    if (ScriptClassName.empty())
1502      ScriptClassName = "<Input Script Name>";
1503
1504    ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
1505
1506    if (mRSContext->getLicenseNote() != NULL) {
1507      C->setLicenseNote(*(mRSContext->getLicenseNote()));
1508    }
1509
1510    if (!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
1511      std::cerr << "Failed to generate class " << ScriptClassName << " ("
1512                << ErrorMsg << ")" << std::endl;
1513      return false;
1514    }
1515
1516    // class ScriptField_<TypeName>
1517    for (RSContext::const_export_type_iterator TI =
1518             mRSContext->export_types_begin(),
1519             TE = mRSContext->export_types_end();
1520         TI != TE;
1521         TI++) {
1522      const RSExportType *ET = TI->getValue();
1523
1524      if (ET->getClass() == RSExportType::ExportClassRecord) {
1525        const RSExportRecordType *ERT =
1526            static_cast<const RSExportRecordType*>(ET);
1527
1528        if (!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
1529          std::cerr << "Failed to generate type class for struct '"
1530                    << ERT->getName() << "' (" << ErrorMsg << ")" << std::endl;
1531          return false;
1532        }
1533      }
1534    }
1535  }
1536
1537  return true;
1538}
1539
1540/************************** RSReflection::Context **************************/
1541const char *const RSReflection::Context::ApacheLicenseNote =
1542    "/*\n"
1543    " * Copyright (C) 2010 The Android Open Source Project\n"
1544    " *\n"
1545    " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
1546    " * you may not use this file except in compliance with the License.\n"
1547    " * You may obtain a copy of the License at\n"
1548    " *\n"
1549    " *      http://www.apache.org/licenses/LICENSE-2.0\n"
1550    " *\n"
1551    " * Unless required by applicable law or agreed to in writing, software\n"
1552    " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
1553    " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
1554    "implied.\n"
1555    " * See the License for the specific language governing permissions and\n"
1556    " * limitations under the License.\n"
1557    " */\n"
1558    "\n";
1559
1560const char *const RSReflection::Context::Import[] = {
1561  // RenderScript java class
1562  "android.renderscript.*",
1563  // Import R
1564  "android.content.res.Resources",
1565  // Import for debugging
1566  "android.util.Log",
1567};
1568
1569const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) {
1570  switch (AM) {
1571    case AM_Public: return "public"; break;
1572    case AM_Protected: return "protected"; break;
1573    case AM_Private: return "private"; break;
1574    default: return ""; break;
1575  }
1576}
1577
1578bool RSReflection::Context::startClass(AccessModifier AM,
1579                                       bool IsStatic,
1580                                       const std::string &ClassName,
1581                                       const char *SuperClassName,
1582                                       std::string &ErrorMsg) {
1583  if (mVerbose)
1584    std::cout << "Generating " << ClassName << ".java ..." << std::endl;
1585
1586  // License
1587  out() << mLicenseNote;
1588
1589  // Notice of generated file
1590  out() << "/*" << std::endl;
1591  out() << " * This file is auto-generated. DO NOT MODIFY!" << std::endl;
1592  out() << " * The source RenderScript file: " << mInputRSFile << std::endl;
1593  out() << " */" << std::endl;
1594
1595  // Package
1596  if (!mPackageName.empty())
1597    out() << "package " << mPackageName << ";" << std::endl;
1598  out() << std::endl;
1599
1600  // Imports
1601  for (unsigned i = 0;i < (sizeof(Import) / sizeof(const char*)); i++)
1602    out() << "import " << Import[i] << ";" << std::endl;
1603  out() << std::endl;
1604
1605  // All reflected classes should be annotated as hidden, so that they won't
1606  // be exposed in SDK.
1607  out() << "/**" << std::endl;
1608  out() << " * @hide" << std::endl;
1609  out() << " */" << std::endl;
1610
1611  out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
1612        << ClassName;
1613  if (SuperClassName != NULL)
1614    out() << " extends " << SuperClassName;
1615
1616  startBlock();
1617
1618  mClassName = ClassName;
1619
1620  return true;
1621}
1622
1623void RSReflection::Context::endClass() {
1624  endBlock();
1625  if (!mUseStdout)
1626    mOF.close();
1627  clear();
1628  return;
1629}
1630
1631void RSReflection::Context::startBlock(bool ShouldIndent) {
1632  if (ShouldIndent)
1633    indent() << "{" << std::endl;
1634  else
1635    out() << " {" << std::endl;
1636  incIndentLevel();
1637  return;
1638}
1639
1640void RSReflection::Context::endBlock() {
1641  decIndentLevel();
1642  indent() << "}" << std::endl << std::endl;
1643  return;
1644}
1645
1646void RSReflection::Context::startTypeClass(const std::string &ClassName) {
1647  indent() << "public static class " << ClassName;
1648  startBlock();
1649  return;
1650}
1651
1652void RSReflection::Context::endTypeClass() {
1653  endBlock();
1654  return;
1655}
1656
1657void RSReflection::Context::startFunction(AccessModifier AM,
1658                                          bool IsStatic,
1659                                          const char *ReturnType,
1660                                          const std::string &FunctionName,
1661                                          int Argc, ...) {
1662  ArgTy Args;
1663  va_list vl;
1664  va_start(vl, Argc);
1665
1666  for (int i = 0; i < Argc; i++) {
1667    const char *ArgType = va_arg(vl, const char*);
1668    const char *ArgName = va_arg(vl, const char*);
1669
1670    Args.push_back(std::make_pair(ArgType, ArgName));
1671  }
1672  va_end(vl);
1673
1674  startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
1675
1676  return;
1677}
1678
1679void RSReflection::Context::startFunction(AccessModifier AM,
1680                                          bool IsStatic,
1681                                          const char *ReturnType,
1682                                          const std::string &FunctionName,
1683                                          const ArgTy &Args) {
1684  indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
1685           << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
1686
1687  bool FirstArg = true;
1688  for (ArgTy::const_iterator I = Args.begin(), E = Args.end();
1689       I != E;
1690       I++) {
1691    if (!FirstArg)
1692      out() << ", ";
1693    else
1694      FirstArg = false;
1695
1696    out() << I->first << " " << I->second;
1697  }
1698
1699  out() << ")";
1700  startBlock();
1701
1702  return;
1703}
1704
1705void RSReflection::Context::endFunction() {
1706  endBlock();
1707  return;
1708}
1709