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