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