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