slang_rs_reflection.cpp revision b6902e2d07d1a0f20723f8502c65438a18d8b6e3
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                  3,
510                  "RenderScript", "rs",
511                  "Resources", "resources",
512                  "int", "id");
513  // Call constructor of super class
514  C.indent() << "super(rs, resources, id);" << std::endl;
515
516  // If an exported variable has initial value, reflect it
517
518  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
519           E = mRSContext->export_vars_end();
520       I != E;
521       I++) {
522    const RSExportVar *EV = *I;
523    if (!EV->getInit().isUninit())
524      genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
525  }
526
527  C.endFunction();
528
529  C.startFunction(Context::AM_Public,
530                  false,
531                  NULL,
532                  C.getClassName(),
533                  4,
534                  "RenderScript", "rs",
535                  "Resources", "resources",
536                  "int", "id",
537                  "boolean", "isRoot");
538  // Call constructor of super class
539  C.indent() << "super(rs, resources, id);" << std::endl;
540
541  // If an exported variable has initial value, reflect it
542
543  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
544           E = mRSContext->export_vars_end();
545       I != E;
546       I++) {
547    const RSExportVar *EV = *I;
548    if (!EV->getInit().isUninit())
549      genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
550  }
551
552  C.endFunction();
553
554  return;
555}
556
557void RSReflection::genInitBoolExportVariable(Context &C,
558                                             const std::string &VarName,
559                                             const clang::APValue &Val) {
560  assert(!Val.isUninit() && "Not a valid initializer");
561
562  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
563  assert((Val.getKind() == clang::APValue::Int) &&
564         "Bool type has wrong initial APValue");
565
566  C.out() << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
567          << ";" << std::endl;
568
569  return;
570}
571
572void RSReflection::genInitPrimitiveExportVariable(Context &C,
573                                                  const std::string &VarName,
574                                                  const clang::APValue &Val) {
575  assert(!Val.isUninit() && "Not a valid initializer");
576
577  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
578  switch (Val.getKind()) {
579    case clang::APValue::Int: {
580      llvm::APInt api = Val.getInt();
581      C.out() << api.getSExtValue();
582      if (api.getBitWidth() > 32) {
583        C.out() << "L";
584      }
585      break;
586    }
587    case clang::APValue::Float: {
588      llvm::APFloat apf = Val.getFloat();
589      if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
590        C.out() << apf.convertToFloat() << "f";
591      } else {
592        C.out() << apf.convertToDouble();
593      }
594      break;
595    }
596
597    case clang::APValue::ComplexInt:
598    case clang::APValue::ComplexFloat:
599    case clang::APValue::LValue:
600    case clang::APValue::Vector: {
601      assert(false && "Primitive type cannot have such kind of initializer");
602      break;
603    }
604    default: {
605      assert(false && "Unknown kind of initializer");
606    }
607  }
608  C.out() << ";" << std::endl;
609
610  return;
611}
612
613void RSReflection::genInitExportVariable(Context &C,
614                                         const RSExportType *ET,
615                                         const std::string &VarName,
616                                         const clang::APValue &Val) {
617  assert(!Val.isUninit() && "Not a valid initializer");
618
619  switch (ET->getClass()) {
620    case RSExportType::ExportClassPrimitive: {
621      const RSExportPrimitiveType *EPT =
622          static_cast<const RSExportPrimitiveType*>(ET);
623      if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) {
624        genInitBoolExportVariable(C, VarName, Val);
625      } else {
626        genInitPrimitiveExportVariable(C, VarName, Val);
627      }
628      break;
629    }
630    case RSExportType::ExportClassPointer: {
631      if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
632        std::cout << "Initializer which is non-NULL to pointer type variable "
633                     "will be ignored" << std::endl;
634      break;
635    }
636    case RSExportType::ExportClassVector: {
637      const RSExportVectorType *EVT =
638          static_cast<const RSExportVectorType*>(ET);
639      switch (Val.getKind()) {
640        case clang::APValue::Int:
641        case clang::APValue::Float: {
642          for (unsigned i = 0; i < EVT->getNumElement(); i++) {
643            std::string Name =  VarName + "." + GetVectorAccessor(i);
644            genInitPrimitiveExportVariable(C, Name, Val);
645          }
646          break;
647        }
648        case clang::APValue::Vector: {
649          C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "
650                     << GetVectorTypeName(EVT) << "();" << std::endl;
651
652          unsigned NumElements =
653              std::min(static_cast<unsigned>(EVT->getNumElement()),
654                       Val.getVectorLength());
655          for (unsigned i = 0; i < NumElements; i++) {
656            const clang::APValue &ElementVal = Val.getVectorElt(i);
657            std::string Name = VarName + "." + GetVectorAccessor(i);
658            genInitPrimitiveExportVariable(C, Name, ElementVal);
659          }
660          break;
661        }
662        case clang::APValue::Uninitialized:
663        case clang::APValue::ComplexInt:
664        case clang::APValue::ComplexFloat:
665        case clang::APValue::LValue: {
666          assert(false && "Unexpected type of value of initializer.");
667        }
668      }
669      break;
670    }
671    // TODO(zonr): Resolving initializer of a record (and matrix) type variable
672    // is complex. It cannot obtain by just simply evaluating the initializer
673    // expression.
674    case RSExportType::ExportClassMatrix:
675    case RSExportType::ExportClassConstantArray:
676    case RSExportType::ExportClassRecord: {
677#if 0
678      unsigned InitIndex = 0;
679      const RSExportRecordType *ERT =
680          static_cast<const RSExportRecordType*>(ET);
681
682      assert((Val.getKind() == clang::APValue::Vector) && "Unexpected type of "
683             "initializer for record type variable");
684
685      C.indent() << RS_EXPORT_VAR_PREFIX << VarName
686                 << " = new "RS_TYPE_CLASS_NAME_PREFIX << ERT->getName()
687                 <<  "."RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
688
689      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
690               E = ERT->fields_end();
691           I != E;
692           I++) {
693        const RSExportRecordType::Field *F = *I;
694        std::string FieldName = VarName + "." + F->getName();
695
696        if (InitIndex > Val.getVectorLength())
697          break;
698
699        genInitPrimitiveExportVariable(C,
700                                       FieldName,
701                                       Val.getVectorElt(InitIndex++));
702      }
703#endif
704      assert(false && "Unsupported initializer for record/matrix/constant "
705                      "array type variable currently");
706      break;
707    }
708    default: {
709      assert(false && "Unknown class of type");
710    }
711  }
712  return;
713}
714
715void RSReflection::genExportVariable(Context &C, const RSExportVar *EV) {
716  const RSExportType *ET = EV->getType();
717
718  C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX
719             << EV->getName() << " = " << C.getNextExportVarSlot() << ";"
720             << std::endl;
721
722  switch (ET->getClass()) {
723    case RSExportType::ExportClassPrimitive: {
724      genPrimitiveTypeExportVariable(C, EV);
725      break;
726    }
727    case RSExportType::ExportClassPointer: {
728      genPointerTypeExportVariable(C, EV);
729      break;
730    }
731    case RSExportType::ExportClassVector: {
732      genVectorTypeExportVariable(C, EV);
733      break;
734    }
735    case RSExportType::ExportClassMatrix: {
736      genMatrixTypeExportVariable(C, EV);
737      break;
738    }
739    case RSExportType::ExportClassConstantArray: {
740      genConstantArrayTypeExportVariable(C, EV);
741      break;
742    }
743    case RSExportType::ExportClassRecord: {
744      genRecordTypeExportVariable(C, EV);
745      break;
746    }
747    default: {
748      assert(false && "Unknown class of type");
749    }
750  }
751
752  return;
753}
754
755void RSReflection::genExportFunction(Context &C, const RSExportFunc *EF) {
756  C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX
757             << EF->getName() << " = " << C.getNextExportFuncSlot() << ";"
758             << std::endl;
759
760  // invoke_*()
761  Context::ArgTy Args;
762
763  if (EF->hasParam()) {
764    for (RSExportFunc::const_param_iterator I = EF->params_begin(),
765             E = EF->params_end();
766         I != E;
767         I++) {
768      Args.push_back(std::make_pair(GetTypeName((*I)->getType()),
769                                    (*I)->getName()));
770    }
771  }
772
773  C.startFunction(Context::AM_Public,
774                  false,
775                  "void",
776                  "invoke_" + EF->getName(),
777                  Args);
778
779  if (!EF->hasParam()) {
780    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");"
781               << std::endl;
782  } else {
783    const RSExportRecordType *ERT = EF->getParamPacketType();
784    std::string FieldPackerName = EF->getName() + "_fp";
785
786    if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
787      genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
788
789    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", "
790               << FieldPackerName << ");" << std::endl;
791  }
792
793  C.endFunction();
794  return;
795}
796
797void RSReflection::genPrimitiveTypeExportVariable(Context &C,
798                                                  const RSExportVar *EV) {
799  assert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive) &&
800         "Variable should be type of primitive here");
801
802  const RSExportPrimitiveType *EPT =
803      static_cast<const RSExportPrimitiveType*>(EV->getType());
804  const char *TypeName = GetPrimitiveTypeName(EPT);
805
806  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
807             << EV->getName() << ";" << std::endl;
808
809  // set_*()
810  if (!EV->isConst()) {
811    C.startFunction(Context::AM_Public,
812                    false,
813                    "void",
814                    "set_" + EV->getName(),
815                    1,
816                    TypeName, "v");
817    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
818
819    if (EPT->isRSObjectType())
820      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
821                 << ", (v == null) ? 0 : v.getID());" << std::endl;
822    else
823      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
824                 << ", v);" << std::endl;
825
826    C.endFunction();
827  }
828
829  genGetExportVariable(C, TypeName, EV->getName());
830
831  return;
832}
833
834void RSReflection::genPointerTypeExportVariable(Context &C,
835                                                const RSExportVar *EV) {
836  const RSExportType *ET = EV->getType();
837  const RSExportType *PointeeType;
838  std::string TypeName;
839
840  assert((ET->getClass() == RSExportType::ExportClassPointer) &&
841         "Variable should be type of pointer here");
842
843  PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
844  TypeName = GetTypeName(ET);
845
846  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
847             << EV->getName() << ";" << std::endl;
848
849  // bind_*()
850  C.startFunction(Context::AM_Public,
851                  false,
852                  "void",
853                  "bind_" + EV->getName(),
854                  1,
855                  TypeName.c_str(), "v");
856
857  C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
858  C.indent() << "if (v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX
859             << EV->getName() << ");" << std::endl;
860
861  if (PointeeType->getClass() == RSExportType::ExportClassRecord)
862    C.indent() << "else bindAllocation(v.getAllocation(), "
863        RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");"
864               << std::endl;
865  else
866    C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX
867               << EV->getName() << ");" << std::endl;
868
869  C.endFunction();
870
871  genGetExportVariable(C, TypeName, EV->getName());
872
873  return;
874}
875
876void RSReflection::genVectorTypeExportVariable(Context &C,
877                                               const RSExportVar *EV) {
878  assert((EV->getType()->getClass() == RSExportType::ExportClassVector) &&
879         "Variable should be type of vector here");
880
881  const RSExportVectorType *EVT =
882      static_cast<const RSExportVectorType*>(EV->getType());
883  const char *TypeName = GetVectorTypeName(EVT);
884  const char *FieldPackerName = "fp";
885
886  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
887             << EV->getName() << ";" << std::endl;
888
889  // set_*()
890  if (!EV->isConst()) {
891    C.startFunction(Context::AM_Public,
892                    false,
893                    "void",
894                    "set_" + EV->getName(),
895                    1,
896                    TypeName, "v");
897    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
898
899    if (genCreateFieldPacker(C, EVT, FieldPackerName))
900      genPackVarOfType(C, EVT, "v", FieldPackerName);
901    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
902               << FieldPackerName << ");" << std::endl;
903
904    C.endFunction();
905  }
906
907  genGetExportVariable(C, TypeName, EV->getName());
908  return;
909}
910
911void RSReflection::genMatrixTypeExportVariable(Context &C,
912                                               const RSExportVar *EV) {
913  assert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) &&
914         "Variable should be type of matrix here");
915
916  const RSExportMatrixType *EMT =
917      static_cast<const RSExportMatrixType*>(EV->getType());
918  const char *TypeName = GetMatrixTypeName(EMT);
919  const char *FieldPackerName = "fp";
920
921  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
922             << EV->getName() << ";" << std::endl;
923
924  // set_*()
925  if (!EV->isConst()) {
926    C.startFunction(Context::AM_Public,
927                    false,
928                    "void",
929                    "set_" + EV->getName(),
930                    1,
931                    TypeName, "v");
932    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
933
934    if (genCreateFieldPacker(C, EMT, FieldPackerName))
935      genPackVarOfType(C, EMT, "v", FieldPackerName);
936    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
937               << FieldPackerName << ");" << std::endl;
938
939    C.endFunction();
940  }
941
942  genGetExportVariable(C, TypeName, EV->getName());
943  return;
944}
945
946void RSReflection::genConstantArrayTypeExportVariable(Context &C,
947                                                      const RSExportVar *EV) {
948  assert((EV->getType()->getClass() == RSExportType::ExportClassConstantArray)&&
949         "Variable should be type of constant array here");
950
951  const RSExportConstantArrayType *ECAT =
952      static_cast<const RSExportConstantArrayType*>(EV->getType());
953  std::string TypeName = GetTypeName(ECAT);
954  const char *FieldPackerName = "fp";
955
956  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
957             << EV->getName() << ";" << std::endl;
958
959  // set_*()
960  if (!EV->isConst()) {
961    C.startFunction(Context::AM_Public,
962                    false,
963                    "void",
964                    "set_" + EV->getName(),
965                    1,
966                    TypeName.c_str(), "v");
967    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
968
969    if (genCreateFieldPacker(C, ECAT, FieldPackerName))
970      genPackVarOfType(C, ECAT, "v", FieldPackerName);
971    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
972               << FieldPackerName << ");" << std::endl;
973
974    C.endFunction();
975  }
976
977  genGetExportVariable(C, TypeName, EV->getName());
978  return;
979}
980
981void RSReflection::genRecordTypeExportVariable(Context &C,
982                                               const RSExportVar *EV) {
983  assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
984         "Variable should be type of struct here");
985
986  const RSExportRecordType *ERT =
987      static_cast<const RSExportRecordType*>(EV->getType());
988  std::string TypeName =
989      RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
990  const char *FieldPackerName = "fp";
991
992  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
993             << EV->getName() << ";" << std::endl;
994
995  // set_*()
996  if (!EV->isConst()) {
997    C.startFunction(Context::AM_Public,
998                    false,
999                    "void",
1000                    "set_" + EV->getName(),
1001                    1,
1002                    TypeName.c_str(), "v");
1003    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
1004
1005    if (genCreateFieldPacker(C, ERT, FieldPackerName))
1006      genPackVarOfType(C, ERT, "v", FieldPackerName);
1007    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
1008               << ", " << FieldPackerName << ");" << std::endl;
1009
1010    C.endFunction();
1011  }
1012
1013  genGetExportVariable(C, TypeName.c_str(), EV->getName());
1014  return;
1015}
1016
1017void RSReflection::genGetExportVariable(Context &C,
1018                                        const std::string &TypeName,
1019                                        const std::string &VarName) {
1020  C.startFunction(Context::AM_Public,
1021                  false,
1022                  TypeName.c_str(),
1023                  "get_" + VarName,
1024                  0);
1025
1026  C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << std::endl;
1027
1028  C.endFunction();
1029  return;
1030}
1031
1032/******************* Methods to generate script class /end *******************/
1033
1034bool RSReflection::genCreateFieldPacker(Context &C,
1035                                        const RSExportType *ET,
1036                                        const char *FieldPackerName) {
1037  size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
1038  if (AllocSize > 0)
1039    C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
1040               << AllocSize << ");" << std::endl;
1041  else
1042    return false;
1043  return true;
1044}
1045
1046void RSReflection::genPackVarOfType(Context &C,
1047                                    const RSExportType *ET,
1048                                    const char *VarName,
1049                                    const char *FieldPackerName) {
1050  switch (ET->getClass()) {
1051    case RSExportType::ExportClassPrimitive:
1052    case RSExportType::ExportClassVector: {
1053      C.indent() << FieldPackerName << "."
1054                 << GetPackerAPIName(
1055                     static_cast<const RSExportPrimitiveType*>(ET))
1056                 << "(" << VarName << ");" << std::endl;
1057      break;
1058    }
1059    case RSExportType::ExportClassPointer: {
1060      // Must reflect as type Allocation in Java
1061      const RSExportType *PointeeType =
1062          static_cast<const RSExportPointerType*>(ET)->getPointeeType();
1063
1064      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
1065        C.indent() << FieldPackerName << ".addI32(" << VarName
1066                   << ".getPtr());" << std::endl;
1067      else
1068        C.indent() << FieldPackerName << ".addI32(" << VarName
1069                   << ".getAllocation().getPtr());" << std::endl;
1070      break;
1071    }
1072    case RSExportType::ExportClassMatrix: {
1073      C.indent() << FieldPackerName << ".addObj(" << VarName << ");"
1074                 << std::endl;
1075      break;
1076    }
1077    case RSExportType::ExportClassConstantArray: {
1078      const RSExportConstantArrayType *ECAT =
1079          static_cast<const RSExportConstantArrayType *>(ET);
1080
1081      // TODO(zonr): more elegant way. Currently, we obtain the unique index
1082      //             variable (this method involves recursive call which means
1083      //             we may have more than one level loop, therefore we can't
1084      //             always use the same index variable name here) name given
1085      //             in the for-loop from counting the '.' in @VarName.
1086      unsigned Level = 0;
1087      size_t LastDotPos = 0;
1088      std::string ElementVarName(VarName);
1089
1090      while (LastDotPos != std::string::npos) {
1091        LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
1092        Level++;
1093      }
1094      std::string IndexVarName("ct");
1095      IndexVarName.append(llvm::utostr_32(Level));
1096
1097      C.indent() << "for (int " << IndexVarName << " = 0; " <<
1098                          IndexVarName << " < " << ECAT->getSize() << "; " <<
1099                          IndexVarName << "++)";
1100      C.startBlock();
1101
1102      ElementVarName.append("[" + IndexVarName + "]");
1103      genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
1104                       FieldPackerName);
1105
1106      C.endBlock();
1107      break;
1108    }
1109    case RSExportType::ExportClassRecord: {
1110      const RSExportRecordType *ERT =
1111          static_cast<const RSExportRecordType*>(ET);
1112      // Relative pos from now on in field packer
1113      unsigned Pos = 0;
1114
1115      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1116               E = ERT->fields_end();
1117           I != E;
1118           I++) {
1119        const RSExportRecordType::Field *F = *I;
1120        std::string FieldName;
1121        size_t FieldOffset = F->getOffsetInParent();
1122        size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1123        size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1124
1125        if (VarName != NULL)
1126          FieldName = VarName + ("." + F->getName());
1127        else
1128          FieldName = F->getName();
1129
1130        if (FieldOffset > Pos)
1131          C.indent() << FieldPackerName << ".skip("
1132                     << (FieldOffset - Pos) << ");" << std::endl;
1133
1134        genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
1135
1136        // There is padding in the field type
1137        if (FieldAllocSize > FieldStoreSize)
1138            C.indent() << FieldPackerName << ".skip("
1139                       << (FieldAllocSize - FieldStoreSize)
1140                       << ");" << std::endl;
1141
1142          Pos = FieldOffset + FieldAllocSize;
1143      }
1144
1145      // There maybe some padding after the struct
1146      size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
1147      if (Padding > 0)
1148        C.indent() << FieldPackerName << ".skip(" << Padding << ");"
1149                   << std::endl;
1150      break;
1151    }
1152    default: {
1153      assert(false && "Unknown class of type");
1154    }
1155  }
1156
1157  return;
1158}
1159
1160void RSReflection::genAllocateVarOfType(Context &C,
1161                                        const RSExportType *T,
1162                                        const std::string &VarName) {
1163  switch (T->getClass()) {
1164    case RSExportType::ExportClassPrimitive: {
1165      // Primitive type like int in Java has its own storage once it's declared.
1166      //
1167      // FIXME: Should we allocate storage for RS object?
1168      // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType())
1169      //  C.indent() << VarName << " = new " << GetTypeName(T) << "();"
1170      //             << std::endl;
1171      break;
1172    }
1173    case RSExportType::ExportClassPointer: {
1174      // Pointer type is an instance of Allocation or a TypeClass whose value is
1175      // expected to be assigned by programmer later in Java program. Therefore
1176      // we don't reflect things like [VarName] = new Allocation();
1177      C.indent() << VarName << " = null;" << std::endl;
1178      break;
1179    }
1180    case RSExportType::ExportClassConstantArray: {
1181      const RSExportConstantArrayType *ECAT =
1182          static_cast<const RSExportConstantArrayType *>(T);
1183      const RSExportType *ElementType = ECAT->getElementType();
1184
1185      C.indent() << VarName << " = new " << GetTypeName(ElementType)
1186                 << "[" << ECAT->getSize() << "];" << std::endl;
1187
1188      // Primitive type element doesn't need allocation code.
1189      if (ElementType->getClass() != RSExportType::ExportClassPrimitive) {
1190        C.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() << "; "
1191                            "$ct++)";
1192        C.startBlock();
1193
1194        std::string ElementVarName(VarName);
1195        ElementVarName.append("[$ct]");
1196        genAllocateVarOfType(C, ElementType, ElementVarName);
1197
1198        C.endBlock();
1199      }
1200      break;
1201    }
1202    case RSExportType::ExportClassVector:
1203    case RSExportType::ExportClassMatrix:
1204    case RSExportType::ExportClassRecord: {
1205      C.indent() << VarName << " = new " << GetTypeName(T) << "();"
1206                 << std::endl;
1207      break;
1208    }
1209  }
1210  return;
1211}
1212
1213void RSReflection::genNewItemBufferIfNull(Context &C, const char *Index) {
1214  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "
1215                  RS_TYPE_ITEM_BUFFER_NAME" = "
1216                    "new "RS_TYPE_ITEM_CLASS_NAME"[getType().getX() /* count */];"
1217             << std::endl;
1218  if (Index != NULL)
1219    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] == null) "
1220                    RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = "
1221                      "new "RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
1222  return;
1223}
1224
1225void RSReflection::genNewItemBufferPackerIfNull(Context &C) {
1226  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_PACKER_NAME" == null) "
1227                  RS_TYPE_ITEM_BUFFER_PACKER_NAME" = "
1228                    "new FieldPacker("
1229                      RS_TYPE_ITEM_CLASS_NAME".sizeof * getType().getX()/* count */"
1230                    ");" << std::endl;
1231  return;
1232}
1233
1234/********************** Methods to generate type class  **********************/
1235bool RSReflection::genTypeClass(Context &C,
1236                                const RSExportRecordType *ERT,
1237                                std::string &ErrorMsg) {
1238  std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
1239
1240  if (!C.startClass(Context::AM_Public,
1241                    false,
1242                    ClassName,
1243                    RS_TYPE_CLASS_SUPER_CLASS_NAME,
1244                    ErrorMsg))
1245    return false;
1246
1247  genTypeItemClass(C, ERT);
1248
1249  // Declare item buffer and item buffer packer
1250  C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[]"
1251      ";" << std::endl;
1252  C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";"
1253             << std::endl;
1254
1255  genTypeClassConstructor(C, ERT);
1256  genTypeClassCopyToArray(C, ERT);
1257  genTypeClassItemSetter(C, ERT);
1258  genTypeClassItemGetter(C, ERT);
1259  genTypeClassComponentSetter(C, ERT);
1260  genTypeClassComponentGetter(C, ERT);
1261  genTypeClassCopyAll(C, ERT);
1262  genTypeClassResize(C);
1263
1264  C.endClass();
1265
1266  C.resetFieldIndex();
1267  C.clearFieldIndexMap();
1268
1269  return true;
1270}
1271
1272void RSReflection::genTypeItemClass(Context &C, const RSExportRecordType *ERT) {
1273  C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
1274  C.startBlock();
1275
1276  C.indent() << "public static final int sizeof = "
1277             << RSExportType::GetTypeAllocSize(ERT) << ";" << std::endl;
1278
1279  // Member elements
1280  C.out() << std::endl;
1281  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1282           FE = ERT->fields_end();
1283       FI != FE;
1284       FI++) {
1285    C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
1286               << ";" << std::endl;
1287  }
1288
1289  // Constructor
1290  C.out() << std::endl;
1291  C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
1292  C.startBlock();
1293
1294  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1295           FE = ERT->fields_end();
1296       FI != FE;
1297       FI++) {
1298    const RSExportRecordType::Field *F = *FI;
1299    genAllocateVarOfType(C, F->getType(), F->getName());
1300  }
1301
1302  // end Constructor
1303  C.endBlock();
1304
1305  // end Item class
1306  C.endBlock();
1307
1308  return;
1309}
1310
1311void RSReflection::genTypeClassConstructor(Context &C,
1312                                           const RSExportRecordType *ERT) {
1313  const char *RenderScriptVar = "rs";
1314
1315  C.startFunction(Context::AM_Public,
1316                  true,
1317                  "Element",
1318                  "createElement",
1319                  1,
1320                  "RenderScript", RenderScriptVar);
1321  genBuildElement(C, "eb", ERT, RenderScriptVar, /* IsInline = */false);
1322  C.endFunction();
1323
1324  C.startFunction(Context::AM_Public,
1325                  false,
1326                  NULL,
1327                  C.getClassName(),
1328                  2,
1329                  "RenderScript", RenderScriptVar,
1330                  "int", "count");
1331
1332  C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl;
1333  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl;
1334  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
1335             << std::endl;
1336  // Call init() in super class
1337  C.indent() << "init(" << RenderScriptVar << ", count);" << std::endl;
1338  C.endFunction();
1339
1340  return;
1341}
1342
1343void RSReflection::genTypeClassCopyToArray(Context &C,
1344                                           const RSExportRecordType *ERT) {
1345  C.startFunction(Context::AM_Private,
1346                  false,
1347                  "void",
1348                  "copyToArray",
1349                  2,
1350                  RS_TYPE_ITEM_CLASS_NAME, "i",
1351                  "int", "index");
1352
1353  genNewItemBufferPackerIfNull(C);
1354  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1355                ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);"
1356             << std::endl;
1357
1358  genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1359
1360  C.endFunction();
1361  return;
1362}
1363
1364void RSReflection::genTypeClassItemSetter(Context &C,
1365                                          const RSExportRecordType *ERT) {
1366  C.startFunction(Context::AM_Public,
1367                  false,
1368                  "void",
1369                  "set",
1370                  3,
1371                  RS_TYPE_ITEM_CLASS_NAME, "i",
1372                  "int", "index",
1373                  "boolean", "copyNow");
1374  genNewItemBufferIfNull(C, NULL);
1375  C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << std::endl;
1376
1377  C.indent() << "if (copyNow) ";
1378  C.startBlock();
1379
1380  C.indent() << "copyToArray(i, index);" << std::endl;
1381  C.indent() << "mAllocation.subData1D(index, 1, "
1382                  RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << std::endl;
1383
1384  // End of if (copyNow)
1385  C.endBlock();
1386
1387  C.endFunction();
1388  return;
1389}
1390
1391void RSReflection::genTypeClassItemGetter(Context &C,
1392                                          const RSExportRecordType *ERT) {
1393  C.startFunction(Context::AM_Public,
1394                  false,
1395                  RS_TYPE_ITEM_CLASS_NAME,
1396                  "get",
1397                  1,
1398                  "int", "index");
1399  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;"
1400             << std::endl;
1401  C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index];" << std::endl;
1402  C.endFunction();
1403  return;
1404}
1405
1406void RSReflection::genTypeClassComponentSetter(Context &C,
1407                                               const RSExportRecordType *ERT) {
1408  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1409           FE = ERT->fields_end();
1410       FI != FE;
1411       FI++) {
1412    const RSExportRecordType::Field *F = *FI;
1413    size_t FieldOffset = F->getOffsetInParent();
1414    size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1415    unsigned FieldIndex = C.getFieldIndex(F);
1416
1417    C.startFunction(Context::AM_Public,
1418                    false,
1419                    "void",
1420                    "set_" + F->getName(), 3,
1421                    "int", "index",
1422                    GetTypeName(F->getType()).c_str(), "v",
1423                    "boolean", "copyNow");
1424    genNewItemBufferPackerIfNull(C);
1425    genNewItemBufferIfNull(C, "index");
1426    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
1427               << " = v;" << std::endl;
1428
1429    C.indent() << "if (copyNow) ";
1430    C.startBlock();
1431
1432    if (FieldOffset > 0)
1433      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1434                    ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof + "
1435                 << FieldOffset << ");" << std::endl;
1436    else
1437      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1438                    ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);"
1439                 << std::endl;
1440    genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1441
1442    C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");"
1443               << std::endl;
1444    genPackVarOfType(C, F->getType(), "v", "fp");
1445    C.indent() << "mAllocation.subElementData(index, " << FieldIndex << ", fp);"
1446               << std::endl;
1447
1448    // End of if (copyNow)
1449    C.endBlock();
1450
1451    C.endFunction();
1452  }
1453  return;
1454}
1455
1456void RSReflection::genTypeClassComponentGetter(Context &C,
1457                                               const RSExportRecordType *ERT) {
1458  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1459           FE = ERT->fields_end();
1460       FI != FE;
1461       FI++) {
1462    const RSExportRecordType::Field *F = *FI;
1463    C.startFunction(Context::AM_Public,
1464                    false,
1465                    GetTypeName(F->getType()).c_str(),
1466                    "get_" + F->getName(),
1467                    1,
1468                    "int", "index");
1469    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return "
1470               << GetTypeNullValue(F->getType()) << ";" << std::endl;
1471    C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
1472               << ";" << std::endl;
1473    C.endFunction();
1474  }
1475  return;
1476}
1477
1478void RSReflection::genTypeClassCopyAll(Context &C,
1479                                       const RSExportRecordType *ERT) {
1480  C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
1481
1482  C.indent() << "for (int ct = 0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++)"
1483                  " copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);"
1484             << std::endl;
1485  C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());"
1486             << std::endl;
1487
1488  C.endFunction();
1489  return;
1490}
1491
1492void RSReflection::genTypeClassResize(Context &C) {
1493  C.startFunction(Context::AM_Public,
1494                  false,
1495                  "void",
1496                  "resize",
1497                  1,
1498                  "int", "newSize");
1499
1500  C.indent() << "if (mItemArray != null) ";
1501  C.startBlock();
1502  C.indent() << "int oldSize = mItemArray.length;" << std::endl;
1503  C.indent() << "int copySize = Math.min(oldSize, newSize);" << std::endl;
1504  C.indent() << "if (newSize == oldSize) return;" << std::endl;
1505  C.indent() << "Item ni[] = new Item[newSize];" << std::endl;
1506  C.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);"
1507             << std::endl;
1508  C.indent() << "mItemArray = ni;" << std::endl;
1509  C.endBlock();
1510  C.indent() << "mAllocation.resize(newSize);" << std::endl;
1511
1512  C.endFunction();
1513  return;
1514}
1515
1516/******************** Methods to generate type class /end ********************/
1517
1518/********** Methods to create Element in Java of given record type ***********/
1519void RSReflection::genBuildElement(Context &C,
1520                                   const char *ElementBuilderName,
1521                                   const RSExportRecordType *ERT,
1522                                   const char *RenderScriptVar,
1523                                   bool IsInline) {
1524  C.indent() << "Element.Builder " << ElementBuilderName << " = "
1525      "new Element.Builder(" << RenderScriptVar << ");" << std::endl;
1526
1527  // eb.add(...)
1528  genAddElementToElementBuilder(C,
1529                                ERT,
1530                                "",
1531                                ElementBuilderName,
1532                                RenderScriptVar,
1533                                /* ArraySize = */0);
1534
1535  if (!IsInline)
1536    C.indent() << "return " << ElementBuilderName << ".create();" << std::endl;
1537  return;
1538}
1539
1540#define EB_ADD(x) do {                                              \
1541  C.indent() << ElementBuilderName                                  \
1542             << ".add(" << x << ", \"" << VarName << "\"";  \
1543  if (ArraySize > 0)                                                \
1544    C.out() << ", " << ArraySize;                                   \
1545  C.out() << ");" << std::endl;                                     \
1546  C.incFieldIndex();                                                \
1547} while (false)
1548
1549void RSReflection::genAddElementToElementBuilder(Context &C,
1550                                                 const RSExportType *ET,
1551                                                 const std::string &VarName,
1552                                                 const char *ElementBuilderName,
1553                                                 const char *RenderScriptVar,
1554                                                 unsigned ArraySize) {
1555  const char *ElementConstruct = GetBuiltinElementConstruct(ET);
1556
1557  if (ElementConstruct != NULL) {
1558    EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
1559  } else {
1560    if ((ET->getClass() == RSExportType::ExportClassPrimitive) ||
1561        (ET->getClass() == RSExportType::ExportClassVector)) {
1562      const RSExportPrimitiveType *EPT =
1563          static_cast<const RSExportPrimitiveType*>(ET);
1564      const char *DataKindName = GetElementDataKindName(EPT->getKind());
1565      const char *DataTypeName = GetElementDataTypeName(EPT->getType());
1566      int Size = (ET->getClass() == RSExportType::ExportClassVector) ?
1567          static_cast<const RSExportVectorType*>(ET)->getNumElement() :
1568          1;
1569
1570      switch (EPT->getKind()) {
1571        case RSExportPrimitiveType::DataKindPixelL:
1572        case RSExportPrimitiveType::DataKindPixelA:
1573        case RSExportPrimitiveType::DataKindPixelLA:
1574        case RSExportPrimitiveType::DataKindPixelRGB:
1575        case RSExportPrimitiveType::DataKindPixelRGBA: {
1576          // Element.createPixel()
1577          EB_ADD("Element.createPixel(" << RenderScriptVar << ", "
1578                                        << DataTypeName << ", "
1579                                        << DataKindName << ")");
1580          break;
1581        }
1582        case RSExportPrimitiveType::DataKindUser:
1583        default: {
1584          if (EPT->getClass() == RSExportType::ExportClassPrimitive) {
1585            // Element.createUser()
1586            EB_ADD("Element.createUser(" << RenderScriptVar << ", "
1587                                         << DataTypeName << ")");
1588          } else {
1589            assert((ET->getClass() == RSExportType::ExportClassVector) &&
1590                   "Unexpected type.");
1591            EB_ADD("Element.createVector(" << RenderScriptVar << ", "
1592                                           << DataTypeName << ", "
1593                                           << Size << ")");
1594          }
1595          break;
1596        }
1597      }
1598#ifndef NDEBUG
1599    } else if (ET->getClass() == RSExportType::ExportClassPointer) {
1600      // Pointer type variable should be resolved in
1601      // GetBuiltinElementConstruct()
1602      assert(false && "??");
1603    } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
1604      // Matrix type variable should be resolved
1605      // in GetBuiltinElementConstruct()
1606      assert(false && "??");
1607#endif
1608    } else if (ET->getClass() == RSExportType::ExportClassConstantArray) {
1609      const RSExportConstantArrayType *ECAT =
1610          static_cast<const RSExportConstantArrayType *>(ET);
1611
1612      const RSExportType *ElementType = ECAT->getElementType();
1613      if (ElementType->getClass() != RSExportType::ExportClassRecord) {
1614        genAddElementToElementBuilder(C,
1615                                      ECAT->getElementType(),
1616                                      VarName,
1617                                      ElementBuilderName,
1618                                      RenderScriptVar,
1619                                      ECAT->getSize());
1620      } else {
1621        std::string NewElementBuilderName(ElementBuilderName);
1622        NewElementBuilderName.append(1, '_');
1623
1624        genBuildElement(C,
1625                        NewElementBuilderName.c_str(),
1626                        static_cast<const RSExportRecordType*>(ElementType),
1627                        RenderScriptVar,
1628                        /* IsInline = */true);
1629        ArraySize = ECAT->getSize();
1630        EB_ADD(NewElementBuilderName << ".create()");
1631      }
1632    } else if (ET->getClass() == RSExportType::ExportClassRecord) {
1633      // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
1634      //
1635      // TODO(zonr): Generalize these two function such that there's no
1636      //             duplicated codes.
1637      const RSExportRecordType *ERT =
1638          static_cast<const RSExportRecordType*>(ET);
1639      int Pos = 0;    // relative pos from now on
1640
1641      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1642               E = ERT->fields_end();
1643           I != E;
1644           I++) {
1645        const RSExportRecordType::Field *F = *I;
1646        std::string FieldName;
1647        int FieldOffset = F->getOffsetInParent();
1648        int FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1649        int FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1650
1651        if (!VarName.empty())
1652          FieldName = VarName + "." + F->getName();
1653        else
1654          FieldName = F->getName();
1655
1656        // Alignment
1657        genAddPaddingToElementBuiler(C,
1658                                     (FieldOffset - Pos),
1659                                     ElementBuilderName,
1660                                     RenderScriptVar);
1661
1662        // eb.add(...)
1663        C.addFieldIndexMapping(F);
1664        if (F->getType()->getClass() != RSExportType::ExportClassRecord) {
1665          genAddElementToElementBuilder(C,
1666                                        F->getType(),
1667                                        FieldName,
1668                                        ElementBuilderName,
1669                                        RenderScriptVar,
1670                                        0);
1671        } else {
1672          std::string NewElementBuilderName(ElementBuilderName);
1673          NewElementBuilderName.append(1, '_');
1674
1675          genBuildElement(C,
1676                          NewElementBuilderName.c_str(),
1677                          static_cast<const RSExportRecordType*>(F->getType()),
1678                          RenderScriptVar,
1679                          /* IsInline = */true);
1680
1681          const std::string &VarName = FieldName;  // Hack for EB_ADD macro
1682          EB_ADD(NewElementBuilderName << ".create()");
1683        }
1684
1685        // There is padding within the field type
1686        genAddPaddingToElementBuiler(C,
1687                                     (FieldAllocSize - FieldStoreSize),
1688                                     ElementBuilderName,
1689                                     RenderScriptVar);
1690
1691        Pos = FieldOffset + FieldAllocSize;
1692      }
1693
1694      // There maybe some padding after the struct
1695      size_t RecordStoreSize = RSExportType::GetTypeStoreSize(ERT);
1696
1697      genAddPaddingToElementBuiler(C,
1698                                   RecordStoreSize - Pos,
1699                                   ElementBuilderName,
1700                                   RenderScriptVar);
1701    } else {
1702      assert(false && "Unknown class of type");
1703    }
1704  }
1705}
1706
1707void RSReflection::genAddPaddingToElementBuiler(Context &C,
1708                                                int PaddingSize,
1709                                                const char *ElementBuilderName,
1710                                                const char *RenderScriptVar) {
1711  unsigned ArraySize = 0;   // Hack the EB_ADD macro
1712  while (PaddingSize > 0) {
1713    const std::string &VarName = C.createPaddingField();
1714    if (PaddingSize >= 4) {
1715      EB_ADD("Element.U32(" << RenderScriptVar << ")");
1716      PaddingSize -= 4;
1717    } else if (PaddingSize >= 2) {
1718      EB_ADD("Element.U16(" << RenderScriptVar << ")");
1719      PaddingSize -= 2;
1720    } else if (PaddingSize >= 1) {
1721      EB_ADD("Element.U8(" << RenderScriptVar << ")");
1722      PaddingSize -= 1;
1723    }
1724  }
1725  return;
1726}
1727
1728#undef EB_ADD
1729/******** Methods to create Element in Java of given record type /end ********/
1730
1731bool RSReflection::reflect(const std::string &OutputPathBase,
1732                           const std::string &OutputPackageName,
1733                           const std::string &InputFileName,
1734                           const std::string &OutputBCFileName) {
1735  Context *C = NULL;
1736  std::string ResourceId = "";
1737
1738  if (!GetClassNameFromFileName(OutputBCFileName, ResourceId))
1739    return false;
1740
1741  if (ResourceId.empty())
1742    ResourceId = "<Resource ID>";
1743
1744  if (OutputPackageName.empty() || OutputPackageName == "-")
1745    C = new Context(OutputPathBase, InputFileName, "<Package Name>",
1746                    ResourceId, true);
1747  else
1748    C = new Context(OutputPathBase, InputFileName, OutputPackageName,
1749                    ResourceId, false);
1750
1751  if (C != NULL) {
1752    std::string ErrorMsg, ScriptClassName;
1753    // class ScriptC_<ScriptName>
1754    if (!GetClassNameFromFileName(InputFileName, ScriptClassName))
1755      return false;
1756
1757    if (ScriptClassName.empty())
1758      ScriptClassName = "<Input Script Name>";
1759
1760    ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
1761
1762    if (mRSContext->getLicenseNote() != NULL) {
1763      C->setLicenseNote(*(mRSContext->getLicenseNote()));
1764    }
1765
1766    if (!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
1767      std::cerr << "Failed to generate class " << ScriptClassName << " ("
1768                << ErrorMsg << ")" << std::endl;
1769      return false;
1770    }
1771
1772    // class ScriptField_<TypeName>
1773    for (RSContext::const_export_type_iterator TI =
1774             mRSContext->export_types_begin(),
1775             TE = mRSContext->export_types_end();
1776         TI != TE;
1777         TI++) {
1778      const RSExportType *ET = TI->getValue();
1779
1780      if (ET->getClass() == RSExportType::ExportClassRecord) {
1781        const RSExportRecordType *ERT =
1782            static_cast<const RSExportRecordType*>(ET);
1783
1784        if (!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
1785          std::cerr << "Failed to generate type class for struct '"
1786                    << ERT->getName() << "' (" << ErrorMsg << ")" << std::endl;
1787          return false;
1788        }
1789      }
1790    }
1791  }
1792
1793  return true;
1794}
1795
1796/************************** RSReflection::Context **************************/
1797const char *const RSReflection::Context::ApacheLicenseNote =
1798    "/*\n"
1799    " * Copyright (C) 2010 The Android Open Source Project\n"
1800    " *\n"
1801    " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
1802    " * you may not use this file except in compliance with the License.\n"
1803    " * You may obtain a copy of the License at\n"
1804    " *\n"
1805    " *      http://www.apache.org/licenses/LICENSE-2.0\n"
1806    " *\n"
1807    " * Unless required by applicable law or agreed to in writing, software\n"
1808    " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
1809    " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
1810    "implied.\n"
1811    " * See the License for the specific language governing permissions and\n"
1812    " * limitations under the License.\n"
1813    " */\n"
1814    "\n";
1815
1816const char *const RSReflection::Context::Import[] = {
1817  // RenderScript java class
1818  "android.renderscript.*",
1819  // Import R
1820  "android.content.res.Resources",
1821  // Import for debugging
1822  "android.util.Log",
1823};
1824
1825bool RSReflection::Context::openClassFile(const std::string &ClassName,
1826                                          std::string &ErrorMsg) {
1827  if (!mUseStdout) {
1828    mOF.clear();
1829    std::string Path =
1830        RSSlangReflectUtils::ComputePackagedPath(mOutputPathBase.c_str(),
1831                                                 mPackageName.c_str());
1832
1833    if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg))
1834      return false;
1835
1836    std::string ClassFile = Path + "/" + ClassName + ".java";
1837
1838    mOF.open(ClassFile.c_str());
1839    if (!mOF.good()) {
1840      ErrorMsg = "failed to open file '" + ClassFile + "' for write";
1841      return false;
1842    }
1843  }
1844  return true;
1845}
1846
1847const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) {
1848  switch (AM) {
1849    case AM_Public: return "public"; break;
1850    case AM_Protected: return "protected"; break;
1851    case AM_Private: return "private"; break;
1852    default: return ""; break;
1853  }
1854}
1855
1856bool RSReflection::Context::startClass(AccessModifier AM,
1857                                       bool IsStatic,
1858                                       const std::string &ClassName,
1859                                       const char *SuperClassName,
1860                                       std::string &ErrorMsg) {
1861  if (mVerbose)
1862    std::cout << "Generating " << ClassName << ".java ..." << std::endl;
1863
1864  // Open file for class
1865  if (!openClassFile(ClassName, ErrorMsg))
1866    return false;
1867
1868  // License
1869  out() << mLicenseNote;
1870
1871  // Notice of generated file
1872  out() << "/*" << std::endl;
1873  out() << " * This file is auto-generated. DO NOT MODIFY!" << std::endl;
1874  out() << " * The source RenderScript file: " << mInputRSFile << std::endl;
1875  out() << " */" << std::endl;
1876
1877  // Package
1878  if (!mPackageName.empty())
1879    out() << "package " << mPackageName << ";" << std::endl;
1880  out() << std::endl;
1881
1882  // Imports
1883  for (unsigned i = 0;i < (sizeof(Import) / sizeof(const char*)); i++)
1884    out() << "import " << Import[i] << ";" << std::endl;
1885  out() << std::endl;
1886
1887  // All reflected classes should be annotated as hidden, so that they won't
1888  // be exposed in SDK.
1889  out() << "/**" << std::endl;
1890  out() << " * @hide" << std::endl;
1891  out() << " */" << std::endl;
1892
1893  out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
1894        << ClassName;
1895  if (SuperClassName != NULL)
1896    out() << " extends " << SuperClassName;
1897
1898  startBlock();
1899
1900  mClassName = ClassName;
1901
1902  return true;
1903}
1904
1905void RSReflection::Context::endClass() {
1906  endBlock();
1907  if (!mUseStdout)
1908    mOF.close();
1909  clear();
1910  return;
1911}
1912
1913void RSReflection::Context::startBlock(bool ShouldIndent) {
1914  if (ShouldIndent)
1915    indent() << "{" << std::endl;
1916  else
1917    out() << " {" << std::endl;
1918  incIndentLevel();
1919  return;
1920}
1921
1922void RSReflection::Context::endBlock() {
1923  decIndentLevel();
1924  indent() << "}" << std::endl << std::endl;
1925  return;
1926}
1927
1928void RSReflection::Context::startTypeClass(const std::string &ClassName) {
1929  indent() << "public static class " << ClassName;
1930  startBlock();
1931  return;
1932}
1933
1934void RSReflection::Context::endTypeClass() {
1935  endBlock();
1936  return;
1937}
1938
1939void RSReflection::Context::startFunction(AccessModifier AM,
1940                                          bool IsStatic,
1941                                          const char *ReturnType,
1942                                          const std::string &FunctionName,
1943                                          int Argc, ...) {
1944  ArgTy Args;
1945  va_list vl;
1946  va_start(vl, Argc);
1947
1948  for (int i = 0; i < Argc; i++) {
1949    const char *ArgType = va_arg(vl, const char*);
1950    const char *ArgName = va_arg(vl, const char*);
1951
1952    Args.push_back(std::make_pair(ArgType, ArgName));
1953  }
1954  va_end(vl);
1955
1956  startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
1957
1958  return;
1959}
1960
1961void RSReflection::Context::startFunction(AccessModifier AM,
1962                                          bool IsStatic,
1963                                          const char *ReturnType,
1964                                          const std::string &FunctionName,
1965                                          const ArgTy &Args) {
1966  indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
1967           << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
1968
1969  bool FirstArg = true;
1970  for (ArgTy::const_iterator I = Args.begin(), E = Args.end();
1971       I != E;
1972       I++) {
1973    if (!FirstArg)
1974      out() << ", ";
1975    else
1976      FirstArg = false;
1977
1978    out() << I->first << " " << I->second;
1979  }
1980
1981  out() << ")";
1982  startBlock();
1983
1984  return;
1985}
1986
1987void RSReflection::Context::endFunction() {
1988  endBlock();
1989  return;
1990}
1991