slang_rs_reflection.cpp revision c95381a2c3b6e9117901eef0687e861e4d533bfe
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    "",         // DataTypeFloat16
120    "addF32",   // DataTypeFloat32
121    "addF64",   // DataTypeFloat64
122    "addI8",    // DataTypeSigned8
123    "addI16",   // DataTypeSigned16
124    "addI32",   // DataTypeSigned32
125    "addI64",   // DataTypeSigned64
126    "addU8",    // DataTypeUnsigned8
127    "addU16",   // DataTypeUnsigned16
128    "addU32",   // DataTypeUnsigned32
129    "addU64",   // DataTypeUnsigned64
130    "addBoolean",  // DataTypeBoolean
131
132    "addU16",   // DataTypeUnsigned565
133    "addU16",   // DataTypeUnsigned5551
134    "addU16",   // DataTypeUnsigned4444
135
136    "addMatrix",   // DataTypeRSMatrix2x2
137    "addMatrix",   // DataTypeRSMatrix3x3
138    "addMatrix",   // DataTypeRSMatrix4x4
139
140    "addObj",   // DataTypeRSElement
141    "addObj",   // DataTypeRSType
142    "addObj",   // DataTypeRSAllocation
143    "addObj",   // DataTypeRSSampler
144    "addObj",   // DataTypeRSScript
145    "addObj",   // DataTypeRSMesh
146    "addObj",   // DataTypeRSPath
147    "addObj",   // DataTypeRSProgramFragment
148    "addObj",   // DataTypeRSProgramVertex
149    "addObj",   // DataTypeRSProgramRaster
150    "addObj",   // DataTypeRSProgramStore
151    "addObj",   // 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() == 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() == 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() == 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() == 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        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 = ET->getAllocSize();
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        const RSExportType *T = F->getType();
1251        size_t FieldStoreSize = T->getStoreSize();
1252        size_t FieldAllocSize = T->getAllocSize();
1253
1254        if (VarName != NULL)
1255          FieldName = VarName + ("." + F->getName());
1256        else
1257          FieldName = F->getName();
1258
1259        if (FieldOffset > Pos)
1260          C.indent() << FieldPackerName << ".skip("
1261                     << (FieldOffset - Pos) << ");" << std::endl;
1262
1263        genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
1264
1265        // There is padding in the field type
1266        if (FieldAllocSize > FieldStoreSize)
1267            C.indent() << FieldPackerName << ".skip("
1268                       << (FieldAllocSize - FieldStoreSize)
1269                       << ");" << std::endl;
1270
1271        Pos = FieldOffset + FieldAllocSize;
1272      }
1273
1274      // There maybe some padding after the struct
1275      if (ERT->getAllocSize() > Pos)
1276        C.indent() << FieldPackerName << ".skip("
1277                   << ERT->getAllocSize() - Pos << ");"
1278                   << std::endl;
1279      break;
1280    }
1281    default: {
1282      slangAssert(false && "Unknown class of type");
1283    }
1284  }
1285
1286  return;
1287}
1288
1289void RSReflection::genAllocateVarOfType(Context &C,
1290                                        const RSExportType *T,
1291                                        const std::string &VarName) {
1292  switch (T->getClass()) {
1293    case RSExportType::ExportClassPrimitive: {
1294      // Primitive type like int in Java has its own storage once it's declared.
1295      //
1296      // FIXME: Should we allocate storage for RS object?
1297      // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType())
1298      //  C.indent() << VarName << " = new " << GetTypeName(T) << "();"
1299      //             << std::endl;
1300      break;
1301    }
1302    case RSExportType::ExportClassPointer: {
1303      // Pointer type is an instance of Allocation or a TypeClass whose value is
1304      // expected to be assigned by programmer later in Java program. Therefore
1305      // we don't reflect things like [VarName] = new Allocation();
1306      C.indent() << VarName << " = null;" << std::endl;
1307      break;
1308    }
1309    case RSExportType::ExportClassConstantArray: {
1310      const RSExportConstantArrayType *ECAT =
1311          static_cast<const RSExportConstantArrayType *>(T);
1312      const RSExportType *ElementType = ECAT->getElementType();
1313
1314      C.indent() << VarName << " = new " << GetTypeName(ElementType)
1315                 << "[" << ECAT->getSize() << "];" << std::endl;
1316
1317      // Primitive type element doesn't need allocation code.
1318      if (ElementType->getClass() != RSExportType::ExportClassPrimitive) {
1319        C.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() << "; "
1320                            "$ct++)";
1321        C.startBlock();
1322
1323        std::string ElementVarName(VarName);
1324        ElementVarName.append("[$ct]");
1325        genAllocateVarOfType(C, ElementType, ElementVarName);
1326
1327        C.endBlock();
1328      }
1329      break;
1330    }
1331    case RSExportType::ExportClassVector:
1332    case RSExportType::ExportClassMatrix:
1333    case RSExportType::ExportClassRecord: {
1334      C.indent() << VarName << " = new " << GetTypeName(T) << "();"
1335                 << std::endl;
1336      break;
1337    }
1338  }
1339  return;
1340}
1341
1342void RSReflection::genNewItemBufferIfNull(Context &C,
1343                                          const char *Index) {
1344  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) "
1345                  RS_TYPE_ITEM_BUFFER_NAME " = "
1346                    "new " RS_TYPE_ITEM_CLASS_NAME
1347                      "[getType().getX() /* count */];"
1348             << std::endl;
1349  if (Index != NULL)
1350    C.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME "[" << Index << "] == null) "
1351                    RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = "
1352                      "new " RS_TYPE_ITEM_CLASS_NAME "();" << std::endl;
1353  return;
1354}
1355
1356void RSReflection::genNewItemBufferPackerIfNull(Context &C) {
1357  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME " == null) "
1358                  RS_TYPE_ITEM_BUFFER_PACKER_NAME " = "
1359                    "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME
1360                      ".sizeof * getType().getX()/* count */"
1361                        ");" << std::endl;
1362  return;
1363}
1364
1365/********************** Methods to generate type class  **********************/
1366bool RSReflection::genTypeClass(Context &C,
1367                                const RSExportRecordType *ERT,
1368                                std::string &ErrorMsg) {
1369  std::string ClassName = ERT->getElementName();
1370  std::string superClassName = C.getRSPackageName();
1371  superClassName += RS_TYPE_CLASS_SUPER_CLASS_NAME;
1372
1373  if (!C.startClass(Context::AM_Public,
1374                    false,
1375                    ClassName,
1376                    superClassName.c_str(),
1377                    ErrorMsg))
1378    return false;
1379
1380  mGeneratedFileNames->push_back(ClassName);
1381
1382  genTypeItemClass(C, ERT);
1383
1384  // Declare item buffer and item buffer packer
1385  C.indent() << "private " RS_TYPE_ITEM_CLASS_NAME " " RS_TYPE_ITEM_BUFFER_NAME "[]"
1386      ";" << std::endl;
1387  C.indent() << "private FieldPacker " RS_TYPE_ITEM_BUFFER_PACKER_NAME";"
1388             << std::endl;
1389  C.indent() << "private static java.lang.ref.WeakReference<Element> "
1390             RS_TYPE_ELEMENT_REF_NAME
1391             " = new java.lang.ref.WeakReference<Element>(null);" << std::endl;
1392
1393  genTypeClassConstructor(C, ERT);
1394  genTypeClassCopyToArrayLocal(C, ERT);
1395  genTypeClassCopyToArray(C, ERT);
1396  genTypeClassItemSetter(C, ERT);
1397  genTypeClassItemGetter(C, ERT);
1398  genTypeClassComponentSetter(C, ERT);
1399  genTypeClassComponentGetter(C, ERT);
1400  genTypeClassCopyAll(C, ERT);
1401  if (!mRSContext->isCompatLib()) {
1402    // Skip the resize method if we are targeting a compatibility library.
1403    genTypeClassResize(C);
1404  }
1405
1406  C.endClass();
1407
1408  C.resetFieldIndex();
1409  C.clearFieldIndexMap();
1410
1411  return true;
1412}
1413
1414void RSReflection::genTypeItemClass(Context &C,
1415                                    const RSExportRecordType *ERT) {
1416  C.indent() << "static public class " RS_TYPE_ITEM_CLASS_NAME;
1417  C.startBlock();
1418
1419  C.indent() << "public static final int sizeof = "
1420             << ERT->getAllocSize() << ";" << std::endl;
1421
1422  // Member elements
1423  C.out() << std::endl;
1424  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1425           FE = ERT->fields_end();
1426       FI != FE;
1427       FI++) {
1428    C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
1429               << ";" << std::endl;
1430  }
1431
1432  // Constructor
1433  C.out() << std::endl;
1434  C.indent() << RS_TYPE_ITEM_CLASS_NAME "()";
1435  C.startBlock();
1436
1437  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1438           FE = ERT->fields_end();
1439       FI != FE;
1440       FI++) {
1441    const RSExportRecordType::Field *F = *FI;
1442    genAllocateVarOfType(C, F->getType(), F->getName());
1443  }
1444
1445  // end Constructor
1446  C.endBlock();
1447
1448  // end Item class
1449  C.endBlock();
1450
1451  return;
1452}
1453
1454void RSReflection::genTypeClassConstructor(Context &C,
1455                                           const RSExportRecordType *ERT) {
1456  const char *RenderScriptVar = "rs";
1457
1458  C.startFunction(Context::AM_Public,
1459                  true,
1460                  "Element",
1461                  "createElement",
1462                  1,
1463                  "RenderScript", RenderScriptVar);
1464
1465  // TODO(all): Fix weak-refs + multi-context issue.
1466  // C.indent() << "Element e = " << RS_TYPE_ELEMENT_REF_NAME
1467  //            << ".get();" << std::endl;
1468  // C.indent() << "if (e != null) return e;" << std::endl;
1469  genBuildElement(C, "eb", ERT, RenderScriptVar, /* IsInline = */true);
1470  C.indent() << "return eb.create();" << std::endl;
1471  // C.indent() << "e = eb.create();" << std::endl;
1472  // C.indent() << RS_TYPE_ELEMENT_REF_NAME
1473  //            << " = new java.lang.ref.WeakReference<Element>(e);"
1474  //            << std::endl;
1475  // C.indent() << "return e;" << std::endl;
1476  C.endFunction();
1477
1478
1479  // private with element
1480  C.startFunction(Context::AM_Private,
1481                  false,
1482                  NULL,
1483                  C.getClassName(),
1484                  1,
1485                  "RenderScript", RenderScriptVar);
1486  C.indent() << RS_TYPE_ITEM_BUFFER_NAME " = null;" << std::endl;
1487  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = null;" << std::endl;
1488  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
1489             << std::endl;
1490  C.endFunction();
1491
1492  // 1D without usage
1493  C.startFunction(Context::AM_Public,
1494                  false,
1495                  NULL,
1496                  C.getClassName(),
1497                  2,
1498                  "RenderScript", RenderScriptVar,
1499                  "int", "count");
1500
1501  C.indent() << RS_TYPE_ITEM_BUFFER_NAME " = null;" << std::endl;
1502  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = null;" << std::endl;
1503  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
1504             << std::endl;
1505  // Call init() in super class
1506  C.indent() << "init(" << RenderScriptVar << ", count);" << std::endl;
1507  C.endFunction();
1508
1509  // 1D with usage
1510  C.startFunction(Context::AM_Public,
1511                  false,
1512                  NULL,
1513                  C.getClassName(),
1514                  3,
1515                  "RenderScript", RenderScriptVar,
1516                  "int", "count",
1517                  "int", "usages");
1518
1519  C.indent() << RS_TYPE_ITEM_BUFFER_NAME " = null;" << std::endl;
1520  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = null;" << std::endl;
1521  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
1522             << std::endl;
1523  // Call init() in super class
1524  C.indent() << "init(" << RenderScriptVar << ", count, usages);" << std::endl;
1525  C.endFunction();
1526
1527
1528  // create1D with usage
1529  C.startFunction(Context::AM_Public,
1530                  true,
1531                  C.getClassName().c_str(),
1532                  "create1D",
1533                  3,
1534                  "RenderScript", RenderScriptVar,
1535                  "int", "dimX",
1536                  "int", "usages");
1537  C.indent() << C.getClassName() << " obj = new " << C.getClassName() << "("
1538             << RenderScriptVar << ");" << std::endl;
1539  C.indent() << "obj.mAllocation = Allocation.createSized("
1540                "rs, obj.mElement, dimX, usages);" << std::endl;
1541  C.indent() << "return obj;" << std::endl;
1542  C.endFunction();
1543
1544  // create1D without usage
1545  C.startFunction(Context::AM_Public,
1546                  true,
1547                  C.getClassName().c_str(),
1548                  "create1D",
1549                  2,
1550                  "RenderScript", RenderScriptVar,
1551                  "int", "dimX");
1552  C.indent() << "return create1D(" << RenderScriptVar
1553             << ", dimX, Allocation.USAGE_SCRIPT);" << std::endl;
1554  C.endFunction();
1555
1556
1557  // create2D without usage
1558  C.startFunction(Context::AM_Public,
1559                  true,
1560                  C.getClassName().c_str(),
1561                  "create2D",
1562                  3,
1563                  "RenderScript", RenderScriptVar,
1564                  "int", "dimX",
1565                  "int", "dimY");
1566  C.indent() << "return create2D(" << RenderScriptVar
1567             << ", dimX, dimY, Allocation.USAGE_SCRIPT);" << std::endl;
1568  C.endFunction();
1569
1570  // create2D with usage
1571  C.startFunction(Context::AM_Public,
1572                  true,
1573                  C.getClassName().c_str(),
1574                  "create2D",
1575                  4,
1576                  "RenderScript", RenderScriptVar,
1577                  "int", "dimX",
1578                  "int", "dimY",
1579                  "int", "usages");
1580
1581  C.indent() << C.getClassName() << " obj = new " << C.getClassName() << "("
1582             << RenderScriptVar << ");" << std::endl;
1583  C.indent() << "Type.Builder b = new Type.Builder(rs, obj.mElement);"
1584             << std::endl;
1585  C.indent() << "b.setX(dimX);" << std::endl;
1586  C.indent() << "b.setY(dimY);" << std::endl;
1587  C.indent() << "Type t = b.create();" << std::endl;
1588  C.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);"
1589             << std::endl;
1590  C.indent() << "return obj;" << std::endl;
1591  C.endFunction();
1592
1593
1594  // createTypeBuilder
1595  C.startFunction(Context::AM_Public,
1596                  true,
1597                  "Type.Builder",
1598                  "createTypeBuilder",
1599                  1,
1600                  "RenderScript", RenderScriptVar);
1601  C.indent() << "Element e = createElement(" << RenderScriptVar << ");"
1602             << std::endl;
1603  C.indent() << "return new Type.Builder(rs, e);" << std::endl;
1604  C.endFunction();
1605
1606  // createCustom with usage
1607  C.startFunction(Context::AM_Public,
1608                  true,
1609                  C.getClassName().c_str(),
1610                  "createCustom",
1611                  3,
1612                  "RenderScript", RenderScriptVar,
1613                  "Type.Builder", "tb",
1614                  "int", "usages");
1615  C.indent() << C.getClassName() << " obj = new " << C.getClassName() << "("
1616             << RenderScriptVar << ");" << std::endl;
1617  C.indent() << "Type t = tb.create();" << std::endl;
1618  C.indent() << "if (t.getElement() != obj.mElement) {" << std::endl;
1619  C.indent() << "    throw new RSIllegalArgumentException("
1620                "\"Type.Builder did not match expected element type.\");"
1621             << std::endl;
1622  C.indent() << "}" << std::endl;
1623  C.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);"
1624             << std::endl;
1625  C.indent() << "return obj;" << std::endl;
1626  C.endFunction();
1627}
1628
1629
1630void RSReflection::genTypeClassCopyToArray(Context &C,
1631                                           const RSExportRecordType *ERT) {
1632  C.startFunction(Context::AM_Private,
1633                  false,
1634                  "void",
1635                  "copyToArray",
1636                  2,
1637                  RS_TYPE_ITEM_CLASS_NAME, "i",
1638                  "int", "index");
1639
1640  genNewItemBufferPackerIfNull(C);
1641  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1642                ".reset(index * " RS_TYPE_ITEM_CLASS_NAME ".sizeof);"
1643             << std::endl;
1644
1645  C.indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME
1646                ");" << std::endl;
1647
1648  C.endFunction();
1649  return;
1650}
1651
1652void RSReflection::genTypeClassCopyToArrayLocal(Context &C,
1653                                                const RSExportRecordType *ERT) {
1654  C.startFunction(Context::AM_Private,
1655                  false,
1656                  "void",
1657                  "copyToArrayLocal",
1658                  2,
1659                  RS_TYPE_ITEM_CLASS_NAME, "i",
1660                  "FieldPacker", "fp");
1661
1662  genPackVarOfType(C, ERT, "i", "fp");
1663
1664  C.endFunction();
1665  return;
1666}
1667
1668void RSReflection::genTypeClassItemSetter(Context &C,
1669                                          const RSExportRecordType *ERT) {
1670  C.startFunction(Context::AM_PublicSynchronized,
1671                  false,
1672                  "void",
1673                  "set",
1674                  3,
1675                  RS_TYPE_ITEM_CLASS_NAME, "i",
1676                  "int", "index",
1677                  "boolean", "copyNow");
1678  genNewItemBufferIfNull(C, NULL);
1679  C.indent() << RS_TYPE_ITEM_BUFFER_NAME "[index] = i;" << std::endl;
1680
1681  C.indent() << "if (copyNow) ";
1682  C.startBlock();
1683
1684  C.indent() << "copyToArray(i, index);" << std::endl;
1685  C.indent() << "FieldPacker fp = new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME
1686                ".sizeof);" << std::endl;
1687  C.indent() << "copyToArrayLocal(i, fp);" << std::endl;
1688  C.indent() << "mAllocation.setFromFieldPacker(index, fp);" << std::endl;
1689
1690  // End of if (copyNow)
1691  C.endBlock();
1692
1693  C.endFunction();
1694  return;
1695}
1696
1697void RSReflection::genTypeClassItemGetter(Context &C,
1698                                          const RSExportRecordType *ERT) {
1699  C.startFunction(Context::AM_PublicSynchronized,
1700                  false,
1701                  RS_TYPE_ITEM_CLASS_NAME,
1702                  "get",
1703                  1,
1704                  "int", "index");
1705  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) return null;"
1706             << std::endl;
1707  C.indent() << "return " RS_TYPE_ITEM_BUFFER_NAME "[index];" << std::endl;
1708  C.endFunction();
1709  return;
1710}
1711
1712void RSReflection::genTypeClassComponentSetter(Context &C,
1713                                               const RSExportRecordType *ERT) {
1714  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1715           FE = ERT->fields_end();
1716       FI != FE;
1717       FI++) {
1718    const RSExportRecordType::Field *F = *FI;
1719    size_t FieldOffset = F->getOffsetInParent();
1720    size_t FieldStoreSize = F->getType()->getStoreSize();
1721    unsigned FieldIndex = C.getFieldIndex(F);
1722
1723    C.startFunction(Context::AM_PublicSynchronized,
1724                    false,
1725                    "void",
1726                    "set_" + F->getName(), 3,
1727                    "int", "index",
1728                    GetTypeName(F->getType()).c_str(), "v",
1729                    "boolean", "copyNow");
1730    genNewItemBufferPackerIfNull(C);
1731    genNewItemBufferIfNull(C, "index");
1732    C.indent() << RS_TYPE_ITEM_BUFFER_NAME "[index]." << F->getName()
1733               << " = v;" << std::endl;
1734
1735    C.indent() << "if (copyNow) ";
1736    C.startBlock();
1737
1738    if (FieldOffset > 0)
1739      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1740                    ".reset(index * " RS_TYPE_ITEM_CLASS_NAME ".sizeof + "
1741                 << FieldOffset << ");" << std::endl;
1742    else
1743      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1744                    ".reset(index * " RS_TYPE_ITEM_CLASS_NAME ".sizeof);"
1745                 << std::endl;
1746    genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1747
1748    C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");"
1749               << std::endl;
1750    genPackVarOfType(C, F->getType(), "v", "fp");
1751    C.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex
1752               << ", fp);"
1753               << std::endl;
1754
1755    // End of if (copyNow)
1756    C.endBlock();
1757
1758    C.endFunction();
1759  }
1760  return;
1761}
1762
1763void RSReflection::genTypeClassComponentGetter(Context &C,
1764                                               const RSExportRecordType *ERT) {
1765  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1766           FE = ERT->fields_end();
1767       FI != FE;
1768       FI++) {
1769    const RSExportRecordType::Field *F = *FI;
1770    C.startFunction(Context::AM_PublicSynchronized,
1771                    false,
1772                    GetTypeName(F->getType()).c_str(),
1773                    "get_" + F->getName(),
1774                    1,
1775                    "int", "index");
1776    C.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) return "
1777               << GetTypeNullValue(F->getType()) << ";" << std::endl;
1778    C.indent() << "return " RS_TYPE_ITEM_BUFFER_NAME "[index]." << F->getName()
1779               << ";" << std::endl;
1780    C.endFunction();
1781  }
1782  return;
1783}
1784
1785void RSReflection::genTypeClassCopyAll(Context &C,
1786                                       const RSExportRecordType *ERT) {
1787  C.startFunction(Context::AM_PublicSynchronized, false, "void", "copyAll", 0);
1788
1789  C.indent() << "for (int ct = 0; ct < " RS_TYPE_ITEM_BUFFER_NAME ".length; ct++)"
1790                  " copyToArray(" RS_TYPE_ITEM_BUFFER_NAME "[ct], ct);"
1791             << std::endl;
1792  C.indent() << "mAllocation.setFromFieldPacker(0, "
1793                  RS_TYPE_ITEM_BUFFER_PACKER_NAME ");"
1794             << std::endl;
1795
1796  C.endFunction();
1797  return;
1798}
1799
1800void RSReflection::genTypeClassResize(Context &C) {
1801  C.startFunction(Context::AM_PublicSynchronized,
1802                  false,
1803                  "void",
1804                  "resize",
1805                  1,
1806                  "int", "newSize");
1807
1808  C.indent() << "if (mItemArray != null) ";
1809  C.startBlock();
1810  C.indent() << "int oldSize = mItemArray.length;" << std::endl;
1811  C.indent() << "int copySize = Math.min(oldSize, newSize);" << std::endl;
1812  C.indent() << "if (newSize == oldSize) return;" << std::endl;
1813  C.indent() << "Item ni[] = new Item[newSize];" << std::endl;
1814  C.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);"
1815             << std::endl;
1816  C.indent() << "mItemArray = ni;" << std::endl;
1817  C.endBlock();
1818  C.indent() << "mAllocation.resize(newSize);" << std::endl;
1819
1820  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME " != null) "
1821                  RS_TYPE_ITEM_BUFFER_PACKER_NAME " = "
1822                    "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME
1823                      ".sizeof * getType().getX()/* count */"
1824                        ");" << std::endl;
1825
1826  C.endFunction();
1827  return;
1828}
1829
1830/******************** Methods to generate type class /end ********************/
1831
1832/********** Methods to create Element in Java of given record type ***********/
1833void RSReflection::genBuildElement(Context &C,
1834                                   const char *ElementBuilderName,
1835                                   const RSExportRecordType *ERT,
1836                                   const char *RenderScriptVar,
1837                                   bool IsInline) {
1838  C.indent() << "Element.Builder " << ElementBuilderName << " = "
1839      "new Element.Builder(" << RenderScriptVar << ");" << std::endl;
1840
1841  // eb.add(...)
1842  genAddElementToElementBuilder(C,
1843                                ERT,
1844                                "",
1845                                ElementBuilderName,
1846                                RenderScriptVar,
1847                                /* ArraySize = */0);
1848
1849  if (!IsInline)
1850    C.indent() << "return " << ElementBuilderName << ".create();" << std::endl;
1851  return;
1852}
1853
1854#define EB_ADD(x) do {                                              \
1855  C.indent() << ElementBuilderName                                  \
1856             << ".add(" << x << ", \"" << VarName << "\"";  \
1857  if (ArraySize > 0)                                                \
1858    C.out() << ", " << ArraySize;                                   \
1859  C.out() << ");" << std::endl;                                     \
1860  C.incFieldIndex();                                                \
1861} while (false)
1862
1863void RSReflection::genAddElementToElementBuilder(Context &C,
1864                                                 const RSExportType *ET,
1865                                                 const std::string &VarName,
1866                                                 const char *ElementBuilderName,
1867                                                 const char *RenderScriptVar,
1868                                                 unsigned ArraySize) {
1869  std::string ElementConstruct = GetBuiltinElementConstruct(ET);
1870
1871  if (ElementConstruct != "") {
1872    EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
1873  } else {
1874    if ((ET->getClass() == RSExportType::ExportClassPrimitive) ||
1875        (ET->getClass() == RSExportType::ExportClassVector)) {
1876      const RSExportPrimitiveType *EPT =
1877          static_cast<const RSExportPrimitiveType*>(ET);
1878      const char *DataTypeName =
1879          RSExportPrimitiveType::getRSReflectionType(EPT)->rs_type;
1880      int Size = (ET->getClass() == RSExportType::ExportClassVector) ?
1881          static_cast<const RSExportVectorType*>(ET)->getNumElement() :
1882          1;
1883
1884      if (EPT->getClass() == RSExportType::ExportClassPrimitive) {
1885        // Element.createUser()
1886        EB_ADD("Element.createUser(" << RenderScriptVar
1887                                     << ", Element.DataType."
1888                                     << DataTypeName << ")");
1889      } else {
1890        slangAssert((ET->getClass() == RSExportType::ExportClassVector) &&
1891                    "Unexpected type.");
1892        EB_ADD("Element.createVector(" << RenderScriptVar
1893                                       << ", Element.DataType."
1894                                       << DataTypeName << ", "
1895                                       << Size << ")");
1896      }
1897#ifndef NDEBUG
1898    } else if (ET->getClass() == RSExportType::ExportClassPointer) {
1899      // Pointer type variable should be resolved in
1900      // GetBuiltinElementConstruct()
1901      slangAssert(false && "??");
1902    } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
1903      // Matrix type variable should be resolved
1904      // in GetBuiltinElementConstruct()
1905      slangAssert(false && "??");
1906#endif
1907    } else if (ET->getClass() == RSExportType::ExportClassConstantArray) {
1908      const RSExportConstantArrayType *ECAT =
1909          static_cast<const RSExportConstantArrayType *>(ET);
1910
1911      const RSExportType *ElementType = ECAT->getElementType();
1912      if (ElementType->getClass() != RSExportType::ExportClassRecord) {
1913        genAddElementToElementBuilder(C,
1914                                      ECAT->getElementType(),
1915                                      VarName,
1916                                      ElementBuilderName,
1917                                      RenderScriptVar,
1918                                      ECAT->getSize());
1919      } else {
1920        std::string NewElementBuilderName(ElementBuilderName);
1921        NewElementBuilderName.append(1, '_');
1922
1923        genBuildElement(C,
1924                        NewElementBuilderName.c_str(),
1925                        static_cast<const RSExportRecordType*>(ElementType),
1926                        RenderScriptVar,
1927                        /* IsInline = */true);
1928        ArraySize = ECAT->getSize();
1929        EB_ADD(NewElementBuilderName << ".create()");
1930      }
1931    } else if (ET->getClass() == RSExportType::ExportClassRecord) {
1932      // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
1933      //
1934      // TODO(zonr): Generalize these two function such that there's no
1935      //             duplicated codes.
1936      const RSExportRecordType *ERT =
1937          static_cast<const RSExportRecordType*>(ET);
1938      int Pos = 0;    // relative pos from now on
1939
1940      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1941               E = ERT->fields_end();
1942           I != E;
1943           I++) {
1944        const RSExportRecordType::Field *F = *I;
1945        std::string FieldName;
1946        int FieldOffset = F->getOffsetInParent();
1947        const RSExportType *T = F->getType();
1948        int FieldStoreSize = T->getStoreSize();
1949        int FieldAllocSize = T->getAllocSize();
1950
1951        if (!VarName.empty())
1952          FieldName = VarName + "." + F->getName();
1953        else
1954          FieldName = F->getName();
1955
1956        // Alignment
1957        genAddPaddingToElementBuiler(C,
1958                                     (FieldOffset - Pos),
1959                                     ElementBuilderName,
1960                                     RenderScriptVar);
1961
1962        // eb.add(...)
1963        C.addFieldIndexMapping(F);
1964        if (F->getType()->getClass() != RSExportType::ExportClassRecord) {
1965          genAddElementToElementBuilder(C,
1966                                        F->getType(),
1967                                        FieldName,
1968                                        ElementBuilderName,
1969                                        RenderScriptVar,
1970                                        0);
1971        } else {
1972          std::string NewElementBuilderName(ElementBuilderName);
1973          NewElementBuilderName.append(1, '_');
1974
1975          genBuildElement(C,
1976                          NewElementBuilderName.c_str(),
1977                          static_cast<const RSExportRecordType*>(F->getType()),
1978                          RenderScriptVar,
1979                          /* IsInline = */true);
1980
1981          const std::string &VarName = FieldName;  // Hack for EB_ADD macro
1982          EB_ADD(NewElementBuilderName << ".create()");
1983        }
1984
1985        if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
1986          // There is padding within the field type. This is only necessary
1987          // for HC-targeted APIs.
1988          genAddPaddingToElementBuiler(C,
1989                                       (FieldAllocSize - FieldStoreSize),
1990                                       ElementBuilderName,
1991                                       RenderScriptVar);
1992        }
1993
1994        Pos = FieldOffset + FieldAllocSize;
1995      }
1996
1997      // There maybe some padding after the struct
1998      size_t RecordAllocSize = ERT->getAllocSize();
1999
2000      genAddPaddingToElementBuiler(C,
2001                                   RecordAllocSize - Pos,
2002                                   ElementBuilderName,
2003                                   RenderScriptVar);
2004    } else {
2005      slangAssert(false && "Unknown class of type");
2006    }
2007  }
2008}
2009
2010void RSReflection::genAddPaddingToElementBuiler(Context &C,
2011                                                int PaddingSize,
2012                                                const char *ElementBuilderName,
2013                                                const char *RenderScriptVar) {
2014  unsigned ArraySize = 0;   // Hack the EB_ADD macro
2015  while (PaddingSize > 0) {
2016    const std::string &VarName = C.createPaddingField();
2017    if (PaddingSize >= 4) {
2018      EB_ADD("Element.U32(" << RenderScriptVar << ")");
2019      PaddingSize -= 4;
2020    } else if (PaddingSize >= 2) {
2021      EB_ADD("Element.U16(" << RenderScriptVar << ")");
2022      PaddingSize -= 2;
2023    } else if (PaddingSize >= 1) {
2024      EB_ADD("Element.U8(" << RenderScriptVar << ")");
2025      PaddingSize -= 1;
2026    }
2027  }
2028  return;
2029}
2030
2031#undef EB_ADD
2032/******** Methods to create Element in Java of given record type /end ********/
2033
2034bool RSReflection::reflect(const std::string &OutputPathBase,
2035                           const std::string &OutputPackageName,
2036                           const std::string &RSPackageName,
2037                           const std::string &InputFileName,
2038                           const std::string &OutputBCFileName) {
2039  Context *C = NULL;
2040  std::string ResourceId = "";
2041  std::string PaddingPrefix = "";
2042
2043  if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
2044    PaddingPrefix = "#padding_";
2045  } else {
2046    PaddingPrefix = "#rs_padding_";
2047  }
2048
2049  if (!GetClassNameFromFileName(OutputBCFileName, ResourceId))
2050    return false;
2051
2052  if (ResourceId.empty())
2053    ResourceId = "<Resource ID>";
2054
2055  if (OutputPackageName.empty() || OutputPackageName == "-")
2056    C = new Context(OutputPathBase, InputFileName, "<Package Name>",
2057                    RSPackageName, ResourceId, PaddingPrefix, true);
2058  else
2059    C = new Context(OutputPathBase, InputFileName, OutputPackageName,
2060                    RSPackageName, ResourceId, PaddingPrefix, false);
2061
2062  if (C != NULL) {
2063    std::string ErrorMsg, ScriptClassName;
2064    // class ScriptC_<ScriptName>
2065    if (!GetClassNameFromFileName(InputFileName, ScriptClassName))
2066      return false;
2067
2068    if (ScriptClassName.empty())
2069      ScriptClassName = "<Input Script Name>";
2070
2071    ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
2072
2073    if (mRSContext->getLicenseNote() != NULL) {
2074      C->setLicenseNote(*(mRSContext->getLicenseNote()));
2075    }
2076
2077    if (!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
2078      std::cerr << "Failed to generate class " << ScriptClassName << " ("
2079                << ErrorMsg << ")" << std::endl;
2080      return false;
2081    }
2082
2083    mGeneratedFileNames->push_back(ScriptClassName);
2084
2085    // class ScriptField_<TypeName>
2086    for (RSContext::const_export_type_iterator TI =
2087             mRSContext->export_types_begin(),
2088             TE = mRSContext->export_types_end();
2089         TI != TE;
2090         TI++) {
2091      const RSExportType *ET = TI->getValue();
2092
2093      if (ET->getClass() == RSExportType::ExportClassRecord) {
2094        const RSExportRecordType *ERT =
2095            static_cast<const RSExportRecordType*>(ET);
2096
2097        if (!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
2098          std::cerr << "Failed to generate type class for struct '"
2099                    << ERT->getName() << "' (" << ErrorMsg << ")" << std::endl;
2100          return false;
2101        }
2102      }
2103    }
2104  }
2105
2106  return true;
2107}
2108
2109/************************** RSReflection::Context **************************/
2110const char *const RSReflection::Context::ApacheLicenseNote =
2111    "/*\n"
2112    " * Copyright (C) 2011-2013 The Android Open Source Project\n"
2113    " *\n"
2114    " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
2115    " * you may not use this file except in compliance with the License.\n"
2116    " * You may obtain a copy of the License at\n"
2117    " *\n"
2118    " *      http://www.apache.org/licenses/LICENSE-2.0\n"
2119    " *\n"
2120    " * Unless required by applicable law or agreed to in writing, software\n"
2121    " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
2122    " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
2123    "implied.\n"
2124    " * See the License for the specific language governing permissions and\n"
2125    " * limitations under the License.\n"
2126    " */\n"
2127    "\n";
2128
2129bool RSReflection::Context::openClassFile(const std::string &ClassName,
2130                                          std::string &ErrorMsg) {
2131  if (!mUseStdout) {
2132    mOF.clear();
2133    std::string Path =
2134        RSSlangReflectUtils::ComputePackagedPath(mOutputPathBase.c_str(),
2135                                                 mPackageName.c_str());
2136
2137    if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg))
2138      return false;
2139
2140    std::string ClassFile = Path + OS_PATH_SEPARATOR_STR + ClassName + ".java";
2141
2142    mOF.open(ClassFile.c_str());
2143    if (!mOF.good()) {
2144      ErrorMsg = "failed to open file '" + ClassFile + "' for write";
2145      return false;
2146    }
2147  }
2148  return true;
2149}
2150
2151const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) {
2152  switch (AM) {
2153    case AM_Public: return "public"; break;
2154    case AM_Protected: return "protected"; break;
2155    case AM_Private: return "private"; break;
2156    case AM_PublicSynchronized: return "public synchronized"; break;
2157    default: return ""; break;
2158  }
2159}
2160
2161bool RSReflection::Context::startClass(AccessModifier AM,
2162                                       bool IsStatic,
2163                                       const std::string &ClassName,
2164                                       const char *SuperClassName,
2165                                       std::string &ErrorMsg) {
2166  if (mVerbose)
2167    std::cout << "Generating " << ClassName << ".java ..." << std::endl;
2168
2169  // Open file for class
2170  if (!openClassFile(ClassName, ErrorMsg))
2171    return false;
2172
2173  // License
2174  out() << mLicenseNote;
2175
2176  // Notice of generated file
2177  out() << "/*" << std::endl;
2178  out() << " * This file is auto-generated. DO NOT MODIFY!" << std::endl;
2179  out() << " * The source Renderscript file: "
2180        << SanitizeString(mInputRSFile) << std::endl;
2181  out() << " */" << std::endl;
2182
2183  // Package
2184  if (!mPackageName.empty())
2185    out() << "package " << mPackageName << ";" << std::endl;
2186  out() << std::endl;
2187
2188  // Imports
2189  out() << "import " << mRSPackageName << ".*;" << std::endl;
2190  out() << "import android.content.res.Resources;" << std::endl;
2191  out() << std::endl;
2192
2193  // All reflected classes should be annotated as hidden, so that they won't
2194  // be exposed in SDK.
2195  out() << "/**" << std::endl;
2196  out() << " * @hide" << std::endl;
2197  out() << " */" << std::endl;
2198
2199  out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
2200        << ClassName;
2201  if (SuperClassName != NULL)
2202    out() << " extends " << SuperClassName;
2203
2204  startBlock();
2205
2206  mClassName = ClassName;
2207
2208  return true;
2209}
2210
2211void RSReflection::Context::endClass() {
2212  endBlock();
2213  if (!mUseStdout)
2214    mOF.close();
2215  clear();
2216  return;
2217}
2218
2219void RSReflection::Context::startBlock(bool ShouldIndent) {
2220  if (ShouldIndent)
2221    indent() << "{" << std::endl;
2222  else
2223    out() << " {" << std::endl;
2224  incIndentLevel();
2225  return;
2226}
2227
2228void RSReflection::Context::endBlock() {
2229  decIndentLevel();
2230  indent() << "}" << std::endl << std::endl;
2231  return;
2232}
2233
2234void RSReflection::Context::startTypeClass(const std::string &ClassName) {
2235  indent() << "public static class " << ClassName;
2236  startBlock();
2237  return;
2238}
2239
2240void RSReflection::Context::endTypeClass() {
2241  endBlock();
2242  return;
2243}
2244
2245void RSReflection::Context::startFunction(AccessModifier AM,
2246                                          bool IsStatic,
2247                                          const char *ReturnType,
2248                                          const std::string &FunctionName,
2249                                          int Argc, ...) {
2250  ArgTy Args;
2251  va_list vl;
2252  va_start(vl, Argc);
2253
2254  for (int i = 0; i < Argc; i++) {
2255    const char *ArgType = va_arg(vl, const char*);
2256    const char *ArgName = va_arg(vl, const char*);
2257
2258    Args.push_back(std::make_pair(ArgType, ArgName));
2259  }
2260  va_end(vl);
2261
2262  startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
2263
2264  return;
2265}
2266
2267void RSReflection::Context::startFunction(AccessModifier AM,
2268                                          bool IsStatic,
2269                                          const char *ReturnType,
2270                                          const std::string &FunctionName,
2271                                          const ArgTy &Args) {
2272  indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
2273           << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
2274
2275  bool FirstArg = true;
2276  for (ArgTy::const_iterator I = Args.begin(), E = Args.end();
2277       I != E;
2278       I++) {
2279    if (!FirstArg)
2280      out() << ", ";
2281    else
2282      FirstArg = false;
2283
2284    out() << I->first << " " << I->second;
2285  }
2286
2287  out() << ")";
2288  startBlock();
2289
2290  return;
2291}
2292
2293void RSReflection::Context::endFunction() {
2294  endBlock();
2295  return;
2296}
2297
2298bool RSReflection::Context::addTypeNameForElement(
2299    const std::string &TypeName) {
2300  if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
2301    mTypesToCheck.insert(TypeName);
2302    return true;
2303  } else {
2304    return false;
2305  }
2306}
2307
2308bool RSReflection::Context::addTypeNameForFieldPacker(
2309    const std::string &TypeName) {
2310  if (mFieldPackerTypes.find(TypeName) == mFieldPackerTypes.end()) {
2311    mFieldPackerTypes.insert(TypeName);
2312    return true;
2313  } else {
2314    return false;
2315  }
2316}
2317
2318}  // namespace slang
2319