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