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