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