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