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