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