slang_rs_reflection.cpp revision 70842c7439bd523611f3ed232ecc6de844932145
1#include "slang_rs_context.hpp"
2#include "slang_rs_export_var.hpp"
3#include "slang_rs_reflection.hpp"
4#include "slang_rs_export_func.hpp"
5#include "slang_rs_reflect_utils.hpp"
6
7#include <ctype.h>
8
9#include <utility>
10#include <cstdarg>
11
12#include "llvm/ADT/APFloat.h"
13
14using std::make_pair;
15using std::endl;
16
17
18#define RS_SCRIPT_CLASS_NAME_PREFIX         "ScriptC_"
19#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME    "ScriptC"
20
21#define RS_TYPE_CLASS_NAME_PREFIX           "ScriptField_"
22#define RS_TYPE_CLASS_SUPER_CLASS_NAME      "android.renderscript.Script.FieldBase"
23
24#define RS_TYPE_ITEM_CLASS_NAME             "Item"
25
26#define RS_TYPE_ITEM_BUFFER_NAME            "mItemArray"
27#define RS_TYPE_ITEM_BUFFER_PACKER_NAME     "mIOBuffer"
28
29#define RS_EXPORT_VAR_INDEX_PREFIX          "mExportVarIdx_"
30#define RS_EXPORT_VAR_PREFIX                "mExportVar_"
31
32#define RS_EXPORT_FUNC_INDEX_PREFIX         "mExportFuncIdx_"
33
34#define RS_EXPORT_VAR_ALLOCATION_PREFIX     "mAlloction_"
35#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX   "mData_"
36
37namespace slang {
38
39/* Some utility function using internal in RSReflection */
40static bool GetClassNameFromFileName(const std::string& FileName, std::string& ClassName) {
41    ClassName.clear();
42
43    if(FileName.empty() || (FileName == "-"))
44        return true;
45
46    ClassName = RSSlangReflectUtils::JavaClassNameFromRSFileName(FileName.c_str());
47
48    return true;
49}
50
51static const char* GetPrimitiveTypeName(const RSExportPrimitiveType* EPT) {
52    static const char* PrimitiveTypeJavaNameMap[] = {
53        "",
54        "",
55        "float",    /* RSExportPrimitiveType::DataTypeFloat32 */
56        "double",   /* RSExportPrimitiveType::DataTypeFloat64 */
57        "byte",     /* RSExportPrimitiveType::DataTypeSigned8 */
58        "short",    /* RSExportPrimitiveType::DataTypeSigned16 */
59        "int",      /* RSExportPrimitiveType::DataTypeSigned32 */
60        "long",     /* RSExportPrimitiveType::DataTypeSigned64 */
61        "short",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
62        "int",      /* RSExportPrimitiveType::DataTypeUnsigned16 */
63        "long",     /* RSExportPrimitiveType::DataTypeUnsigned32 */
64        "long",     /* RSExportPrimitiveType::DataTypeUnsigned64 */
65
66        "int",      /* RSExportPrimitiveType::DataTypeUnsigned565 */
67        "int",      /* RSExportPrimitiveType::DataTypeUnsigned5551 */
68        "int",      /* RSExportPrimitiveType::DataTypeUnsigned4444 */
69
70        "boolean",  /* RSExportPrimitiveType::DataTypeBool */
71
72        "Element",  /* RSExportPrimitiveType::DataTypeRSElement */
73        "Type",     /* RSExportPrimitiveType::DataTypeRSType */
74        "Allocation",   /* RSExportPrimitiveType::DataTypeRSAllocation */
75        "Sampler",  /* RSExportPrimitiveType::DataTypeRSSampler */
76        "Script",   /* RSExportPrimitiveType::DataTypeRSScript */
77        "Mesh",       /* RSExportPrimitiveType::DataTypeRSMesh */
78        "ProgramFragment",  /* RSExportPrimitiveType::DataTypeRSProgramFragment */
79        "ProgramVertex",    /* RSExportPrimitiveType::DataTypeRSProgramVertex */
80        "ProgramRaster",    /* RSExportPrimitiveType::DataTypeRSProgramRaster */
81        "ProgramStore",     /* RSExportPrimitiveType::DataTypeRSProgramStore */
82        "Font",     /* RSExportPrimitiveType::DataTypeRSFont */
83        "Matrix2f",     /* RSExportPrimitiveType::DataTypeRSMatrix2x2 */
84        "Matrix3f",     /* RSExportPrimitiveType::DataTypeRSMatrix3x3 */
85        "Matrix4f",     /* RSExportPrimitiveType::DataTypeRSMatrix4x4 */
86    };
87    unsigned TypeId = EPT->getType();
88
89    if(TypeId < (sizeof(PrimitiveTypeJavaNameMap) / sizeof(const char*))) {
90        // printf("Type %d\n", EPT->getType());
91        return PrimitiveTypeJavaNameMap[ EPT->getType() ];
92    }
93
94    assert(false && "GetPrimitiveTypeName : Unknown primitive data type");
95    return NULL;
96}
97
98static const char* GetVectorTypeName(const RSExportVectorType* EVT) {
99    static const char* VectorTypeJavaNameMap[][3] = {
100        /* 0 */ { "Byte2",  "Byte3",    "Byte4" },
101        /* 1 */ { "Short2", "Short3",   "Short4" },
102        /* 2 */ { "Int2",   "Int3",     "Int4" },
103        /* 3 */ { "Long2",  "Long3",    "Long4" },
104        /* 4 */ { "Float2", "Float3",   "Float4" },
105    };
106
107    const char** BaseElement = NULL;
108
109    switch(EVT->getType()) {
110        case RSExportPrimitiveType::DataTypeSigned8:
111            BaseElement = VectorTypeJavaNameMap[0];
112        break;
113
114        case RSExportPrimitiveType::DataTypeSigned16:
115        case RSExportPrimitiveType::DataTypeUnsigned8:
116            BaseElement = VectorTypeJavaNameMap[1];
117        break;
118
119        case RSExportPrimitiveType::DataTypeSigned32:
120        case RSExportPrimitiveType::DataTypeUnsigned16:
121            BaseElement = VectorTypeJavaNameMap[2];
122        break;
123
124        case RSExportPrimitiveType::DataTypeUnsigned32:
125            BaseElement = VectorTypeJavaNameMap[3];
126        break;
127
128        case RSExportPrimitiveType::DataTypeFloat32:
129            BaseElement = VectorTypeJavaNameMap[4];
130        break;
131
132        case RSExportPrimitiveType::DataTypeBool:
133            BaseElement = VectorTypeJavaNameMap[0];
134        break;
135
136        default:
137            assert(false && "RSReflection::genElementTypeName : Unsupported vector element data type");
138        break;
139    }
140
141    assert((EVT->getNumElement() > 1) && (EVT->getNumElement() <= 4) && "Number of element in vector type is invalid");
142
143    return BaseElement[EVT->getNumElement() - 2];
144}
145
146static const char* GetVectorAccessor(int Index) {
147    static const char* VectorAccessorMap[] = {
148        /* 0 */ "x",
149        /* 1 */ "y",
150        /* 2 */ "z",
151        /* 3 */ "w",
152    };
153
154    assert((Index >= 0) && (Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) && "Out-of-bound index to access vector member");
155
156    return VectorAccessorMap[Index];
157}
158
159static const char* GetPackerAPIName(const RSExportPrimitiveType* EPT) {
160    static const char* PrimitiveTypePackerAPINameMap[] = {
161        "",
162        "",
163        "addF32",   /* RSExportPrimitiveType::DataTypeFloat32 */
164        "addF64",   /* RSExportPrimitiveType::DataTypeFloat64 */
165        "addI8",    /* RSExportPrimitiveType::DataTypeSigned8 */
166        "addI16",   /* RSExportPrimitiveType::DataTypeSigned16 */
167        "addI32",   /* RSExportPrimitiveType::DataTypeSigned32 */
168        "addI64",   /* RSExportPrimitiveType::DataTypeSigned64 */
169        "addU8",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
170        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned16 */
171        "addU32",   /* RSExportPrimitiveType::DataTypeUnsigned32 */
172        "addU64",   /* RSExportPrimitiveType::DataTypeUnsigned64 */
173
174        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
175        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
176        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
177
178        "addBoolean",  /* RSExportPrimitiveType::DataTypeBool */
179
180        "addObj",   /* RSExportPrimitiveType::DataTypeRSElement */
181        "addObj",   /* RSExportPrimitiveType::DataTypeRSType */
182        "addObj",   /* RSExportPrimitiveType::DataTypeRSAllocation */
183        "addObj",   /* RSExportPrimitiveType::DataTypeRSSampler */
184        "addObj",   /* RSExportPrimitiveType::DataTypeRSScript */
185        "addObj",   /* RSExportPrimitiveType::DataTypeRSMesh */
186        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramFragment */
187        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
188        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
189        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramStore */
190        "addObj",   /* RSExportPrimitiveType::DataTypeRSFont */
191        "addObj",   /* RSExportPrimitiveType::DataTypeRSMatrix2x2 */
192        "addObj",   /* RSExportPrimitiveType::DataTypeRSMatrix3x3 */
193        "addObj",   /* RSExportPrimitiveType::DataTypeRSMatrix4x4 */
194    };
195    unsigned TypeId = EPT->getType();
196
197    if(TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*)))
198        return PrimitiveTypePackerAPINameMap[ EPT->getType() ];
199
200    assert(false && "GetPackerAPIName : Unknown primitive data type");
201    return NULL;
202}
203
204static std::string GetTypeName(const RSExportType* ET) {
205    switch(ET->getClass()) {
206        case RSExportType::ExportClassPrimitive:
207        case RSExportType::ExportClassConstantArray:
208            return GetPrimitiveTypeName(static_cast<const RSExportPrimitiveType*>(ET));
209        break;
210
211        case RSExportType::ExportClassPointer:
212        {
213            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
214
215            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
216                return "Allocation";
217            else
218                return RS_TYPE_CLASS_NAME_PREFIX + PointeeType->getName();
219        }
220        break;
221
222        case RSExportType::ExportClassVector:
223            return GetVectorTypeName(static_cast<const RSExportVectorType*>(ET));
224        break;
225
226        case RSExportType::ExportClassRecord:
227            return RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
228        break;
229
230        default:
231            assert(false && "Unknown class of type");
232        break;
233    }
234
235    return "";
236}
237
238static const char* GetBuiltinElementConstruct(const RSExportType* ET) {
239    if (ET->getClass() == RSExportType::ExportClassPrimitive || ET->getClass() == RSExportType::ExportClassConstantArray) {
240        const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
241        if (EPT->getKind() == RSExportPrimitiveType::DataKindUser) {
242            static const char* PrimitiveBuiltinElementConstructMap[] = {
243                NULL,
244                NULL,
245                "F32", /* RSExportPrimitiveType::DataTypeFloat32 */
246                "F64",       /* RSExportPrimitiveType::DataTypeFloat64 */
247                "I8",  /* RSExportPrimitiveType::DataTypeSigned8 */
248                NULL,       /* RSExportPrimitiveType::DataTypeSigned16 */
249                "I32", /* RSExportPrimitiveType::DataTypeSigned32 */
250                NULL,       /* RSExportPrimitiveType::DataTypeSigned64 */
251                "U8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
252                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned16 */
253                "U32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
254                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned64 */
255
256                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned565 */
257                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
258                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
259
260                "BOOLEAN",  /* RSExportPrimitiveType::DataTypeBool */
261
262                "ELEMENT", /* RSExportPrimitiveType::DataTypeRSElement */
263                "TYPE",    /* RSExportPrimitiveType::DataTypeRSType */
264                "ALLOCATION",  /* RSExportPrimitiveType::DataTypeRSAllocation */
265                "SAMPLER",     /* RSExportPrimitiveType::DataTypeRSSampler */
266                "SCRIPT",      /* RSExportPrimitiveType::DataTypeRSScript */
267                "MESH",        /* RSExportPrimitiveType::DataTypeRSMesh */
268                "PROGRAM_FRAGMENT",    /* RSExportPrimitiveType::DataTypeRSProgramFragment */
269                "PROGRAM_VERTEX",      /* RSExportPrimitiveType::DataTypeRSProgramVertex */
270                "PROGRAM_RASTER",      /* RSExportPrimitiveType::DataTypeRSProgramRaster */
271                "PROGRAM_STORE",       /* RSExportPrimitiveType::DataTypeRSProgramStore */
272                "FONT",       /* RSExportPrimitiveType::DataTypeRSFont */
273                "MATRIX_2X2",       /* RSExportPrimitiveType::DataTypeRSMatrix2x2 */
274                "MATRIX_3X3",       /* RSExportPrimitiveType::DataTypeRSMatrix3x3 */
275                "MATRIX_4X4",       /* RSExportPrimitiveType::DataTypeRSMatrix4x4 */
276            };
277            unsigned TypeId = EPT->getType();
278
279            if (TypeId < (sizeof(PrimitiveBuiltinElementConstructMap) / sizeof(const char*)))
280                return PrimitiveBuiltinElementConstructMap[ EPT->getType() ];
281        } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelA) {
282            if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
283                return "A_8";
284        } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGB) {
285            if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned565)
286                return "RGB_565";
287            else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
288                return "RGB_888";
289        } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGBA) {
290            if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned5551)
291                return "RGB_5551";
292            else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned4444)
293                return "RGB_4444";
294            else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
295                return "RGB_8888";
296        } else if (EPT->getKind() == RSExportPrimitiveType::DataKindIndex) {
297            if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned16)
298                return "INDEX_16";
299        }
300    } else if (ET->getClass() == RSExportType::ExportClassVector) {
301        const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(ET);
302        if (EVT->getKind() == RSExportPrimitiveType::DataKindPosition) {
303            if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
304                if (EVT->getNumElement() == 2)
305                    return "ATTRIB_POSITION_2";
306                else if (EVT->getNumElement() == 3)
307                    return "ATTRIB_POSITION_3";
308            }
309        } else if (EVT->getKind() == RSExportPrimitiveType::DataKindTexture) {
310            if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
311                if (EVT->getNumElement() == 2)
312                    return "ATTRIB_TEXTURE_2";
313            }
314        } else if (EVT->getKind() == RSExportPrimitiveType::DataKindNormal) {
315            if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
316                if (EVT->getNumElement() == 3)
317                    return "ATTRIB_NORMAL_3";
318            }
319        } else if (EVT->getKind() == RSExportPrimitiveType::DataKindColor) {
320            if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
321                if (EVT->getNumElement() == 4)
322                    return "ATTRIB_COLOR_F32_4";
323            } else if (EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
324                if (EVT->getNumElement() == 4)
325                    return "ATTRIB_COLOR_U8_4";
326            }
327        }
328    } else if (ET->getClass() == RSExportType::ExportClassPointer) {
329        return "USER_I32";  /* tread pointer type variable as unsigned int (TODO: this is target dependent) */
330    }
331
332    return NULL;
333}
334
335static const char* GetElementDataKindName(RSExportPrimitiveType::DataKind DK) {
336    static const char* ElementDataKindNameMap[] = {
337        "Element.DataKind.USER",        /* RSExportPrimitiveType::DataKindUser */
338        "Element.DataKind.COLOR",       /* RSExportPrimitiveType::DataKindColor */
339        "Element.DataKind.POSITION",    /* RSExportPrimitiveType::DataKindPosition */
340        "Element.DataKind.TEXTURE",     /* RSExportPrimitiveType::DataKindTexture */
341        "Element.DataKind.NORMAL",      /* RSExportPrimitiveType::DataKindNormal */
342        "Element.DataKind.INDEX",       /* RSExportPrimitiveType::DataKindIndex */
343        "Element.DataKind.POINT_SIZE",  /* RSExportPrimitiveType::DataKindPointSize */
344        "Element.DataKind.PIXEL_L",     /* RSExportPrimitiveType::DataKindPixelL */
345        "Element.DataKind.PIXEL_A",     /* RSExportPrimitiveType::DataKindPixelA */
346        "Element.DataKind.PIXEL_LA",    /* RSExportPrimitiveType::DataKindPixelLA */
347        "Element.DataKind.PIXEL_RGB",   /* RSExportPrimitiveType::DataKindPixelRGB */
348        "Element.DataKind.PIXEL_RGBA",  /* RSExportPrimitiveType::DataKindPixelRGBA */
349    };
350
351    if(static_cast<unsigned>(DK) < (sizeof(ElementDataKindNameMap) / sizeof(const char*)))
352        return ElementDataKindNameMap[ DK ];
353    else
354        return NULL;
355}
356
357static const char* GetElementDataTypeName(RSExportPrimitiveType::DataType DT) {
358    static const char* ElementDataTypeNameMap[] = {
359        NULL,
360        NULL,
361        "Element.DataType.FLOAT_32",    /* RSExportPrimitiveType::DataTypeFloat32 */
362        "Element.DataType.FLOAT_64",    /* RSExportPrimitiveType::DataTypeFloat64 */
363        "Element.DataType.SIGNED_8",    /* RSExportPrimitiveType::DataTypeSigned8 */
364        "Element.DataType.SIGNED_16",   /* RSExportPrimitiveType::DataTypeSigned16 */
365        "Element.DataType.SIGNED_32",   /* RSExportPrimitiveType::DataTypeSigned32 */
366        NULL,                           /* RSExportPrimitiveType::DataTypeSigned64 */
367        "Element.DataType.UNSIGNED_8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
368        "Element.DataType.UNSIGNED_16", /* RSExportPrimitiveType::DataTypeUnsigned16 */
369        "Element.DataType.UNSIGNED_32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
370        NULL,                           /* RSExportPrimitiveType::DataTypeUnsigned64 */
371
372        "Element.DataType.UNSIGNED_5_6_5",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
373        "Element.DataType.UNSIGNED_5_5_5_1", /* RSExportPrimitiveType::DataTypeUnsigned5551 */
374        "Element.DataType.UNSIGNED_4_4_4_4", /* RSExportPrimitiveType::DataTypeUnsigned4444 */
375
376        "Element.DataType.BOOLEAN",     /* RSExportPrimitiveType::DataTypeBool */
377
378        "Element.DataType.RS_ELEMENT",  /* RSExportPrimitiveType::DataTypeRSElement */
379        "Element.DataType.RS_TYPE",     /* RSExportPrimitiveType::DataTypeRSType */
380        "Element.DataType.RS_ALLOCATION",   /* RSExportPrimitiveType::DataTypeRSAllocation */
381        "Element.DataType.RS_SAMPLER",      /* RSExportPrimitiveType::DataTypeRSSampler */
382        "Element.DataType.RS_SCRIPT",       /* RSExportPrimitiveType::DataTypeRSScript */
383        "Element.DataType.RS_MESH",         /* RSExportPrimitiveType::DataTypeRSMesh */
384        "Element.DataType.RS_PROGRAM_FRAGMENT", /* RSExportPrimitiveType::DataTypeRSProgramFragment */
385        "Element.DataType.RS_PROGRAM_VERTEX",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
386        "Element.DataType.RS_PROGRAM_RASTER",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
387        "Element.DataType.RS_PROGRAM_STORE",    /* RSExportPrimitiveType::DataTypeRSProgramStore */
388        "Element.DataType.RS_FONT",    /* RSExportPrimitiveType::DataTypeRSFont */
389        "Element.DataType.RS_MATRIX_2X2",    /* RSExportPrimitiveType::DataTypeRSMatrix2x2 */
390        "Element.DataType.RS_MATRIX_3X3",    /* RSExportPrimitiveType::DataTypeRSMatrix3x3 */
391        "Element.DataType.RS_MATRIX_4X4",    /* RSExportPrimitiveType::DataTypeRSMatrix4x4 */
392    };
393
394    if(static_cast<unsigned>(DT) < (sizeof(ElementDataTypeNameMap) / sizeof(const char*)))
395        return ElementDataTypeNameMap[ DT ];
396    else
397        return NULL;
398}
399
400bool RSReflection::openScriptFile(Context&C, const std::string& ClassName, std::string& ErrorMsg) {
401    if(!C.mUseStdout) {
402        C.mOF.clear();
403        std::string _path = RSSlangReflectUtils::ComputePackagedPath(
404            mRSContext->getReflectJavaPathName().c_str(), C.getPackageName().c_str());
405
406        RSSlangReflectUtils::mkdir_p(_path.c_str());
407        C.mOF.open(( _path + "/" + ClassName + ".java" ).c_str());
408        if(!C.mOF.good()) {
409            ErrorMsg = "failed to open file '" + _path + "/" + ClassName + ".java' for write";
410
411            return false;
412        }
413    }
414    return true;
415}
416
417/****************************** Methods to generate script class ******************************/
418bool RSReflection::genScriptClass(Context& C, const std::string& ClassName, std::string& ErrorMsg) {
419    /* Open the file */
420    if (!openScriptFile(C, ClassName, ErrorMsg)) {
421        return false;
422    }
423
424    if(!C.startClass(Context::AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME, ErrorMsg))
425        return false;
426
427    genScriptClassConstructor(C);
428
429    /* Reflect export variable */
430    for(RSContext::const_export_var_iterator I = mRSContext->export_vars_begin();
431        I != mRSContext->export_vars_end();
432        I++)
433        genExportVariable(C, *I);
434
435    /* Reflect export function */
436    for(RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin();
437        I != mRSContext->export_funcs_end();
438        I++)
439        genExportFunction(C, *I);
440
441    C.endClass();
442
443    return true;
444}
445
446void RSReflection::genScriptClassConstructor(Context& C) {
447    C.indent() << "// Constructor" << endl;
448    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 4, "RenderScript", "rs",
449                                                                          "Resources", "resources",
450                                                                          "int", "id",
451                                                                          "boolean", "isRoot");
452    /* Call constructor of super class */
453    C.indent() << "super(rs, resources, id, isRoot);" << endl;
454
455    /* If an exported variable has initial value, reflect it */
456
457    for(RSContext::const_export_var_iterator I = mRSContext->export_vars_begin();
458        I != mRSContext->export_vars_end();
459        I++)
460    {
461        const RSExportVar* EV = *I;
462        if(!EV->getInit().isUninit())
463            genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
464    }
465
466    C.endFunction();
467    return;
468}
469
470void RSReflection::genInitBoolExportVariable(Context& C, const std::string& VarName, const APValue& Val) {
471    assert(!Val.isUninit() && "Not a valid initializer");
472
473    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
474    assert((Val.getKind() == APValue::Int) && "Bool type has wrong initial APValue");
475
476    if (Val.getInt().getSExtValue() == 0) {
477        C.out() << "false";
478    } else {
479        C.out() << "true";
480    }
481    C.out() << ";" << endl;
482
483    return;
484}
485
486void RSReflection::genInitPrimitiveExportVariable(Context& C, const std::string& VarName, const APValue& Val) {
487    assert(!Val.isUninit() && "Not a valid initializer");
488
489    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
490    switch(Val.getKind()) {
491      case APValue::Int: C.out() << Val.getInt().getSExtValue(); break;
492
493      case APValue::Float: {
494        llvm::APFloat apf = Val.getFloat();
495        if (apf.semanticsPrecision(apf.getSemantics()) == 24 /*llvm::APFloat::IEEEsingle*/) {
496          C.out() << apf.convertToFloat();
497        } else {
498          C.out() << apf.convertToDouble();
499        }
500        break;
501      }
502
503      case APValue::ComplexInt:
504      case APValue::ComplexFloat:
505      case APValue::LValue:
506      case APValue::Vector:
507        assert(false && "Primitive type cannot have such kind of initializer");
508        break;
509
510      default:
511        assert(false && "Unknown kind of initializer");
512        break;
513    }
514    C.out() << ";" << endl;
515
516    return;
517}
518
519void RSReflection::genInitExportVariable(Context& C, const RSExportType* ET, const std::string& VarName, const APValue& Val) {
520    assert(!Val.isUninit() && "Not a valid initializer");
521
522    switch(ET->getClass()) {
523        case RSExportType::ExportClassPrimitive:
524        case RSExportType::ExportClassConstantArray:
525        {
526            const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
527            if (EPT->getType() == RSExportPrimitiveType::DataTypeBool) {
528                genInitBoolExportVariable(C, VarName, Val);
529            } else {
530                genInitPrimitiveExportVariable(C, VarName, Val);
531            }
532            break;
533        }
534
535        case RSExportType::ExportClassPointer:
536            if(!Val.isInt() || Val.getInt().getSExtValue() != 0)
537                std::cout << "Initializer which is non-NULL to pointer type variable will be ignored" << endl;
538        break;
539
540        case RSExportType::ExportClassVector:
541        {
542            const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(ET);
543            switch(Val.getKind()) {
544                case APValue::Int:
545                case APValue::Float:
546                    for(int i=0;i<EVT->getNumElement();i++) {
547                        std::string Name =  VarName + "." + GetVectorAccessor(i);
548                        genInitPrimitiveExportVariable(C, Name, Val);
549                    }
550                break;
551
552                case APValue::Vector:
553                {
554                    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new " << GetVectorTypeName(EVT) << "();" << endl;
555
556                    unsigned NumElements = std::min(static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
557                    for(unsigned i=0;i<NumElements;i++) {
558                        const APValue& ElementVal = Val.getVectorElt(i);
559                        std::string Name =  VarName + "." + GetVectorAccessor(i);
560                        genInitPrimitiveExportVariable(C, Name, ElementVal);
561                    }
562                }
563                break;
564
565                case APValue::Uninitialized:
566                case APValue::ComplexInt:
567                case APValue::ComplexFloat:
568                case APValue::LValue:
569                    assert(false && "Unexpected type of value of initializer.");
570                break;
571            }
572        }
573        break;
574
575        /* TODO: Resolving initializer of a record type variable is complex. It cannot obtain by just simply evaluating the initializer expression. */
576        case RSExportType::ExportClassRecord:
577        {
578            /*
579            unsigned InitIndex = 0;
580            const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
581
582            assert((Val.getKind() == APValue::Vector) && "Unexpected type of initializer for record type variable");
583
584            C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "RS_TYPE_CLASS_NAME_PREFIX << ERT->getName() <<  "."RS_TYPE_ITEM_CLASS_NAME"();" << endl;
585
586            for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
587                I != ERT->fields_end();
588                I++)
589            {
590                const RSExportRecordType::Field* F = *I;
591                std::string FieldName = VarName + "." + F->getName();
592
593                if(InitIndex > Val.getVectorLength())
594                    break;
595
596                genInitPrimitiveExportVariable(C, FieldName, Val.getVectorElt(InitIndex++));
597            }
598            */
599            assert(false && "Unsupported initializer for record type variable currently");
600        }
601        break;
602
603        default:
604            assert(false && "Unknown class of type");
605        break;
606    }
607    return;
608}
609
610void RSReflection::genExportVariable(Context& C, const RSExportVar* EV) {
611    const RSExportType* ET = EV->getType();
612
613    C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << " = " << C.getNextExportVarSlot() << ";" << endl;
614
615    switch(ET->getClass()) {
616        case RSExportType::ExportClassPrimitive:
617        case RSExportType::ExportClassConstantArray:
618            genPrimitiveTypeExportVariable(C, EV);
619        break;
620
621        case RSExportType::ExportClassPointer:
622            genPointerTypeExportVariable(C, EV);
623        break;
624
625        case RSExportType::ExportClassVector:
626            genVectorTypeExportVariable(C, EV);
627        break;
628
629        case RSExportType::ExportClassRecord:
630            genRecordTypeExportVariable(C, EV);
631        break;
632
633        default:
634            assert(false && "Unknown class of type");
635        break;
636    }
637
638    return;
639}
640
641void RSReflection::genExportFunction(Context& C, const RSExportFunc* EF) {
642    C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << " = " << C.getNextExportFuncSlot() << ";" << endl;
643
644    /* invoke_*() */
645    Context::ArgTy Args;
646
647    for(RSExportFunc::const_param_iterator I = EF->params_begin();
648        I != EF->params_end();
649        I++)
650    {
651        const RSExportFunc::Parameter* P = *I;
652        Args.push_back( make_pair(GetTypeName(P->getType()), P->getName()) );
653    }
654
655    C.startFunction(Context::AM_Public, false, "void", "invoke_" + EF->getName(), Args);
656
657    if(!EF->hasParam()) {
658        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");" << endl;
659    } else {
660        const RSExportRecordType* ERT = EF->getParamPacketType();
661        std::string FieldPackerName = EF->getName() + "_fp";
662
663        if(genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
664            genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
665
666        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", " << FieldPackerName << ");" << endl;
667    }
668
669    C.endFunction();
670    return;
671}
672
673void RSReflection::genPrimitiveTypeExportVariable(Context& C, const RSExportVar* EV) {
674    assert((  EV->getType()->getClass() == RSExportType::ExportClassPrimitive ||
675              EV->getType()->getClass() == RSExportType::ExportClassConstantArray
676           ) && "Variable should be type of primitive here");
677
678    const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(EV->getType());
679    const char* TypeName = GetPrimitiveTypeName(EPT);
680
681    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
682
683    /* set_*() */
684    if(!EV->isConst()) {
685        C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
686        C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
687
688        if(EPT->isRSObjectType())
689            C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", (v == null) ? 0 : v.getID());" << endl;
690        else
691            C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", v);" << endl;
692
693        C.endFunction();
694    }
695
696    genGetExportVariable(C, TypeName, EV->getName());
697
698    return;
699}
700
701void RSReflection::genPointerTypeExportVariable(Context& C, const RSExportVar* EV) {
702    const RSExportType* ET = EV->getType();
703    const RSExportType* PointeeType;
704    std::string TypeName;
705
706    assert((ET->getClass() == RSExportType::ExportClassPointer) && "Variable should be type of pointer here");
707
708    PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
709    TypeName = GetTypeName(ET);
710
711    /* bind_*() */
712    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
713
714    C.startFunction(Context::AM_Public, false, "void", "bind_" + EV->getName(), 1, TypeName.c_str(), "v");
715
716    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
717    C.indent() << "if(v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
718
719    if(PointeeType->getClass() == RSExportType::ExportClassRecord)
720        C.indent() << "else bindAllocation(v.getAllocation(), "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
721    else
722        C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
723
724    C.endFunction();
725
726    genGetExportVariable(C, TypeName, EV->getName());
727
728    return;
729}
730
731void RSReflection::genVectorTypeExportVariable(Context& C, const RSExportVar* EV) {
732    assert((EV->getType()->getClass() == RSExportType::ExportClassVector) && "Variable should be type of vector here");
733
734    const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(EV->getType());
735    const char* TypeName = GetVectorTypeName(EVT);
736    const char* FieldPackerName = "fp";
737
738    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
739
740    /* set_*() */
741    if(!EV->isConst()) {
742        C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
743        C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
744
745        if(genCreateFieldPacker(C, EVT, FieldPackerName))
746            genPackVarOfType(C, EVT, "v", FieldPackerName);
747        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
748
749        C.endFunction();
750    }
751
752    genGetExportVariable(C, TypeName, EV->getName());
753    return;
754}
755
756void RSReflection::genRecordTypeExportVariable(Context& C, const RSExportVar* EV) {
757    assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && "Variable should be type of struct here");
758
759    const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(EV->getType());
760    std::string TypeName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
761    const char* FieldPackerName = "fp";
762
763    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
764
765    /* set_*() */
766    if(!EV->isConst()) {
767        C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName.c_str(), "v");
768        C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
769
770        if(genCreateFieldPacker(C, ERT, FieldPackerName))
771            genPackVarOfType(C, ERT, "v", FieldPackerName);
772        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
773
774        C.endFunction();
775    }
776
777    genGetExportVariable(C, TypeName.c_str(), EV->getName());
778    return;
779}
780
781void RSReflection::genGetExportVariable(Context& C, const std::string& TypeName, const std::string& VarName) {
782    C.startFunction(Context::AM_Public, false, TypeName.c_str(), "get_" + VarName, 0);
783
784    C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << endl;
785
786    C.endFunction();
787    return;
788}
789
790/****************************** Methods to generate script class /end ******************************/
791
792bool RSReflection::genCreateFieldPacker(Context& C, const RSExportType* ET, const char* FieldPackerName) {
793    size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
794    if(AllocSize > 0)
795        C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" << AllocSize << ");" << endl;
796    else
797        return false;
798    return true;
799}
800
801void RSReflection::genPackVarOfType(Context& C, const RSExportType* ET, const char* VarName, const char* FieldPackerName) {
802    switch(ET->getClass()) {
803        case RSExportType::ExportClassPrimitive:
804        case RSExportType::ExportClassVector:
805            C.indent() << FieldPackerName << "." << GetPackerAPIName(static_cast<const RSExportPrimitiveType*>(ET)) << "(" << VarName << ");" << endl;
806        break;
807
808        case RSExportType::ExportClassConstantArray: {
809          if (ET->getName().compare("addObj") == 0) {
810            C.indent() << FieldPackerName << "." << "addObj" << "(" << VarName << ");" << endl;
811          } else {
812            C.indent() << FieldPackerName << "." << GetPackerAPIName(static_cast<const RSExportPrimitiveType*>(ET)) << "(" << VarName << ");" << endl;
813          }
814          break;
815        }
816
817        case RSExportType::ExportClassPointer:
818        {
819            /* Must reflect as type Allocation in Java */
820            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
821
822            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
823                C.indent() << FieldPackerName << ".addI32(" << VarName << ".getPtr());" << endl;
824            else
825                C.indent() << FieldPackerName << ".addI32(" << VarName << ".getAllocation().getPtr());" << endl;
826        }
827        break;
828
829        case RSExportType::ExportClassRecord:
830        {
831            const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
832            unsigned Pos = 0;    /* relative pos from now on in field packer */
833
834            for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
835                I != ERT->fields_end();
836                I++)
837            {
838                const RSExportRecordType::Field* F = *I;
839                std::string FieldName;
840                size_t FieldOffset = F->getOffsetInParent();
841                size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
842                size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
843
844                if(VarName != NULL)
845                    FieldName = VarName + ("." + F->getName());
846                else
847                    FieldName = F->getName();
848
849                if(FieldOffset > Pos)
850                    C.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos) << ");" << endl;
851
852                genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
853
854                if(FieldAllocSize > FieldStoreSize)  /* there's padding in the field type */
855                    C.indent() << FieldPackerName << ".skip(" << (FieldAllocSize - FieldStoreSize) << ");" << endl;
856
857                Pos = FieldOffset + FieldAllocSize;
858            }
859
860            /* There maybe some padding after the struct */
861            size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
862            if(Padding > 0)
863                C.indent() << FieldPackerName << ".skip(" << Padding << ");" << endl;
864        }
865        break;
866
867        default:
868            assert(false && "Unknown class of type");
869        break;
870    }
871
872    return;
873}
874
875void RSReflection::genNewItemBufferIfNull(Context& C, const char* Index) {
876    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "
877                       RS_TYPE_ITEM_BUFFER_NAME" = new "RS_TYPE_ITEM_CLASS_NAME"[mType.getX() /* count */];" << endl;
878    if (Index != NULL)
879        C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] == null) "
880                           RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = new "RS_TYPE_ITEM_CLASS_NAME"();" << endl;
881    return;
882}
883
884void RSReflection::genNewItemBufferPackerIfNull(Context& C) {
885    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_PACKER_NAME" == null) "
886                       RS_TYPE_ITEM_BUFFER_PACKER_NAME" = new FieldPacker("RS_TYPE_ITEM_CLASS_NAME".sizeof * mType.getX() /* count */);" << endl;
887    return;
888}
889
890/****************************** Methods to generate type class  ******************************/
891bool RSReflection::genTypeClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
892    std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
893
894    /* Open the file */
895    if (!openScriptFile(C, ClassName, ErrorMsg)) {
896        return false;
897    }
898
899    if(!C.startClass(Context::AM_Public, false, ClassName, RS_TYPE_CLASS_SUPER_CLASS_NAME, ErrorMsg))
900        return false;
901
902    if(!genTypeItemClass(C, ERT, ErrorMsg))
903        return false;
904
905    /* Declare item buffer and item buffer packer */
906    C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[];" << endl;
907    C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";" << endl;
908
909    genTypeClassConstructor(C, ERT);
910    genTypeClassCopyToArray(C, ERT);
911    genTypeClassItemSetter(C, ERT);
912    genTypeClassItemGetter(C, ERT);
913    genTypeClassComponentSetter(C, ERT);
914    genTypeClassComponentGetter(C, ERT);
915    genTypeClassCopyAll(C, ERT);
916
917    C.endClass();
918
919    return true;
920}
921
922bool RSReflection::genTypeItemClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
923    C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
924    C.startBlock();
925
926    C.indent() << "public static final int sizeof = " << RSExportType::GetTypeAllocSize(ERT) << ";" << endl;
927
928    /* Member elements */
929    C.out() << endl;
930    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
931        FI != ERT->fields_end();
932        FI++) {
933        C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() << ";" << endl;
934    }
935
936    /* Constructor */
937    C.out() << endl;
938    C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
939    C.startBlock();
940
941    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
942        FI != ERT->fields_end();
943        FI++)
944    {
945        const RSExportRecordType::Field* F = *FI;
946        if( (F->getType()->getClass() == RSExportType::ExportClassVector) ||
947            (F->getType()->getClass() == RSExportType::ExportClassRecord) ||
948            (F->getType()->getClass() == RSExportType::ExportClassConstantArray)
949            ) {
950          C.indent() << F->getName() << " = new " << GetTypeName(F->getType()) << "();" << endl;
951        }
952    }
953
954    C.endBlock();   /* end Constructor */
955
956    C.endBlock();   /* end Item class */
957
958
959    return true;
960}
961
962void RSReflection::genTypeClassConstructor(Context& C, const RSExportRecordType* ERT) {
963    const char* RenderScriptVar = "rs";
964
965    C.startFunction(Context::AM_Public, true, "Element", "createElement", 1, "RenderScript", RenderScriptVar);
966    genBuildElement(C, ERT, RenderScriptVar);
967    C.endFunction();
968
969    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 2, "RenderScript", RenderScriptVar,
970                                                                          "int", "count");
971
972    C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << endl;
973    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << endl;
974    C.indent() << "mElement = createElement(" << RenderScriptVar << ");" << endl;
975    /* Call init() in super class */
976    C.indent() << "init(" << RenderScriptVar << ", count);" << endl;
977    C.endFunction();
978
979    return;
980}
981
982void RSReflection::genTypeClassCopyToArray(Context& C, const RSExportRecordType* ERT) {
983    C.startFunction(Context::AM_Private, false, "void", "copyToArray", 2, RS_TYPE_ITEM_CLASS_NAME, "i",
984                                                                          "int", "index");
985
986    genNewItemBufferPackerIfNull(C);
987    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" << endl;
988
989    genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
990
991    C.endFunction();
992    return;
993}
994
995void RSReflection::genTypeClassItemSetter(Context& C, const RSExportRecordType* ERT) {
996    C.startFunction(Context::AM_Public, false, "void", "set", 3, RS_TYPE_ITEM_CLASS_NAME, "i",
997                                                                 "int", "index",
998                                                                 "boolean", "copyNow");
999    genNewItemBufferIfNull(C, NULL);
1000    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << endl;
1001
1002    C.indent() << "if (copyNow) ";
1003    C.startBlock();
1004
1005    C.indent() << "copyToArray(i, index);" << endl;
1006    C.indent() << "mAllocation.subData1D(index, 1, "RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
1007
1008    C.endBlock();   /* end if (copyNow) */
1009
1010    C.endFunction();
1011    return;
1012}
1013
1014void RSReflection::genTypeClassItemGetter(Context& C, const RSExportRecordType* ERT) {
1015    C.startFunction(Context::AM_Public, false, RS_TYPE_ITEM_CLASS_NAME, "get", 1, "int", "index");
1016    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;" << endl;
1017    C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index];" << endl;
1018    C.endFunction();
1019    return;
1020}
1021void RSReflection::genTypeClassComponentSetter(Context& C, const RSExportRecordType* ERT) {
1022    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
1023        FI != ERT->fields_end();
1024        FI++)
1025    {
1026        const RSExportRecordType::Field* F = *FI;
1027        size_t FieldOffset = F->getOffsetInParent();
1028        size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1029        unsigned FieldIndex = C.getFieldIndex(F);
1030
1031        C.startFunction(Context::AM_Public, false, "void", "set_" + F->getName(), 3, "int", "index",
1032                                                                                     GetTypeName(F->getType()).c_str(), "v",
1033                                                                                     "boolean", "copyNow");
1034        genNewItemBufferPackerIfNull(C);
1035        genNewItemBufferIfNull(C, "index");
1036        C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName() << " = v;" << endl;
1037
1038        C.indent() << "if (copyNow) ";
1039        C.startBlock();
1040
1041        if(FieldOffset > 0)
1042            C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof + " << FieldOffset << ");" << endl;
1043        else
1044            C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" << endl;
1045        genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1046
1047        C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");" << endl;
1048        genPackVarOfType(C, F->getType(), "v", "fp");
1049        C.indent() << "mAllocation.subElementData(index, " << 0/*FieldIndex*/ << ", fp);" << endl;
1050
1051        C.endBlock();   /* end if (copyNow) */
1052
1053        C.endFunction();
1054    }
1055    return;
1056}
1057
1058void RSReflection::genTypeClassComponentGetter(Context& C, const RSExportRecordType* ERT) {
1059    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
1060        FI != ERT->fields_end();
1061        FI++)
1062    {
1063        const RSExportRecordType::Field* F = *FI;
1064        C.startFunction(Context::AM_Public, false, GetTypeName(F->getType()).c_str(), "get_" + F->getName(), 1, "int", "index");
1065        //C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;" << endl;
1066        C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName() << ";" << endl;
1067        C.endFunction();
1068    }
1069    return;
1070}
1071
1072void RSReflection::genTypeClassCopyAll(Context& C, const RSExportRecordType* ERT) {
1073    C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
1074
1075    C.indent() << "for (int ct=0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++) copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);" << endl;
1076    C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
1077
1078    C.endFunction();
1079    return;
1080}
1081
1082/****************************** Methods to generate type class /end ******************************/
1083
1084/******************** Methods to create Element in Java of given record type ********************/
1085void RSReflection::genBuildElement(Context& C, const RSExportRecordType* ERT, const char* RenderScriptVar) {
1086    const char* ElementBuilderName = "eb";
1087
1088    /* Create element builder */
1089    //    C.startBlock(true);
1090
1091    C.indent() << "Element.Builder " << ElementBuilderName << " = new Element.Builder(" << RenderScriptVar << ");" << endl;
1092
1093    /* eb.add(...) */
1094    genAddElementToElementBuilder(C, ERT, "", ElementBuilderName, RenderScriptVar);
1095
1096    C.indent() << "return " << ElementBuilderName << ".create();" << endl;
1097
1098    //   C.endBlock();
1099    return;
1100}
1101
1102#define EB_ADD(x)  \
1103    C.indent() << ElementBuilderName << ".add(Element." << x << ", \"" << VarName << "\");" << endl; \
1104    C.incFieldIndex()
1105
1106void RSReflection::genAddElementToElementBuilder(Context& C, const RSExportType* ET, const std::string& VarName, const char* ElementBuilderName, const char* RenderScriptVar) {
1107    const char* ElementConstruct = GetBuiltinElementConstruct(ET);
1108
1109    if(ElementConstruct != NULL) {
1110      EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
1111    } else {
1112      if ((ET->getClass() == RSExportType::ExportClassPrimitive) ||
1113          (ET->getClass() == RSExportType::ExportClassVector)    ||
1114          (ET->getClass() == RSExportType::ExportClassConstantArray)
1115          ) {
1116        const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
1117        const char* DataKindName = GetElementDataKindName(EPT->getKind());
1118        const char* DataTypeName = GetElementDataTypeName(EPT->getType());
1119        int Size = (ET->getClass() == RSExportType::ExportClassVector) ? static_cast<const RSExportVectorType*>(ET)->getNumElement() : 1;
1120
1121        switch(EPT->getKind()) {
1122          case RSExportPrimitiveType::DataKindColor:
1123          case RSExportPrimitiveType::DataKindPosition:
1124          case RSExportPrimitiveType::DataKindTexture:
1125          case RSExportPrimitiveType::DataKindNormal:
1126          case RSExportPrimitiveType::DataKindPointSize:
1127            /* Element.createAttrib() */
1128            EB_ADD("createAttrib(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ", " << Size << ")");
1129            break;
1130
1131          case RSExportPrimitiveType::DataKindIndex:
1132            /* Element.createIndex() */
1133            EB_ADD("createAttrib(" << RenderScriptVar << ")");
1134            break;
1135
1136          case RSExportPrimitiveType::DataKindPixelL:
1137          case RSExportPrimitiveType::DataKindPixelA:
1138          case RSExportPrimitiveType::DataKindPixelLA:
1139          case RSExportPrimitiveType::DataKindPixelRGB:
1140          case RSExportPrimitiveType::DataKindPixelRGBA:
1141            /* Element.createPixel() */
1142            EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ")");
1143            break;
1144
1145          case RSExportPrimitiveType::DataKindUser:
1146          default:
1147            if (EPT->getClass() == RSExportType::ExportClassPrimitive || EPT->getClass() == RSExportType::ExportClassConstantArray) {
1148              /* Element.createUser() */
1149              EB_ADD("createUser(" << RenderScriptVar << ", " << DataTypeName << ")");
1150            } else {   /* (ET->getClass() == RSExportType::ExportClassVector) must hold here */
1151              /* Element.createVector() */
1152              EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << Size << ")");
1153            }
1154            break;
1155        }
1156      } else if(ET->getClass() == RSExportType::ExportClassPointer) {
1157        /* Pointer type variable should be resolved in GetBuiltinElementConstruct()  */
1158        assert(false && "??");
1159      } else if(ET->getClass() == RSExportType::ExportClassRecord) {
1160        /*
1161         * Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
1162         * TODO: Generalize these two function such that there's no duplicated codes.
1163         */
1164        const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
1165        int Pos = 0;    /* relative pos from now on */
1166
1167        for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
1168            I != ERT->fields_end();
1169            I++)
1170        {
1171          const RSExportRecordType::Field* F = *I;
1172          std::string FieldName;
1173          size_t FieldOffset = F->getOffsetInParent();
1174          size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1175          size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1176
1177          if(!VarName.empty())
1178            FieldName = VarName + "." + F->getName();
1179          else
1180            FieldName = F->getName();
1181
1182          /* alignment */
1183          genAddPaddingToElementBuiler(C, (FieldOffset - Pos), ElementBuilderName, RenderScriptVar);
1184
1185          /* eb.add(...) */
1186          C.addFieldIndexMapping(F);
1187          genAddElementToElementBuilder(C, F->getType(), FieldName, ElementBuilderName, RenderScriptVar);
1188
1189          /* There is padding within the field type */
1190          genAddPaddingToElementBuiler(C, (FieldAllocSize - FieldStoreSize), ElementBuilderName, RenderScriptVar);
1191
1192          Pos = FieldOffset + FieldAllocSize;
1193        }
1194
1195        /* There maybe some padding after the struct */
1196        //unsigned char align = RSExportType::GetTypeAlignment(ERT);
1197        //size_t siz = RSExportType::GetTypeAllocSize(ERT);
1198        size_t siz1 = RSExportType::GetTypeStoreSize(ERT);
1199
1200        genAddPaddingToElementBuiler(C, siz1 - Pos, ElementBuilderName, RenderScriptVar);
1201      } else {
1202        assert(false && "Unknown class of type");
1203      }
1204    }
1205}
1206
1207void RSReflection::genAddPaddingToElementBuiler(Context& C, size_t PaddingSize, const char* ElementBuilderName, const char* RenderScriptVar) {
1208    while(PaddingSize > 0) {
1209        const std::string& VarName = C.createPaddingField();
1210        if(PaddingSize >= 4) {
1211          EB_ADD("U32(" << RenderScriptVar << ")");
1212          PaddingSize -= 4;
1213        } else if(PaddingSize >= 2) {
1214            EB_ADD("U16(" << RenderScriptVar << ")");
1215            PaddingSize -= 2;
1216        } else if(PaddingSize >= 1) {
1217            EB_ADD("U8(" << RenderScriptVar << ")");
1218            PaddingSize -= 1;
1219        }
1220    }
1221    return;
1222}
1223
1224#undef EB_ADD
1225/******************** Methods to create Element in Java of given record type /end ********************/
1226
1227bool RSReflection::reflect(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
1228    Context *C = NULL;
1229    std::string ResourceId = "";
1230
1231    if(!GetClassNameFromFileName(OutputBCFileName, ResourceId))
1232        return false;
1233
1234    if(ResourceId.empty())
1235        ResourceId = "<Resource ID>";
1236
1237    if((OutputPackageName == NULL) || (*OutputPackageName == '\0') || strcmp(OutputPackageName, "-") == 0)
1238        C = new Context(InputFileName, "<Package Name>", ResourceId, true);
1239    else
1240        C = new Context(InputFileName, OutputPackageName, ResourceId, false);
1241
1242    if(C != NULL) {
1243        std::string ErrorMsg, ScriptClassName;
1244        /* class ScriptC_<ScriptName> */
1245        if(!GetClassNameFromFileName(InputFileName, ScriptClassName))
1246            return false;
1247
1248        if(ScriptClassName.empty())
1249            ScriptClassName = "<Input Script Name>";
1250
1251        ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
1252
1253        if (mRSContext->getLicenseNote() != NULL) {
1254          C->setLicenseNote(*(mRSContext->getLicenseNote()));
1255        }
1256
1257        if(!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
1258            std::cerr << "Failed to generate class " << ScriptClassName << " (" << ErrorMsg << ")" << endl;
1259            return false;
1260        }
1261
1262        /* class ScriptField_<TypeName> */
1263        for(RSContext::const_export_type_iterator TI = mRSContext->export_types_begin();
1264            TI != mRSContext->export_types_end();
1265            TI++)
1266        {
1267            const RSExportType* ET = TI->getValue();
1268
1269            if(ET->getClass() == RSExportType::ExportClassRecord) {
1270                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
1271
1272                if(!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
1273                    std::cerr << "Failed to generate type class for struct '" << ERT->getName() << "' (" << ErrorMsg << ")" << endl;
1274                    return false;
1275                }
1276            }
1277        }
1278    }
1279
1280    return true;
1281}
1282
1283/****************************** RSReflection::Context ******************************/
1284const char* const RSReflection::Context::ApacheLicenseNote =
1285    "/*\n"
1286	" * Copyright (C) 2010 The Android Open Source Project\n"
1287	" *\n"
1288	" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
1289	" * you may not use this file except in compliance with the License.\n"
1290	" * You may obtain a copy of the License at\n"
1291	" *\n"
1292	" *      http://www.apache.org/licenses/LICENSE-2.0\n"
1293	" *\n"
1294	" * Unless required by applicable law or agreed to in writing, software\n"
1295	" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
1296	" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
1297	" * See the License for the specific language governing permissions and\n"
1298	" * limitations under the License.\n"
1299	" */\n"
1300	"\n";
1301
1302const char* const RSReflection::Context::Import[] = {
1303    /* RenderScript java class */
1304    "android.renderscript.*",
1305    /* Import R */
1306    "android.content.res.Resources",
1307    /* Import for debugging */
1308    "android.util.Log",
1309};
1310
1311const char* RSReflection::Context::AccessModifierStr(AccessModifier AM) {
1312    switch(AM) {
1313        case AM_Public: return "public"; break;
1314        case AM_Protected: return "protected"; break;
1315        case AM_Private: return "private"; break;
1316        default: return ""; break;
1317    }
1318}
1319
1320bool RSReflection::Context::startClass(AccessModifier AM, bool IsStatic, const std::string& ClassName, const char* SuperClassName, std::string& ErrorMsg) {
1321    if(mVerbose)
1322        std::cout << "Generating " << ClassName << ".java ..." << endl;
1323
1324    /* License */
1325    out() << mLicenseNote;
1326
1327    /* Notice of generated file */
1328    out() << "/*" << endl;
1329    out() << " * This file is auto-generated. DO NOT MODIFY!" << endl;
1330    out() << " * The source RenderScript file: " << mInputRSFile << endl;
1331    out() << " */" << endl;
1332
1333    /* Package */
1334    if(!mPackageName.empty())
1335        out() << "package " << mPackageName << ";" << endl;
1336    out() << endl;
1337
1338    /* Imports */
1339    for(unsigned i=0;i<(sizeof(Import)/sizeof(const char*));i++)
1340        out() << "import " << Import[i] << ";" << endl;
1341    out() << endl;
1342
1343    /* All reflected classes should be annotated as hidden, so that they won't be exposed in SDK. */
1344    out() << "/**" << endl;
1345    out() << " * @hide" << endl;
1346    out() << " */" << endl;
1347
1348    out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " << ClassName;
1349    if(SuperClassName != NULL)
1350        out() << " extends " << SuperClassName;
1351
1352    startBlock();
1353
1354    mClassName = ClassName;
1355
1356    return true;
1357}
1358
1359void RSReflection::Context::endClass() {
1360    endBlock();
1361    if(!mUseStdout)
1362        mOF.close();
1363    clear();
1364    return;
1365}
1366
1367void RSReflection::Context::startBlock(bool ShouldIndent) {
1368    if(ShouldIndent)
1369        indent() << "{" << endl;
1370    else
1371        out() << " {" << endl;
1372    incIndentLevel();
1373    return;
1374}
1375
1376void RSReflection::Context::endBlock() {
1377    decIndentLevel();
1378    indent() << "}" << endl << endl;
1379    return;
1380}
1381
1382void RSReflection::Context::startTypeClass(const std::string& ClassName) {
1383    indent() << "public static class " << ClassName;
1384    startBlock();
1385    return;
1386}
1387
1388void RSReflection::Context::endTypeClass() {
1389    endBlock();
1390    return;
1391}
1392
1393void RSReflection::Context::startFunction(AccessModifier AM, bool IsStatic, const char* ReturnType, const std::string& FunctionName, int Argc, ...) {
1394    ArgTy Args;
1395    va_list vl;
1396    va_start(vl, Argc);
1397
1398    for(int i=0;i<Argc;i++) {
1399        const char* ArgType = va_arg(vl, const char*);
1400        const char* ArgName = va_arg(vl, const char*);
1401
1402        Args.push_back( make_pair(ArgType, ArgName) );
1403    }
1404    va_end(vl);
1405
1406    startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
1407
1408    return;
1409}
1410
1411void RSReflection::Context::startFunction(AccessModifier AM,
1412                                          bool IsStatic,
1413                                          const char* ReturnType,
1414                                          const std::string& FunctionName,
1415                                          const ArgTy& Args)
1416{
1417    indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
1418
1419    bool FirstArg = true;
1420    for(ArgTy::const_iterator I = Args.begin();
1421        I != Args.end();
1422        I++)
1423    {
1424        if(!FirstArg)
1425            out() << ", ";
1426        else
1427            FirstArg = false;
1428
1429        out() << I->first << " " << I->second;
1430    }
1431
1432    out() << ")";
1433    startBlock();
1434
1435    return;
1436}
1437
1438void RSReflection::Context::endFunction() {
1439    endBlock();
1440    return;
1441}
1442
1443}   /* namespace slang */
1444