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