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