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