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