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