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