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