Initialize slang and Android.mk.

Change-Id: If74da8e54d45511c8c9bb236bcfeec508f4f2439
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..8165269
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,69 @@
+LOCAL_PATH := $(call my-dir)
+LLVM_ROOT_PATH := external/llvm/llvm
+
+include $(LLVM_ROOT_PATH)/llvm.mk
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+include $(CLEAR_TBLGEN_VARS)
+
+LOCAL_MODULE := slang
+
+TBLGEN_TABLES :=    \
+	DiagnosticCommonKinds.inc	\
+	DiagnosticFrontendKinds.inc
+
+LOCAL_SRC_FILES :=	\
+	slang_driver.cpp	\
+	libslang.cpp	\
+	slang.cpp	\
+	slang_backend.cpp	\
+	slang_pragma_recorder.cpp	\
+	slang_diagnostic_buffer.cpp	\
+	slang_rs_context.cpp	\
+	slang_rs_pragma_handler.cpp	\
+	slang_rs_backend.cpp	\
+	slang_rs_export_type.cpp	\
+	slang_rs_export_element.cpp	\
+	slang_rs_export_var.cpp	\
+	slang_rs_export_func.cpp	\
+	slang_rs_reflection.cpp
+
+LOCAL_STATIC_LIBRARIES :=	\
+	libLLVMipo	\
+	libLLVMBitWriter	\
+	libLLVMARMAsmPrinter	\
+   	libLLVMX86AsmPrinter	\
+	libLLVMAsmPrinter	\
+	libLLVMMCParser	\
+	libLLVMARMCodeGen	\
+	libLLVMARMInfo	\
+	libLLVMX86CodeGen	\
+	libLLVMX86Info	\
+	libLLVMSelectionDAG	\
+	libLLVMCodeGen	\
+	libLLVMScalarOpts	\
+	libLLVMInstCombine	\
+	libLLVMTransformUtils	\
+	libLLVMipa	\
+	libLLVMAnalysis	\
+	libLLVMTarget	\
+	libLLVMMC	\
+	libLLVMCore	\
+	libclangIndex	\
+	libclangSema	\
+	libclangAnalysis	\
+	libclangAST	\
+	libclangParse	\
+	libclangLex	\
+	libclangCodeGen	\
+	libclangBasic	\
+	libLLVMSupport	\
+	libLLVMSystem
+
+LOCAL_LDLIBS := -ldl -lpthread
+
+include $(CLANG_HOST_BUILD_MK)
+include $(CLANG_TBLGEN_RULES_MK)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/libslang.cpp b/libslang.cpp
new file mode 100644
index 0000000..e774cae
--- /dev/null
+++ b/libslang.cpp
@@ -0,0 +1,88 @@
+#include "slang.hpp"
+
+namespace slang {
+
+/* Following are the API we provide for using slang compiler */
+extern "C" SlangCompiler* slangCreateCompiler(const char* targetTriple, const char* targetCPU, const char** targetFeatures) {
+    Slang* slang = new Slang(targetTriple, targetCPU, targetFeatures);
+    return (SlangCompiler*) slang;
+}
+
+extern "C" int slangSetSourceFromMemory(SlangCompiler* compiler, const char* text, size_t textLength) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->setInputSource("<in memory>", text, textLength);
+    else
+        return 0;
+}
+
+extern "C" int slangSetSourceFromFile(SlangCompiler* compiler, const char* fileName) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->setInputSource(fileName);
+    else
+        return 0;
+}
+
+extern "C" void slangSetOutputType(SlangCompiler* compiler, SlangCompilerOutputTy outputType) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        slang->setOutputType(outputType);
+    return;
+}
+
+extern "C" int slangSetOutputToStream(SlangCompiler* compiler, FILE* stream) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->setOutput(stream);
+    else
+        return 0;
+}
+
+extern "C" int slangSetOutputToFile(SlangCompiler* compiler, const char* fileName) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->setOutput(fileName);
+    else
+        return 0;
+}
+
+extern "C" int slangCompile(SlangCompiler* compiler) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->compile();
+    else
+        return 0;
+}
+
+extern "C" int slangReflectToJava(SlangCompiler* compiler, const char* packageName) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->reflectToJava(packageName);
+    else
+        return 0;
+}
+
+extern "C" const char* slangGetInfoLog(SlangCompiler* compiler) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        return slang->getErrorMessage();
+    else
+        return "";
+}
+
+extern "C" void slangGetPragmas(SlangCompiler* compiler, size_t* actualStringCount, size_t maxStringCount, char** strings) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        slang->getPragmas(actualStringCount, maxStringCount, strings);
+    return;
+}
+
+extern "C" void slangReset(SlangCompiler* compiler) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        slang->reset();
+    return;
+}
+
+}   /* namespace slang */
diff --git a/libslang.h b/libslang.h
new file mode 100644
index 0000000..b197167
--- /dev/null
+++ b/libslang.h
@@ -0,0 +1,47 @@
+#ifndef _ANDROID_SLANG_H_
+#   define _ANDROID_SLANG_H_
+
+#include <stdio.h>
+
+/* Hide the underlying C++ implementation of Slang */
+typedef int SlangCompiler;
+
+typedef enum {
+    SlangCompilerOutput_Assembly,
+    SlangCompilerOutput_LL,
+    SlangCompilerOutput_Bitcode,
+    SlangCompilerOutput_Nothing,
+    SlangCompilerOutput_Obj,
+
+    SlangCompilerOutput_Default = SlangCompilerOutput_Bitcode
+} SlangCompilerOutputTy;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SlangCompiler* slangCreateCompiler(const char* targetTriple, const char* targetCPU, const char** targetFeatures);
+
+int slangSetSourceFromMemory(SlangCompiler* compiler, const char* text, size_t textLength);
+int slangSetSourceFromFile(SlangCompiler* compiler, const char* fileName);
+
+void slangSetOutputType(SlangCompiler* compiler, SlangCompilerOutputTy outputType);
+
+int slangSetOutputToStream(SlangCompiler* compiler, FILE* stream);
+int slangSetOutputToFile(SlangCompiler* compiler, const char* fileName);
+
+int slangCompile(SlangCompiler* compiler);
+
+int slangReflectToJava(SlangCompiler* compiler, const char* packageName);
+
+const char* slangGetInfoLog(SlangCompiler* compiler);
+void slangGetPragmas(SlangCompiler* compiler, size_t* actualStringCount, size_t maxStringCount, char** strings);
+
+void slangReset(SlangCompiler* compiler);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif  /* _ANDROID_SLANG_H_ */
diff --git a/rs_scriptbc.h b/rs_scriptbc.h
new file mode 100644
index 0000000..ff7d4d3
--- /dev/null
+++ b/rs_scriptbc.h
@@ -0,0 +1,216 @@
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+
+typedef char char2 __attribute__((ext_vector_type(2)));
+typedef char char3 __attribute__((ext_vector_type(3)));
+typedef char char4 __attribute__((ext_vector_type(4)));
+typedef unsigned char uchar;
+typedef unsigned char uchar2 __attribute__((ext_vector_type(2)));
+typedef unsigned char uchar3 __attribute__((ext_vector_type(3)));
+typedef unsigned char uchar4 __attribute__((ext_vector_type(4)));
+typedef short short2 __attribute__((ext_vector_type(2)));
+typedef short short3 __attribute__((ext_vector_type(3)));
+typedef short short4 __attribute__((ext_vector_type(4)));
+typedef unsigned short ushort;
+typedef unsigned short ushort2 __attribute__((ext_vector_type(2)));
+typedef unsigned short ushort3 __attribute__((ext_vector_type(3)));
+typedef unsigned short ushort4 __attribute__((ext_vector_type(4)));
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef unsigned int uint;
+typedef unsigned int uint2 __attribute__((ext_vector_type(2)));
+typedef unsigned int uint3 __attribute__((ext_vector_type(3)));
+typedef unsigned int uint4 __attribute__((ext_vector_type(4)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+typedef float float3 __attribute__((ext_vector_type(3)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef short u565;
+typedef short u5551;
+typedef short u4444;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_element;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_type;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_allocation;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_sampler;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_script;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_mesh;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_program_fragment;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_program_vertex;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_program_raster;
+typedef struct { int* p; } __attribute__((packed, aligned(4))) rs_program_store;
+
+// RS_KIND_POSITION
+typedef float rs_position1;
+typedef float2 rs_position2;
+typedef float3 rs_position3;
+typedef float4 rs_position4;
+
+// RS_KIND_COLOR
+typedef float3 rs_color3f;
+typedef float4 rs_color4f;
+typedef uchar4 rs_color4u;
+
+// RS_KIND_NORMAL
+typedef float3 rs_normal;
+
+// RS_KIND_POINT_SIZE
+typedef float rs_point_size;
+
+// RS_KIND_TEXTURE
+typedef float rs_texture_coord1;
+typedef float2 rs_texture_coord2;
+typedef float3 rs_texture_coord3;
+typedef float4 rs_texture_coord4;
+
+// RS_KIND_INDEX
+typedef ushort rs_index;
+
+struct vecF32_2_s {float x; float y;};
+struct vecF32_3_s {float x; float y; float z;};
+struct vecF32_4_s {float x; float y; float z; float w;};
+struct vecU8_4_s {char r; char g; char b; char a;};
+
+typedef struct vecF32_2_s vecF32_2_t;
+typedef struct vecF32_3_s vecF32_3_t;
+typedef struct vecF32_4_s vecF32_4_t;
+typedef struct vecU8_4_s vecU8_4_t;
+typedef struct vecU8_4_s vecI8_4_t;
+
+int loadI32(int, int);
+float loadF(int, int);
+float* loadArrayF(int, int);
+int* loadArrayI32(int, int);
+void loadVec4(int, int, float *);
+void loadMatrix(int, int, float *);
+void storeI32(int, int, int);
+void storeF(int, int, float);
+void storeVec4(int, int, float *);
+void storeMatrix(int, int, float *);
+float* loadSimpleMeshVerticesF(rs_mesh, int);
+void updateSimpleMesh(rs_mesh);
+float modf(float, float);
+int abs(int);
+float absf(float);
+float sinf_fast(float);
+float cosf_fast(float);
+float sinf(float);
+float cosf(float);
+float asinf(float);
+float acosf(float);
+float atanf(float);
+float atan2f(float, float);
+float fabsf(float);
+float randf(float);
+float randf2(float, float);
+float floorf(float);
+float fracf(float);
+float ceilf(float);
+float roundf(float);
+float expf(float);
+float logf(float);
+float powf(float, float);
+float maxf(float, float);
+float minf(float, float);
+int sqrt(int);
+float sqrtf(float);
+int sqr(int);
+float sqrf(float);
+int sign(int);
+float signf(float);
+int clamp(int, int, int);
+float clampf(float, float, float);
+float distf2(float, float, float, float);
+float distf3(float, float, float, float, float, float);
+float magf2(float, float);
+float magf3(float, float, float);
+float radf(float);
+float degf(float);
+float lerpf(float, float, float);
+float normf(float, float, float);
+float mapf(float, float, float, float, float);
+float noisef(float);
+float noisef2(float, float);
+float noisef3(float, float, float);
+float turbulencef2(float, float, float);
+float turbulencef3(float, float, float, float);
+int second();
+int minute();
+int hour();
+int day();
+int month();
+int year();
+int uptimeMillis();
+int startTimeMillis();
+int elapsedTimeMillis();
+void matrixLoadIdentity(float *mat);
+void matrixLoadFloat(float *mat, float *f);
+void matrixLoadMat(float *mat, float *newmat);
+void matrixLoadRotate(float *mat, float rot, float x, float y, float z);
+void matrixLoadScale(float *mat, float x, float y, float z);
+void matrixLoadTranslate(float *mat, float x, float y, float z);
+void matrixLoadMultiply(float *mat, float *lhs, float *rhs);
+void matrixMultiply(float *mat, float *rhs);
+void matrixRotate(float *mat, float rot, float x, float y, float z);
+void matrixScale(float *mat, float x, float y, float z);
+void matrixTranslate(float *mat, float x, float y, float z);
+float2 vec2Rand(float maxLen);
+void vec3Norm(struct vecF32_3_s *);
+float vec3Length(struct vecF32_3_s *);
+void vec3Add(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs);
+void vec3Sub(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs);
+void vec3Cross(struct vecF32_3_s *dest, struct vecF32_3_s *lhs, struct vecF32_3_s *rhs);
+float vec3Dot(struct vecF32_3_s *lhs, struct vecF32_3_s *rhs);
+void vec3Scale(struct vecF32_3_s *lhs, float scale);
+void vec4Norm(struct vecF32_4_s *);
+float vec4Length(struct vecF32_4_s *);
+void vec4Add(struct vecF32_4_s *dest, struct vecF32_4_s *lhs, struct vecF32_4_s *rhs);
+void vec4Sub(struct vecF32_4_s *dest, struct vecF32_4_s *lhs, struct vecF32_4_s *rhs);
+float vec4Dot(struct vecF32_4_s *lhs, struct vecF32_4_s *rhs);
+void vec4Scale(struct vecF32_4_s *lhs, float scale);
+void bindProgramFragment(rs_program_fragment);
+void bindProgramFragmentStore(rs_program_store);
+void bindProgramStore(rs_program_store);
+void bindProgramVertex(rs_program_vertex);
+void bindSampler(rs_program_fragment, int, rs_sampler);
+void bindTexture(rs_program_fragment, int, rs_allocation);
+void vpLoadModelMatrix(void *);
+void vpLoadTextureMatrix(void *);
+void drawRect(float x1, float y1, float x2, float y2, float z);
+void drawQuad(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4);
+void drawQuadTexCoords(float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3, float x4, float y4, float z4, float u4, float v4);
+void drawSprite(float x, float y, float z, float w, float h);
+void drawSpriteScreenspace(float x, float y, float z, float w, float h);
+void drawSpriteScreenspaceCropped(float x, float y, float z, float w, float h, float cx0, float cy0, float cx1, float cy1);
+void drawLine(float x1, float y1, float z1, float x2, float y2, float z2);
+void drawPoint(float x1, float y1, float z1);
+void drawSimpleMesh(rs_mesh ism);
+void drawSimpleMeshRange(rs_mesh ism, int start, int len);
+void pfClearColor(float, float, float, float);
+void color(float, float, float, float);
+void hsb(float, float, float, float);
+void hsbToRgb(float, float, float, float*);
+int hsbToAbgr(float, float, float, float);
+void ambient(float, float, float, float);
+void diffuse(float, float, float, float);
+void specular(float, float, float, float);
+void emission(float, float, float, float);
+void shininess(float);
+void pointAttenuation(float, float, float);
+void uploadToTexture(rs_allocation, int);
+void uploadToBufferObject(rs_allocation);
+void syncToGL(int);
+int colorFloatRGBAtoUNorm8(float, float, float, float);
+int colorFloatRGBto565(float, float, float);
+int getWidth();
+int getHeight();
+int sendToClient(void *data, int cmdID, int len, int waitForSpace);
+void debugF(void *, float);
+void debugI32(void *, int);
+void debugHexF(void *, float);
+void debugHexI32(void *, int);
+void scriptCall(rs_script);
diff --git a/slang.cpp b/slang.cpp
new file mode 100644
index 0000000..6ff5556
--- /dev/null
+++ b/slang.cpp
@@ -0,0 +1,246 @@
+#include "slang.hpp"
+#include "libslang.h"
+
+#include "llvm/ADT/Twine.h"     /* for class llvm::Twine */
+
+#include "llvm/Target/TargetSelect.h"       /* for function LLVMInitialize[ARM|X86][TargetInfo|Target|AsmPrinter]() */
+
+#include "llvm/Support/MemoryBuffer.h"      /* for class llvm::MemoryBuffer */
+#include "llvm/Support/ErrorHandling.h"     /* for function llvm::install_fatal_error_handler() */
+#include "llvm/Support/ManagedStatic.h"     /* for class llvm::llvm_shutdown */
+
+#include "clang/Basic/TargetInfo.h"     /* for class clang::TargetInfo */
+#include "clang/Basic/LangOptions.h"    /* for class clang::LangOptions */
+#include "clang/Basic/TargetOptions.h"  /* for class clang::TargetOptions */
+
+#include "clang/Frontend/FrontendDiagnostic.h"      /* for clang::diag::* */
+
+#include "clang/Sema/ParseAST.h"        /* for function clang::ParseAST() */
+
+#if defined(__arm__)
+#   define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
+#elif defined(__x86_64__)
+#   define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
+#else
+#   define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"    // let's use x86 as default target
+#endif
+
+namespace slang {
+
+bool Slang::GlobalInitialized = false;
+
+/* Language option (define the language feature for compiler such as C99) */
+LangOptions Slang::LangOpts;
+
+/* Code generation option for the compiler */
+CodeGenOptions Slang::CodeGenOpts;
+
+const std::string Slang::TargetDescription = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32";
+
+/* The named of metadata node that pragma resides (should be synced with bcc.cpp) */
+const llvm::Twine Slang::PragmaMetadataName = "#pragma";
+
+void Slang::GlobalInitialization() {
+    if(!GlobalInitialized) {
+        /* We only support x86, x64 and ARM target */
+
+        /* For ARM */
+        LLVMInitializeARMTargetInfo();
+        LLVMInitializeARMTarget();
+        LLVMInitializeARMAsmPrinter();
+
+        /* For x86 and x64 */
+        LLVMInitializeX86TargetInfo();
+        LLVMInitializeX86Target();
+        LLVMInitializeX86AsmPrinter();
+
+        /* Please refer to clang/include/clang/Basic/LangOptions.h for setting up the options */
+        LangOpts.RTTI = 0;  /* turn off the RTTI information support */
+        LangOpts.NeXTRuntime = 0;   /* turn off the NeXT runtime uses */
+        LangOpts.Bool = 1;  /* turn on 'bool', 'true', 'false' keywords. */
+
+        CodeGenOpts.OptimizationLevel = 3;  /* -O3 */
+
+        GlobalInitialized = true;
+    }
+
+    return;
+}
+
+void Slang::LLVMErrorHandler(void *UserData, const std::string &Message) {
+    Diagnostic* Diags = static_cast<Diagnostic*>(UserData);
+    Diags->Report(clang::diag::err_fe_error_backend) << Message;
+    exit(1);
+}
+
+void Slang::createTarget(const char* Triple, const char* CPU, const char** Features) {
+    if(Triple != NULL)
+        mTargetOpts.Triple = Triple;
+    else
+        mTargetOpts.Triple = DEFAULT_TARGET_TRIPLE_STRING;
+
+    if(CPU != NULL)
+        mTargetOpts.CPU = CPU;
+
+    mTarget.reset(TargetInfo::CreateTargetInfo(*mDiagnostics, mTargetOpts));
+
+    if(Features != NULL)
+        for(int i=0;Features[i]!=NULL;i++)
+            mTargetOpts.Features.push_back(Features[i]);
+
+    return;
+}
+
+Slang::Slang(const char* Triple, const char* CPU, const char** Features) :
+    mOutputType(SlangCompilerOutput_Default)
+{
+    GlobalInitialization();
+
+    createDiagnostic();
+    llvm::install_fatal_error_handler(LLVMErrorHandler, mDiagnostics.get());
+
+    createTarget(Triple, CPU, Features);
+    createFileManager();
+    createSourceManager();
+
+    return;
+}
+
+bool Slang::setInputSource(llvm::StringRef inputFile, const char* text, size_t textLength) {
+    mInputFileName = inputFile.str();
+
+    /* Reset the ID tables if we are reusing the SourceManager */
+    mSourceMgr->clearIDTables();
+
+    /* Load the source */
+    llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getMemBuffer(text, text + textLength);
+    mSourceMgr->createMainFileIDForMemBuffer(SB);
+
+    if(mSourceMgr->getMainFileID().isInvalid()) {
+        mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile;
+        return false;
+    }
+
+    return true;
+}
+
+bool Slang::setInputSource(llvm::StringRef inputFile) {
+    mInputFileName = inputFile.str();
+
+    mSourceMgr->clearIDTables();
+
+    const FileEntry* File = mFileMgr->getFile(inputFile);
+    if(File)
+        mSourceMgr->createMainFileID(File, SourceLocation());
+
+    if(mSourceMgr->getMainFileID().isInvalid()) {
+        mDiagnostics->Report(clang::diag::err_fe_error_reading) << inputFile;
+        return false;
+    }
+
+    return true;
+}
+
+void Slang::setOutputType(SlangCompilerOutputTy outputType) {
+    mOutputType = outputType;
+    if( mOutputType != SlangCompilerOutput_Assembly &&
+        mOutputType != SlangCompilerOutput_LL &&
+        mOutputType != SlangCompilerOutput_Bitcode &&
+        mOutputType != SlangCompilerOutput_Nothing &&
+        mOutputType != SlangCompilerOutput_Obj)
+        mOutputType = SlangCompilerOutput_Default;
+    return;
+}
+
+bool Slang::setOutput(const char* outputFile) {
+    std::string Error;
+
+    switch(mOutputType) {
+        case SlangCompilerOutput_Assembly:
+        case SlangCompilerOutput_LL:
+            mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, 0) );
+        break;
+
+        case SlangCompilerOutput_Nothing:
+            mOS.reset();
+        break;
+
+        case SlangCompilerOutput_Obj:
+        case SlangCompilerOutput_Bitcode:
+        default:
+            mOS.reset( new llvm::raw_fd_ostream(outputFile, Error, llvm::raw_fd_ostream::F_Binary) );
+        break;
+    }
+
+    if(!Error.empty()) {
+        mOS.reset();
+        mDiagnostics->Report(clang::diag::err_fe_error_opening) << outputFile << Error;
+        return false;
+    }
+
+    mOutputFileName = outputFile;
+
+    return true;
+}
+
+int Slang::compile() {
+    if((mDiagnostics->getNumErrors() > 0) || (mOS.get() == NULL))
+        return mDiagnostics->getNumErrors();
+
+    /* Here is per-compilation needed initialization */
+    createPreprocessor();
+    createRSContext();
+    createASTContext();
+    //createBackend();
+    createRSBackend();
+
+    /* Inform the diagnostic client we are processing a source file */
+    mDiagClient->BeginSourceFile(LangOpts, mPP.get());
+
+    /* The core of the slang compiler */
+    ParseAST(*mPP, mBackend.get(), *mASTContext);
+
+    /* The compilation ended, clear up */
+    mBackend.reset();
+    mASTContext.reset();
+    mPP.reset();
+
+    /* Inform the diagnostic client we are done with previous source file */
+    mDiagClient->EndSourceFile();
+
+    return mDiagnostics->getNumErrors();
+}
+
+bool Slang::reflectToJava(const char* outputPackageName) {
+    if(mRSContext.get())
+        return mRSContext->reflectToJava(outputPackageName, mInputFileName, mOutputFileName);
+    else
+        return false;
+}
+
+void Slang::getPragmas(size_t* actualStringCount, size_t maxStringCount, char** strings) {
+    int stringCount = mPragmas.size() * 2;
+
+    if(actualStringCount)
+        *actualStringCount = stringCount;
+    if(stringCount > maxStringCount)
+        stringCount = maxStringCount;
+    if(strings)
+        for(PragmaList::const_iterator it = mPragmas.begin();
+            stringCount > 0;
+            stringCount-=2, it++)
+        {
+            *strings++ = const_cast<char*>(it->first.c_str());
+            *strings++ = const_cast<char*>(it->second.c_str());
+        }
+
+    return;
+}
+
+Slang::~Slang() {
+    llvm::llvm_shutdown();
+    return;
+}
+
+}   /* namespace slang */
+
diff --git a/slang.hpp b/slang.hpp
new file mode 100644
index 0000000..8be32a6
--- /dev/null
+++ b/slang.hpp
@@ -0,0 +1,202 @@
+#ifndef _SLANG_COMPILER_SLANG_HPP
+#   define _SLANG_COMPILER_SLANG_HPP
+
+#include "slang_backend.hpp"
+#include "slang_rs_context.hpp"
+#include "slang_rs_backend.hpp"
+#include "slang_pragma_recorder.hpp"
+#include "slang_diagnostic_buffer.hpp"
+
+#include <cstdio>
+#include <string>
+
+#include "llvm/Support/raw_ostream.h"   /* for class llvm::raw_ostream */
+
+#include "llvm/ADT/OwningPtr.h"         /* for class llvm::OwningPtr */
+#include "llvm/ADT/StringRef.h"         /* for class llvm::StringRef */
+
+#include "clang/AST/ASTConsumer.h"      /* for class clang::ASTConsumer */
+#include "clang/AST/ASTContext.h"       /* for class clang::ASTContext */
+
+#include "clang/Lex/Preprocessor.h"     /* for class clang::Preprocessor */
+#include "clang/Lex/HeaderSearch.h"     /* for class clang::HeaderSearch */
+
+#include "clang/Basic/Diagnostic.h"     /* for class clang::Diagnostic, class clang::DiagnosticClient, class clang::DiagnosticInfo  */
+#include "clang/Basic/FileManager.h"    /* for class clang::FileManager and class clang::FileEntry */
+#include "clang/Basic/TargetOptions.h"  /* for class clang::TargetOptions */
+
+namespace llvm {
+
+class Twine;
+class TargetInfo;
+
+}   /* namespace llvm */
+
+namespace clang {
+
+class LangOptions;
+class CodeGenOptions;
+
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+class Slang {
+    static LangOptions LangOpts;
+    static CodeGenOptions CodeGenOpts;
+
+    static bool GlobalInitialized;
+
+    static void GlobalInitialization();
+
+    static void LLVMErrorHandler(void *UserData, const std::string &Message);
+
+private:
+    PragmaList mPragmas;
+
+    /* The diagnostics engine instance (for status reporting during compilation) */
+    llvm::OwningPtr<Diagnostic> mDiagnostics;
+
+    llvm::OwningPtr<DiagnosticBuffer> mDiagClient;
+    inline void createDiagnostic() {
+        mDiagClient.reset(new DiagnosticBuffer());
+        mDiagnostics.reset(new Diagnostic(mDiagClient.get()));
+        return;
+    }
+
+    /* The target being compiled for */
+    TargetOptions mTargetOpts;
+    llvm::OwningPtr<TargetInfo> mTarget;
+    void createTarget(const char* Triple, const char* CPU, const char** Features);
+
+    /**** Below is for parsing ****/
+
+    /* The file manager (for prepocessor doing the job such as header file search) */
+    llvm::OwningPtr<FileManager> mFileMgr;
+    inline void createFileManager() { mFileMgr.reset(new FileManager()); return; }
+
+    /* The source manager (responsible for the source code handling) */
+    llvm::OwningPtr<SourceManager> mSourceMgr;  /* The source manager */
+    inline void createSourceManager() { mSourceMgr.reset(new SourceManager(*mDiagnostics)); return; }
+
+    /* The preprocessor (source code preprocessor) */
+    llvm::OwningPtr<Preprocessor> mPP;
+    inline void createPreprocessor() {
+        HeaderSearch* HeaderInfo = new HeaderSearch(*mFileMgr); /* Default only search header file in current dir */
+        mPP.reset(new Preprocessor( *mDiagnostics,
+                                    LangOpts,
+                                    *mTarget,
+                                    *mSourceMgr,
+                                    *HeaderInfo,
+                                    NULL,
+                                    true /* OwnsHeaderSearch */));
+        /* Initialize the prepocessor */
+        mPragmas.clear();
+        mPP->AddPragmaHandler(NULL, new PragmaRecorder(mPragmas));
+        /* ApplyHeaderSearchOptions */
+        return;
+    }
+
+    /* Context of Slang compiler for RenderScript */
+    llvm::OwningPtr<RSContext> mRSContext;
+    inline void createRSContext() {
+        mRSContext.reset(new RSContext(mPP.get(),
+                                       mTarget.get()));
+        return;
+    }
+
+    /* The AST context (the context to hold long-lived AST nodes) */
+    llvm::OwningPtr<ASTContext> mASTContext;
+    inline void createASTContext() {
+        mASTContext.reset(new ASTContext(LangOpts,
+                                         *mSourceMgr,
+                                         *mTarget,
+                                         mPP->getIdentifierTable(),
+                                         mPP->getSelectorTable(),
+                                         mPP->getBuiltinInfo()));
+        return;
+    }
+
+    /* The AST consumer, responsible for code generation */
+    llvm::OwningPtr<Backend> mBackend;
+    inline void createBackend() {
+        mBackend.reset(new Backend(*mDiagnostics,
+                                   CodeGenOpts,
+                                   mTargetOpts,
+                                   mPragmas,
+                                   mOS.take(),
+                                   mOutputType));
+
+        return;
+    }
+
+    inline void createRSBackend() {
+        mBackend.reset(new RSBackend(mRSContext.get(),
+                                     *mDiagnostics,
+                                     CodeGenOpts,
+                                     mTargetOpts,
+                                     mPragmas,
+                                     mOS.take(),
+                                     mOutputType));
+
+        return;
+    }
+
+    /* Input file name */
+    std::string mInputFileName;
+    std::string mOutputFileName;
+
+    SlangCompilerOutputTy mOutputType;
+
+    /* Output stream */
+    llvm::OwningPtr<llvm::raw_ostream> mOS;
+
+public:
+    static const std::string TargetDescription;
+
+    static const llvm::Twine PragmaMetadataName;
+
+    Slang(const char* Triple, const char* CPU, const char** Features);
+
+    bool setInputSource(llvm::StringRef inputFile, const char* text, size_t textLength);
+
+    bool setInputSource(llvm::StringRef inputFile);
+
+    void setOutputType(SlangCompilerOutputTy outputType);
+
+    inline bool setOutput(FILE* stream) {
+        if(stream == NULL)
+            return false;
+
+        mOS.reset( new llvm::raw_fd_ostream(fileno(stream), /* shouldClose */false) );
+        return true;
+    }
+
+    bool setOutput(const char* outputFile);
+
+    int compile();
+
+    bool reflectToJava(const char* outputPackageName);
+
+    inline const char* getErrorMessage() {
+        return mDiagClient->str().c_str();
+    }
+
+    void getPragmas(size_t* actualStringCount, size_t maxStringCount, char** strings);
+
+    /* Reset the slang compiler state such that it can be reused to compile another file */
+    inline void reset() {
+        /* Seems there's no way to clear the diagnostics. We just re-create it. */
+        createDiagnostic();
+        mOutputType = SlangCompilerOutput_Default;
+        return;
+    }
+
+    ~Slang();
+};  /* class Slang */
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_SLANG_HPP */
diff --git a/slang_backend.cpp b/slang_backend.cpp
new file mode 100644
index 0000000..f1e5cd4
--- /dev/null
+++ b/slang_backend.cpp
@@ -0,0 +1,363 @@
+#include "slang.hpp"
+#include "slang_backend.hpp"
+
+#include "llvm/Module.h"                /* for class llvm::Module */
+#include "llvm/Metadata.h"              /* for class llvm::NamedMDNode */
+#include "llvm/LLVMContext.h"           /* for llvm::getGlobalContext() */
+
+#include "llvm/Target/TargetMachine.h"  /* for class llvm::TargetMachine and llvm::TargetMachine::AssemblyFile */
+#include "llvm/Target/TargetOptions.h"  /* for
+                                         *  variable bool llvm::UseSoftFloat
+                                         *  FloatABI::ABIType llvm::FloatABIType
+                                         *  bool llvm::NoZerosInBSS
+                                         */
+#include "llvm/Target/TargetRegistry.h"     /* for class llvm::TargetRegistry */
+#include "llvm/Target/SubtargetFeature.h"   /* for class llvm::SubtargetFeature */
+
+#include "llvm/CodeGen/RegAllocRegistry.h"      /* for class llvm::RegisterRegAlloc */
+#include "llvm/CodeGen/SchedulerRegistry.h"     /* for class llvm::RegisterScheduler and llvm::createDefaultScheduler() */
+
+#include "llvm/Assembly/PrintModulePass.h"      /* for function createPrintModulePass() */
+#include "llvm/Bitcode/ReaderWriter.h"          /* for function createBitcodeWriterPass() */
+
+#include "clang/AST/Decl.h"             /* for class clang::*Decl */
+#include "clang/AST/Stmt.h"             /* for class clang::*Stmt */
+#include "clang/AST/StmtVisitor.h"      /* for class clang::StmtVisitor */
+#include "clang/AST/Expr.h"             /* for class clang::*Expr */
+#include "clang/AST/DeclGroup.h"        /* for class clang::DeclGroupRef */
+#include "clang/AST/ASTContext.h"       /* for class clang::ASTContext */
+
+#include "clang/Basic/TargetInfo.h"     /* for class clang::TargetInfo */
+#include "clang/Basic/Diagnostic.h"     /* for class clang::Diagnostic */
+#include "clang/Basic/TargetOptions.h"  /* for class clang::TargetOptions */
+
+#include "clang/Frontend/FrontendDiagnostic.h"      /* for clang::diag::* */
+
+#include "clang/CodeGen/ModuleBuilder.h"    /* for class clang::CodeGenerator */
+#include "clang/CodeGen/CodeGenOptions.h"   /* for class clang::CodeGenOptions */
+
+namespace {
+    using namespace clang;
+
+    class CheckFunctionCallVisitor : public StmtVisitor<CheckFunctionCallVisitor> {
+    private:
+        Diagnostic& mDiags;
+        SourceManager& mSourceMgr;
+
+    public:
+        CheckFunctionCallVisitor(Diagnostic& Diags, SourceManager& SourceMgr) : 
+            mDiags(Diags), 
+            mSourceMgr(SourceMgr) 
+        {
+            return;
+        }
+
+        void VisitStmt(Stmt* S);
+        void VisitCallExpr(CallExpr* Node);
+    };
+
+    void CheckFunctionCallVisitor::VisitStmt(Stmt* S) {
+        for(Stmt::child_iterator I = S->child_begin();
+            I != S->child_end();
+            I++)
+            if(*I)
+                Visit(*I);
+        return;
+    }
+
+    void CheckFunctionCallVisitor::VisitCallExpr(CallExpr* Node) {
+        if(Node != NULL) {
+            const FunctionDecl* Callee = Node->getDirectCallee();
+            if(Callee != NULL) {
+                if(!Callee->getBody() && !Callee->hasPrototype()) {
+                    /* Warn: Function has neither definition nore prototype */
+                    mDiags.Report(FullSourceLoc(Node->getLocStart(), mSourceMgr), 
+                                  mDiags.getCustomDiagID(Diagnostic::Warning, "no previous prototype for function '%0'")) << Callee->getName();
+                }
+            }
+        }
+        return;
+    }
+}
+
+namespace slang {
+
+bool Backend::CreateCodeGenPasses() {
+    if(mOutputType != SlangCompilerOutput_Assembly && mOutputType != SlangCompilerOutput_Obj)
+        return true;
+
+    /* Now we add passes for code emitting */
+    if(mCodeGenPasses) {
+        return true;
+    } else {
+        mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
+        mCodeGenPasses->add(new llvm::TargetData(*mpTargetData));
+    }
+
+    /* Create the TargetMachine for generating code. */
+    std::string Triple = mpModule->getTargetTriple();
+
+    std::string Error;
+    const llvm::Target* TargetInfo = llvm::TargetRegistry::lookupTarget(Triple, Error);
+    if(TargetInfo == NULL) {
+        mDiags.Report(clang::diag::err_fe_unable_to_create_target) << Error;
+        return false;
+    }
+
+    llvm::NoFramePointerElim = mCodeGenOpts.DisableFPElim;
+
+    /*
+     * Use hardware FPU.
+     *
+     * FIXME: Need to detect the CPU capability and decide whether to use softfp. To use softfp, change following 2 lines to
+     *
+     *  llvm::FloatABIType = llvm::FloatABI::Soft;
+     *  llvm::UseSoftFloat = true;
+     */
+    llvm::FloatABIType = llvm::FloatABI::Hard;
+    llvm::UseSoftFloat = false;
+
+    llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);   /* ACC needs all unknown symbols resolved at compilation time.
+                                                                        So we don't need any relocation model. */
+
+    /* The target with pointer size greater than 32 (e.g. x86_64 architecture) may need large data address model */
+    if(mpTargetData->getPointerSizeInBits() > 32)
+        llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
+    else
+        llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);  /* This is set for the linker (specify how large of the virtual addresses
+                                                                        we can access for all unknown symbols.) */
+
+    /* setup feature string */
+    std::string FeaturesStr;
+    if(mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
+        llvm::SubtargetFeatures Features;
+
+        Features.setCPU(mTargetOpts.CPU);
+
+        for(std::vector<std::string>::const_iterator it = mTargetOpts.Features.begin();
+            it != mTargetOpts.Features.end();
+            it++)
+            Features.AddFeature(*it);
+
+        FeaturesStr = Features.getString();
+    }
+    llvm::TargetMachine *TM = TargetInfo->createTargetMachine(Triple, FeaturesStr);
+
+    /* Register scheduler */
+    llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
+
+    /* Register allocation policy:
+     *  createLocalRegisterAllocator: fast but bad quality
+     *  createLinearScanRegisterAllocator: not so fast but good quality
+     */
+    llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ? llvm::createLocalRegisterAllocator : llvm::createLinearScanRegisterAllocator);
+
+    llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
+    if(mCodeGenOpts.OptimizationLevel == 0)
+        OptLevel = llvm::CodeGenOpt::None;
+    else if(mCodeGenOpts.OptimizationLevel == 3)
+        OptLevel = llvm::CodeGenOpt::Aggressive;
+
+    llvm::TargetMachine::CodeGenFileType CGFT = llvm::TargetMachine::CGFT_AssemblyFile;;
+    if(mOutputType == SlangCompilerOutput_Obj)
+        CGFT = llvm::TargetMachine::CGFT_ObjectFile;
+    if(TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream, CGFT, OptLevel)) {
+        mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target);
+        return false;
+    }
+
+    return true;
+}
+
+Backend::Backend(Diagnostic &Diags,
+                 const CodeGenOptions& CodeGenOpts,
+                 const TargetOptions& TargetOpts,
+                 const PragmaList& Pragmas,
+                 llvm::raw_ostream* OS,
+                 SlangCompilerOutputTy OutputType) :
+    ASTConsumer(),
+    mLLVMContext(llvm::getGlobalContext()),
+    mDiags(Diags),
+    mCodeGenOpts(CodeGenOpts),
+    mTargetOpts(TargetOpts),
+    mPragmas(Pragmas),
+    mpOS(OS),
+    mOutputType(OutputType),
+    mpModule(NULL),
+    mpTargetData(NULL),
+    mGen(NULL),
+    mPerFunctionPasses(NULL),
+    mPerModulePasses(NULL),
+    mCodeGenPasses(NULL)
+{
+    FormattedOutStream.setStream(*mpOS, llvm::formatted_raw_ostream::PRESERVE_STREAM);
+    mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
+    return;
+}
+
+void Backend::Initialize(ASTContext &Ctx) {
+    mGen->Initialize(Ctx);
+
+    mpModule = mGen->GetModule();
+    mpTargetData = new llvm::TargetData(Slang::TargetDescription);
+
+    return;
+}
+
+void Backend::HandleTopLevelDecl(DeclGroupRef D) {
+    mGen->HandleTopLevelDecl(D);
+    return;
+}
+
+void Backend::HandleTranslationUnit(ASTContext& Ctx) {
+    /* Warn if there's any function without prototype declaration or function definition called */
+    TranslationUnitDecl* TUDecl = Ctx.getTranslationUnitDecl();
+    for(DeclContext::decl_iterator DI = TUDecl->decls_begin();
+        DI != TUDecl->decls_end();
+        DI++)
+    {
+        if(DI->getKind() == Decl::Function) {
+            FunctionDecl* FD = static_cast<FunctionDecl*>(*DI);
+            Stmt* Body = FD->getBody();
+            if(Body != NULL) {
+                CheckFunctionCallVisitor FunctionCallChecker(mDiags, Ctx.getSourceManager());
+                FunctionCallChecker.Visit(Body);
+            }
+        }
+    }
+
+    mGen->HandleTranslationUnit(Ctx);
+
+    /*
+     * Here, we complete a translation unit (whole translation unit is now in LLVM IR).
+     *  Now, interact with LLVM backend to generate actual machine code (asm or machine
+     *  code, whatever.)
+     */
+
+    if(!mpModule || !mpTargetData)  /* Silently ignore if we weren't initialized for some reason. */
+        return;
+
+    llvm::Module* M = mGen->ReleaseModule();
+    if(!M) {
+        /* The module has been released by IR gen on failures, do not double free. */
+        mpModule = NULL;
+        return;
+    }
+
+    assert(mpModule == M && "Unexpected module change during LLVM IR generation");
+
+    /* Insert #pragma information into metadata section of module */
+    if(!mPragmas.empty()) {
+        llvm::NamedMDNode* PragmaMetadata = llvm::NamedMDNode::Create(mLLVMContext, Slang::PragmaMetadataName, NULL, 0, mpModule);
+        for(PragmaList::const_iterator it = mPragmas.begin();
+            it != mPragmas.end();
+            it++)
+        {
+            llvm::SmallVector<llvm::Value*, 2> Pragma;
+            /* Name goes first */
+            Pragma.push_back(llvm::MDString::get(mLLVMContext, it->first));
+            /* And then value */
+            Pragma.push_back(llvm::MDString::get(mLLVMContext, it->second));
+            /* Create MDNode and insert into PragmaMetadata */
+            PragmaMetadata->addOperand( llvm::MDNode::get(mLLVMContext, Pragma.data(), Pragma.size()) );
+        }
+    }
+
+    HandleTranslationUnitEx(Ctx);
+
+    /* Create passes for optimization and code emission */
+
+    /* Create and run per-function passes */
+    CreateFunctionPasses();
+    if(mPerFunctionPasses) {
+        mPerFunctionPasses->doInitialization();
+
+        for(llvm::Module::iterator I = mpModule->begin();
+            I != mpModule->end();
+            I++)
+            if(!I->isDeclaration())
+                mPerFunctionPasses->run(*I);
+
+        mPerFunctionPasses->doFinalization();
+    }
+
+
+    /* Create and run module passes */
+    CreateModulePasses();
+    if(mPerModulePasses)
+        mPerModulePasses->run(*mpModule);
+
+    switch(mOutputType) {
+        case SlangCompilerOutput_Assembly:
+        case SlangCompilerOutput_Obj:
+            if(!CreateCodeGenPasses())
+                return;
+
+            mCodeGenPasses->doInitialization();
+
+            for(llvm::Module::iterator I = mpModule->begin();
+                I != mpModule->end();
+                I++)
+                if(!I->isDeclaration())
+                    mCodeGenPasses->run(*I);
+
+            mCodeGenPasses->doFinalization();
+        break;
+
+        case SlangCompilerOutput_LL:
+        {
+            llvm::PassManager* LLEmitPM = new llvm::PassManager();
+            LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
+            LLEmitPM->run(*mpModule);
+        }
+        break;
+
+        case SlangCompilerOutput_Bitcode:
+        {
+            llvm::PassManager* BCEmitPM = new llvm::PassManager();
+            BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
+            BCEmitPM->run(*mpModule);
+        }
+        break;
+
+        case SlangCompilerOutput_Nothing:
+            return;
+        break;
+
+        default:
+            assert(false && "Unknown output type");
+        break;
+    }
+
+    FormattedOutStream.flush();
+
+    return;
+}
+
+void Backend::HandleTagDeclDefinition(TagDecl* D) {
+    mGen->HandleTagDeclDefinition(D);
+    return;
+}
+
+void Backend::CompleteTentativeDefinition(VarDecl* D) {
+    mGen->CompleteTentativeDefinition(D);
+    return;
+}
+
+Backend::~Backend() {
+    if(mpModule)
+        delete mpModule;
+    if(mpTargetData)
+        delete mpTargetData;
+    if(mGen)
+        delete mGen;
+    if(mPerFunctionPasses)
+        delete mPerFunctionPasses;
+    if(mPerModulePasses)
+        delete mPerModulePasses;
+    if(mCodeGenPasses)
+        delete mCodeGenPasses;
+    return;
+}
+
+}   /* namespace slang */
diff --git a/slang_backend.hpp b/slang_backend.hpp
new file mode 100644
index 0000000..9546b20
--- /dev/null
+++ b/slang_backend.hpp
@@ -0,0 +1,162 @@
+#ifndef _SLANG_COMPILER_BACKEND_HPP
+#   define _SLANG_COMPILER_BACKEND_HPP
+
+#include "libslang.h"
+#include "slang_pragma_recorder.hpp"
+
+#include "llvm/PassManager.h"               /* for class llvm::PassManager and llvm::FunctionPassManager */
+
+#include "llvm/Target/TargetData.h"         /* for class llvm::TargetData */
+
+#include "llvm/Support/StandardPasses.h"    /* for function llvm::createStandardFunctionPasses() and llvm::createStandardModulePasses() */
+#include "llvm/Support/FormattedStream.h"   /* for class llvm::formatted_raw_ostream */
+
+#include "clang/AST/ASTConsumer.h"          /* for class clang::ASTConsumer */
+#include "clang/CodeGen/CodeGenOptions.h"   /* for class clang::CodeGenOptions */
+
+namespace llvm {
+
+class LLVMContext;
+class NamedMDNode;
+class raw_ostream;
+class Module;
+
+}   /* namespace llvm */
+
+namespace clang {
+
+class ASTConsumer;
+class Diagnostic;
+class TargetOptions;
+class PragmaList;
+class CodeGenerator;
+class ASTContext;
+class DeclGroupRef;
+class TagDecl;
+class VarDecl;
+
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+class Backend : public ASTConsumer {
+private:
+    const CodeGenOptions& mCodeGenOpts;
+    const TargetOptions& mTargetOpts;
+
+    /* Output stream */
+    llvm::raw_ostream* mpOS;
+    SlangCompilerOutputTy mOutputType;
+
+    llvm::TargetData* mpTargetData;
+
+    /* The @Gen here help us to translate AST using in Clang to LLVM IR */
+    CodeGenerator* mGen;
+
+    /* Passes */
+    llvm::FunctionPassManager* mPerFunctionPasses;  /* passes apply on function scope in a translation unit */
+    llvm::PassManager* mPerModulePasses;            /* passes apply on module scope */
+    llvm::FunctionPassManager* mCodeGenPasses;      /* passes for code emission */
+
+    llvm::formatted_raw_ostream FormattedOutStream;
+
+    inline void CreateFunctionPasses() {
+        if(!mPerFunctionPasses) {
+            mPerFunctionPasses = new llvm::FunctionPassManager(mpModule);
+            mPerFunctionPasses->add(new llvm::TargetData(*mpTargetData));
+
+            llvm::createStandardFunctionPasses(mPerFunctionPasses, mCodeGenOpts.OptimizationLevel);
+        }
+        return;
+    }
+
+    inline void CreateModulePasses() {
+        if(!mPerModulePasses) {
+            /* inline passes */
+            mPerModulePasses = new llvm::PassManager();
+            mPerModulePasses->add(new llvm::TargetData(*mpTargetData));
+
+            llvm::createStandardModulePasses(mPerModulePasses,
+                                             mCodeGenOpts.OptimizationLevel,
+                                             mCodeGenOpts.OptimizeSize,
+                                             mCodeGenOpts.UnitAtATime,
+                                             mCodeGenOpts.UnrollLoops,
+                                             /* SimplifyLibCalls */true,    /* Some libc functions will be replaced
+                                                                             *  by the LLVM built-in optimized function (e.g. strcmp)
+                                                                             */
+                                             /* HaveExceptions */false,
+                                             /* InliningPass */NULL);
+        }
+
+        /*
+         * llvm::createStandardFunctionPasses and llvm::createStandardModulePasses insert lots of optimization passes for
+         *  the code generator. For the conventional desktop PC which memory resources and computation power is relative
+         *  large, doing lots optimization as possible is reasonible and feasible. However, on the mobile device or embedded
+         *  system, this may cause some problem due to the hardware resources limitation. So they need further refine.
+         */
+        return;
+    }
+
+    bool CreateCodeGenPasses();
+
+protected:
+    llvm::Module* mpModule;
+
+    llvm::LLVMContext& mLLVMContext;
+    const PragmaList& mPragmas;
+    Diagnostic &mDiags;
+
+    /* Extra handler for subclass to handle translation unit before emission */
+    virtual void HandleTranslationUnitEx(ASTContext& Ctx) { return; }
+
+public:
+    Backend(Diagnostic &Diags,
+            const CodeGenOptions& CodeGenOpts,
+            const TargetOptions& TargetOpts,
+            const PragmaList& Pragmas,
+            llvm::raw_ostream* OS,
+            SlangCompilerOutputTy OutputType);
+
+    /*
+     * Initialize - This is called to initialize the consumer, providing the
+     *  ASTContext.
+     */
+    virtual void Initialize(ASTContext &Ctx);
+
+    /*
+     * HandleTopLevelDecl - Handle the specified top-level declaration.  This is
+     *  called by the parser to process every top-level Decl*. Note that D can be
+     *  the head of a chain of Decls (e.g. for `int a, b` the chain will have two
+     *  elements). Use Decl::getNextDeclarator() to walk the chain.
+     */
+    virtual void HandleTopLevelDecl(DeclGroupRef D);
+
+    /*
+     * HandleTranslationUnit - This method is called when the ASTs for entire
+     *  translation unit have been parsed.
+     */
+    virtual void HandleTranslationUnit(ASTContext& Ctx);
+
+    /*
+     * HandleTagDeclDefinition - This callback is invoked each time a TagDecl
+     *  (e.g. struct, union, enum, class) is completed.  This allows the client to
+     *  hack on the type, which can occur at any point in the file (because these
+     *  can be defined in declspecs).
+     */
+    virtual void HandleTagDeclDefinition(TagDecl* D);
+
+    /*
+     * CompleteTentativeDefinition - Callback invoked at the end of a translation
+     *  unit to notify the consumer that the given tentative definition should be
+     *  completed.
+     */
+    virtual void CompleteTentativeDefinition(VarDecl* D);
+
+    virtual ~Backend();
+};
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_BACKEND_HPP */
diff --git a/slang_diagnostic_buffer.cpp b/slang_diagnostic_buffer.cpp
new file mode 100644
index 0000000..89117e7
--- /dev/null
+++ b/slang_diagnostic_buffer.cpp
@@ -0,0 +1,60 @@
+#include "slang_diagnostic_buffer.hpp"
+
+#include "llvm/ADT/SmallString.h"   /* for llvm::SmallString */
+
+#include "clang/Basic/SourceManager.h"  /* for class clang::SourceManager */
+#include "clang/Basic/SourceLocation.h" /* for class clang::SourceLocation, class clang::FullSourceLoc and class clang::PresumedLoc */
+
+namespace slang {
+
+DiagnosticBuffer::DiagnosticBuffer() : mSOS(NULL) {
+    mSOS = new llvm::raw_string_ostream(mDiags);
+    return;
+}
+
+void DiagnosticBuffer::HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info) {
+    const FullSourceLoc& FSLoc = Info.getLocation();
+    llvm::SmallString<100> Buf; /* 100 is enough for storing general diagnosis message */
+
+    if(FSLoc.isValid()) {
+        /* This is a diagnosis for a source code */
+        PresumedLoc PLoc = FSLoc.getManager().getPresumedLoc(FSLoc);
+        (*mSOS) << FSLoc.getManager().getBufferName(FSLoc) << ':' << PLoc.getLine() << ':' << PLoc.getColumn() << ": ";
+    }
+
+    switch(DiagLevel) {
+        case Diagnostic::Note:
+            (*mSOS) << "note: ";
+        break;
+
+        case Diagnostic::Warning:
+            (*mSOS) << "warning: ";
+        break;
+
+        case Diagnostic::Error:
+            (*mSOS) << "error: ";
+        break;
+
+        case Diagnostic::Fatal:
+            (*mSOS) << "fatal: ";
+        break;
+
+        default:
+            assert(0 && "Diagnostic not handled during diagnostic buffering!");
+        break;
+    }
+
+
+    Info.FormatDiagnostic(Buf);
+    (*mSOS) << Buf.str() << '\n';
+
+    return;
+}
+
+DiagnosticBuffer::~DiagnosticBuffer() {
+    if(mSOS != NULL)
+        delete mSOS;
+    return;
+}
+
+}   /* namespace slang */
diff --git a/slang_diagnostic_buffer.hpp b/slang_diagnostic_buffer.hpp
new file mode 100644
index 0000000..832c631
--- /dev/null
+++ b/slang_diagnostic_buffer.hpp
@@ -0,0 +1,41 @@
+#ifndef _SLANG_DIAGNOSTIC_BUFFER_HPP
+#   define _SLANG_DIAGNOSTIC_BUFFER_HPP
+
+#include <string>
+
+#include "llvm/Support/raw_ostream.h"       /* for class llvm::raw_ostream and llvm::raw_string_ostream */
+
+#include "clang/Basic/Diagnostic.h"     /* for class clang::Diagnostic, class clang::DiagnosticClient, class clang::DiagnosticInfo  */
+
+namespace llvm {
+
+class raw_string_ostream;
+
+}   /* namespace llvm */
+
+namespace slang {
+
+using namespace clang;
+
+/* The diagnostics client instance (for reading the processed diagnostics) */
+class DiagnosticBuffer : public DiagnosticClient {
+private:
+    std::string mDiags;
+    llvm::raw_string_ostream* mSOS;
+
+public:
+    DiagnosticBuffer();
+
+    virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo& Info);
+
+    inline const std::string& str() const { mSOS->flush(); return mDiags; }
+
+    inline void reset() { this->mSOS->str().clear(); return; }
+
+    virtual ~DiagnosticBuffer();
+};  /* class DiagnosticBuffer */
+
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_DIAGNOSTIC_BUFFER_HPP */
diff --git a/slang_driver.cpp b/slang_driver.cpp
new file mode 100644
index 0000000..0ba4b60
--- /dev/null
+++ b/slang_driver.cpp
@@ -0,0 +1,543 @@
+#include "libslang.h"
+
+#include <assert.h>
+#include <getopt.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+
+using namespace std;
+
+#define ERR_NO_INPUT_FILE           "no input file"
+
+#define WARN(x) cerr << "warning: " WARN_ ## x << endl
+#define WARN1(x, v1) cerr << "warning: " WARN_ ## x(v1) << endl
+#define WARN2(x, v1, v2) cerr << "warning: " WARN_ ## x(v1, v2) << endl
+
+#define WARN_MULTIPLE_INPUT_FILES   "multiple input files is not supported currently, only first input file will be compiled"
+
+#define WARN_UNKNOWN_CPU(v1)            "the given CPU " << (v1) << " cannot be recognized, but we'll force passing it to Slang compiler"
+
+#define WARN_MISMATCH_CPU_TARGET_ARCH(v1, v2)   \
+    "CPU (target: " << (v1) << ") you selected doesn't match the target of enable features you specified or the triple string you given (" << (v2) << ")"
+#define WARN_MISMATCH_FEATURE_TARGET_ARCH(v1, v2)   \
+    "Feature (target: " << (v1) << ") you selected doesn't match the target of CPU you specified or the triple string you given (" << (v2) << ")"
+
+#define DEFAULT_OUTPUT_FILENAME     "a.out"
+
+/* List of all support target, will look like "ArchARM" */
+#define MK_TARGET_ARCH(target)  Arch ## target
+typedef enum {
+    ArchNone,
+#define DEF_SUPPORT_TARGET(target, name, default_triple)  \
+    MK_TARGET_ARCH(target),
+#   include "target.inc"
+
+    MaxTargetArch
+} TargetArchEnum;
+
+typedef struct {
+    TargetArchEnum Arch;
+    const char* Name;
+    const char* DefaultTriple;
+} TargetArch;
+
+static const TargetArch TargetArchTable[] = {
+    { ArchNone, "none", "unknown-unknown-linux" },
+#define DEF_SUPPORT_TARGET(target, name, default_triple)  \
+    { MK_TARGET_ARCH(target), name, default_triple },
+#   include "target.inc"
+};
+
+#if defined(__arm__)
+#   define HOST_ARCH                        MK_TARGET_ARCH(X86) 
+#elif defined(__i386__)
+#   define HOST_ARCH                        MK_TARGET_ARCH(ARM) 
+#elif defined(__x86_64__)                   
+#   define HOST_ARCH                        MK_TARGET_ARCH(X64) 
+#else
+#   error "We can not find default triple string for your host machine, please define it by yourself via option '--triple' or '-t'"
+#endif
+
+#define DEFAULT_TARGET_TRIPLE_STRING        TargetArchTable[HOST_ARCH].DefaultTriple
+
+/* Lists of all target features, will look like "{Target}FeatureNEON" */
+#define MK_TARGET_FEATURE(target, id)   target ## id
+typedef enum {
+    FeatureNone = 0,
+#define DEF_TARGET_FEATURE(target, id, key, description)    \
+    MK_TARGET_FEATURE(target, id),
+#define HOOK_TARGET_FIRST_FEATURE(target, id, key, description) \
+    target ## FeatureStart,    \
+    MK_TARGET_FEATURE(target, id) = target ## FeatureStart,    
+#   include "target.inc"
+
+    MaxTargetFeature
+} TargetFeatureEnum;
+
+/* Feature as bits using in {Target}TargetCPU, will look like "X{Target}FeatureNEON" */
+#define MK_TARGET_FEATURE_BIT(target, id)   X ## target ## id
+typedef enum {
+    XFeatureNone = 0,
+#define DEF_TARGET_FEATURE(target, id, key, description)    \
+    MK_TARGET_FEATURE_BIT(target, id) = 1 << (MK_TARGET_FEATURE(target, id) - target ## FeatureStart),
+#   include "target.inc"
+
+    XMaxTargetFeature
+} TargetFeatureBit;
+
+typedef struct {
+    TargetArchEnum Arch; 
+    TargetFeatureEnum Key;
+    TargetFeatureBit Bit;
+    const char* Name;
+    const char* Desc;
+} TargetFeature;
+
+/* Should be 1-1 mapping with TargetFeatureEnum */
+static const TargetFeature TargetFeatureTable[] = {
+    { ArchNone, FeatureNone, XFeatureNone, "none", "Empty feature" },    /* FeatureNone */
+#define DEF_TARGET_FEATURE(target, id, key, description)    \
+    { MK_TARGET_ARCH(target), MK_TARGET_FEATURE(target, id), MK_TARGET_FEATURE_BIT(target, id), key, description },
+#   include "target.inc"
+};
+
+typedef struct {
+    TargetArchEnum Arch; 
+    const char* Name;
+    const char* Desc;
+    unsigned int FeatureEnabled;
+} TargetCPU;
+
+/* Sorted by CPU name such that we can call bsearch() to quickly retain the CPU entry corresponding to the name */
+#define E(feature)  MK_TARGET_FEATURE_BIT(ARM, feature)
+static const TargetCPU TargetCPUTable[] = {
+    { MK_TARGET_ARCH(ARM), "arm1020e", "Select the arm1020e processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm1020t", "Select the arm1020t processor", E(ArchV5T) },
+    { MK_TARGET_ARCH(ARM), "arm1022e", "Select the arm1022e processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm10e", "Select the arm10e processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm10tdmi", "Select the arm10tdmi processor", E(ArchV5T) },
+    { MK_TARGET_ARCH(ARM), "arm1136j-s", "Select the arm1136j-s processor", E(ArchV6) },
+    { MK_TARGET_ARCH(ARM), "arm1136jf-s", "Select the arm1136jf-s processor", E(ArchV6) | E(FeatureVFP2) },
+    { MK_TARGET_ARCH(ARM), "arm1156t2-s", "Select the arm1156t2-s processor", E(ArchV6T2) | E(FeatureThumb2) },
+    { MK_TARGET_ARCH(ARM), "arm1156t2f-s", "Select the arm1156t2f-s processor", E(ArchV6T2) | E(FeatureThumb2) | E(FeatureVFP2) },
+    { MK_TARGET_ARCH(ARM), "arm1176jz-s", "Select the arm1176jz-s processor", E(ArchV6) },
+    { MK_TARGET_ARCH(ARM), "arm1176jzf-s", "Select the arm1176jzf-s processor", E(ArchV6) | E(FeatureVFP2) },
+    { MK_TARGET_ARCH(ARM), "arm710t", "Select the arm710t processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm720t", "Select the arm720t processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm7tdmi", "Select the arm7tdmi processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm7tdmi-s", "Select the arm7tdmi-s processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm8", "Select the arm8 processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "arm810", "Select the arm810 processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "arm9", "Select the arm9 processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm920", "Select the arm920 processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm920t", "Select the arm920t processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm922t", "Select the arm922t processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm926ej-s", "Select the arm926ej-s processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm940t", "Select the arm940t processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "arm946e-s", "Select the arm946e-s processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm966e-s", "Select the arm966e-s processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm968e-s", "Select the arm968e-s processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm9e", "Select the arm9e processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "arm9tdmi", "Select the arm9tdmi processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "cortex-a8", "Select the cortex-a8 processor", E(ArchV7A) | E(FeatureThumb2) | E(FeatureNEON) },
+    { MK_TARGET_ARCH(ARM), "cortex-a9", "Select the cortex-a9 processor", E(ArchV7A) | E(FeatureThumb2) | E(FeatureNEON) },
+    { MK_TARGET_ARCH(ARM), "ep9312", "Select the ep9312 processor", E(ArchV4T) },
+    { MK_TARGET_ARCH(ARM), "generic", "Select the generic processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "iwmmxt", "Select the iwmmxt processor", E(ArchV5TE) },
+    { MK_TARGET_ARCH(ARM), "mpcore", "Select the mpcore processor", E(ArchV6) | E(FeatureVFP2) },
+    { MK_TARGET_ARCH(ARM), "mpcorenovfp", "Select the mpcorenovfp processor", E(ArchV6) },
+    { MK_TARGET_ARCH(ARM), "strongarm", "Select the strongarm processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "strongarm110", "Select the strongarm110 processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "strongarm1100", "Select the strongarm1100 processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "strongarm1110", "Select the strongarm1110 processor", XFeatureNone },
+    { MK_TARGET_ARCH(ARM), "xscale", "Select the xscale processor", MK_TARGET_FEATURE_BIT(ARM, ArchV5TE) }
+};
+#undef E
+static int CompareCPUName(const void* a, const void* b) {
+    return strcasecmp(((TargetCPU*) a)->Name, ((TargetCPU*) b)->Name);
+}
+#define NUM_TARGET_CPU (sizeof(TargetCPUTable) / sizeof(TargetCPU))
+
+static struct option* SlangOpts = NULL;
+
+static const char* CPUString;
+static const TargetCPU* CPU;
+static const char* TripleString;
+static TargetFeatureEnum EnableFeatureValue, DisableFeatureValue;
+static SlangCompilerOutputTy OutputFileType;
+static const char* OutputFileName;
+static const char* JavaReflectionPackageName;
+static const char* InputFileName;
+static bool Verbose;
+static const char* FeatureEnabledList[MaxTargetFeature + 1];
+
+/* Construct the command options table used in ParseOption::getopt_long */
+static void ConstructCommandOptions() {
+    /* Basic slang command option */
+    static struct option BasicSlangOpts[] = {
+        { "emit-llvm",      no_argument, (int*) &OutputFileType, SlangCompilerOutput_LL },
+        { "emit-bc",        no_argument, (int*) &OutputFileType, SlangCompilerOutput_Bitcode },
+        { "emit-asm",       no_argument, NULL, 'S' },
+        { "emit-obj",       no_argument, NULL, 'c' },
+        { "emit-nothing",   no_argument, (int*) &OutputFileType, SlangCompilerOutput_Nothing },
+
+        { "help",    no_argument, NULL, 'h' }, /* -h */
+        { "verbose", no_argument, NULL, 'v' }, /* -v */
+
+        { "output", required_argument, NULL, 'o' }, /* -o */
+        { "cpu",    required_argument, NULL, 'u' }, /* -u */
+        { "triple", required_argument, NULL, 't' }, /* -t */
+
+        { "output-java-reflection-class", required_argument, NULL, 'j'}   /* -j */
+    };
+
+    const int NumberOfBasicOptions = sizeof(BasicSlangOpts) / sizeof(struct option);
+
+    SlangOpts = new struct option [ NumberOfBasicOptions + MaxTargetFeature * 2 /* for --enable-feature and --disable-feature */ ];
+
+    /* Fill SlangOpts with basic options */
+    memcpy(SlangOpts, BasicSlangOpts, sizeof(BasicSlangOpts));
+
+    int i = NumberOfBasicOptions;
+    /* Add --enable-TARGET_FEATURE option into slang command option */
+#define DEF_TARGET_FEATURE(target, id, key, description)  \
+        SlangOpts[i].name = "enable-" key;   \
+        SlangOpts[i].has_arg = optional_argument;   \
+        SlangOpts[i].flag = (int*) &EnableFeatureValue;  \
+        SlangOpts[i].val = target ## id;    \
+        i++;
+#   include "target.inc"
+
+    /* Add --disable-TARGET_FEATURE option into slang command option */
+#define DEF_TARGET_FEATURE(target, id, key, description)  \
+        SlangOpts[i].name = "disable-" key;   \
+        SlangOpts[i].has_arg = optional_argument;   \
+        SlangOpts[i].flag = (int*) &DisableFeatureValue;    \
+        SlangOpts[i].val = target ## id;    \
+        i++;
+#   include "target.inc"
+
+    /* NULL-terminated the SlangOpts */
+    memset(&SlangOpts[i], 0, sizeof(struct option));
+
+    return;
+}
+
+extern char *optarg;
+extern int optind;
+extern int optopt;
+extern int opterr;
+
+static void Usage(const char* CommandName) {
+#define OUTPUT_OPTION(short_name, long_name, desc) \
+    do {    \
+        if(short_name)  \
+            cout << setw(4) << right << (short_name) << ", ";    \
+        else    \
+            cout << "      ";   \
+        cout << setw(17) << left << (long_name);    \
+        cout << " " << (desc) << endl; \
+    } while(false)
+
+    cout << "Usage: " << CommandName << " [OPTION]... " << "[INPUT FILE]" << endl;
+
+    cout << endl;
+
+    cout << "Basic: " << endl;
+
+    OUTPUT_OPTION("-h", "--help", "print this help");
+    OUTPUT_OPTION("-v", "--verbos", "be verbose");
+    OUTPUT_OPTION("-o", "--output=<FILE>", "write the output of compilation to FILE ('-' means stdout)");
+    OUTPUT_OPTION("-j", "--output-java-reflection-package=<PACKAGE NAME>", "output reflection to Java for BCC exportables");
+
+    cout << endl;
+
+    cout << "Output type:" << endl;
+
+    OUTPUT_OPTION(NULL, "--emit-llvm", "set output type to LLVM assembly (.ll)");
+    OUTPUT_OPTION(NULL, "--emit-bc", "set output type to Bitcode (.bc) (Default)");
+    OUTPUT_OPTION("-S", "--emit-asm", "set output type to target assmbly code (.S)");
+    OUTPUT_OPTION("-c", "--emit-obj", "set output type to target object file (.o)");
+    OUTPUT_OPTION(NULL, "--emit-nothing", "output nothing");
+
+    cout << endl;
+
+    cout << "Code generation option: " << endl;
+
+    OUTPUT_OPTION("-u", "--cpu=CPU", "generate the assembly / object file for the CPU");
+    cout << endl;
+    cout << "\tAvailable CPU:" << endl;
+
+    for(int i=0;i<NUM_TARGET_CPU;i++) 
+        cout << "\t" << setw(13) << right << TargetCPUTable[i].Name << left << ": (" << TargetArchTable[(TargetCPUTable[i].Arch)].Name << ") " << TargetCPUTable[i].Desc << endl;
+
+    cout << endl;
+
+    OUTPUT_OPTION("-t", "--triple=TRIPLE", "generate the assembly / object file for the Triple");
+    cout << "\tDefault triple: " << endl;
+#define DEF_SUPPORT_TARGET(target, name, default_triple)    \
+        cout << "\t" << setw(5) << right << name << left << ": " << default_triple << endl;
+#include "target.inc"
+    cout << endl;
+
+    OUTPUT_OPTION(NULL, "--enable-FEATURE", "enable the FEATURE for the generation of the assembly / object file");
+    OUTPUT_OPTION(NULL, "--disable-FEATURE", "disable the FEATURE for the generation of the assembly / object file");
+    cout << endl;
+    cout << "\tAvailable features:" << endl;
+#define DEF_TARGET_FEATURE(target, id, key, description)    \
+    cout << "\t" << setw(6) << right << key  \
+        << left << ": (" << TargetArchTable[MK_TARGET_ARCH(target)].Name << ") " \
+        << description << endl;
+#include "target.inc"
+
+
+    cout << endl;
+
+
+#undef OUTPUT_OPTION
+    return;
+}
+
+static bool ParseOption(int Argc, char** Argv) {
+    assert(SlangOpts != NULL && "Slang command options table was not initialized!");
+
+    /* Set default value to option */
+    CPU = NULL;
+    TripleString = DEFAULT_TARGET_TRIPLE_STRING;
+    EnableFeatureValue = DisableFeatureValue = FeatureNone;
+    OutputFileType = SlangCompilerOutput_Default;
+    OutputFileName = DEFAULT_OUTPUT_FILENAME;
+    JavaReflectionPackageName = NULL;
+    InputFileName = NULL;
+    Verbose = false;
+    FeatureEnabledList[0] = NULL;
+
+    int ch;
+
+    unsigned int FeatureEnableBits = 0;
+    unsigned int FeatureDisableBits = 0;
+#define ENABLE_FEATURE(x)   \
+    FeatureEnableBits |= (x)
+#define DISABLE_FEATURE(x)   \
+    FeatureDisableBits |= (x)
+    TargetArchEnum ExpectedArch = ArchNone;
+
+    /* Turn off the error message output by getopt_long */
+    opterr = 0;
+
+    while((ch = getopt_long(Argc, Argv, "Schvo:u:t:j:", SlangOpts, NULL)) != -1) {
+        switch(ch) {
+            case 'S':
+                OutputFileType = SlangCompilerOutput_Assembly;
+            break;
+
+            case 'c':
+                OutputFileType = SlangCompilerOutput_Obj;
+            break;
+
+            case 'o':
+                OutputFileName = optarg;
+            break;
+
+            case 'j':
+                JavaReflectionPackageName = optarg;
+            break;
+
+            case 'u':
+            {
+                CPUString = optarg;
+                const TargetCPU SearchCPU = { ArchNone, CPUString, NULL, XFeatureNone };
+                CPU = (TargetCPU*) bsearch(&SearchCPU, TargetCPUTable, sizeof(TargetCPUTable) / sizeof(TargetCPU), sizeof(TargetCPU), CompareCPUName);
+                if(CPU == NULL) {
+                    WARN1(UNKNOWN_CPU, SearchCPU.Name);
+                } else {
+                    CPUString = CPU->Name;
+
+                    if(ExpectedArch == ArchNone)
+                        ExpectedArch = CPU->Arch;
+                    else if(ExpectedArch != CPU->Arch) {
+                        WARN2(MISMATCH_CPU_TARGET_ARCH, TargetArchTable[CPU->Arch].Name, TargetArchTable[ExpectedArch].Name);
+                        break;
+                    }
+                        
+                    /* Get CPU Feature and enable its available feature */
+                    FeatureEnableBits |= CPU->FeatureEnabled;
+                }
+            }
+            break;
+
+            case 't':
+                TripleString = optarg;
+            break;
+
+            case 'h':
+                Usage(Argv[0]);
+                return false;
+            break;
+
+            case 'v':
+                Verbose = true;
+            break;
+
+            case 0:
+            {
+                if(EnableFeatureValue != FeatureNone || DisableFeatureValue != FeatureNone) {
+                    bool IsDisable = (DisableFeatureValue != FeatureNone);
+                    const TargetFeature* FeatureSelected = &TargetFeatureTable[ ((IsDisable) ? DisableFeatureValue : EnableFeatureValue) ];
+                    assert(FeatureSelected != NULL && "Unexpected target feature! (not presented in table but parsed!?)");
+
+                    if(ExpectedArch == ArchNone) 
+                        ExpectedArch = FeatureSelected->Arch;
+                    else if(FeatureSelected->Arch != ExpectedArch) {
+                        WARN2(MISMATCH_FEATURE_TARGET_ARCH, TargetArchTable[FeatureSelected->Arch].Name, TargetArchTable[ExpectedArch].Name);
+                        break;
+                    }
+
+                    if(optarg != NULL && atoi(optarg) == 0) 
+                        IsDisable = !IsDisable;
+
+                    if(IsDisable)
+                        DISABLE_FEATURE(FeatureSelected->Bit);
+                    else
+                        ENABLE_FEATURE(FeatureSelected->Bit);
+                }
+            }
+            break;
+
+            default:
+                cerr << "Unknown option: " << Argv[optind - 1] << endl;
+                return false;
+            break;
+        }
+    }
+#undef ENABLE_FEATURE
+#undef DISABLE_FEATURE
+
+    int CurFeatureEnableListIdx = 0;
+    /* Add the enable/disable feature string to */
+    switch(ExpectedArch) {
+        case ArchNone:
+            ExpectedArch = HOST_ARCH;
+        break;
+
+#define DEF_TARGET_FEATURE(target, id, key, description)    \
+        if(FeatureDisableBits & MK_TARGET_FEATURE_BIT(target, id))  \
+            FeatureEnabledList[ CurFeatureEnableListIdx++ ] = "-" key;  \
+        else if(FeatureEnableBits & MK_TARGET_FEATURE_BIT(target, id))   \
+            FeatureEnabledList[ CurFeatureEnableListIdx++ ] = "+" key;
+#define HOOK_TARGET_FIRST_FEATURE(target, id, key, description) \
+        case Arch ## target:    \
+            /* Fix target triple */ \
+            if(TripleString == DEFAULT_TARGET_TRIPLE_STRING)  \
+                TripleString = TargetArchTable[MK_TARGET_ARCH(target)].DefaultTriple; \
+            DEF_TARGET_FEATURE(target, id, key, description)
+#define HOOK_TARGET_LAST_FEATURE(target, id, key, description) \
+            DEF_TARGET_FEATURE(target, id, key, description)    \
+            FeatureEnabledList[ CurFeatureEnableListIdx++ ] = NULL; /* null-terminator */   \
+        break;
+#include "target.inc"
+
+        default:
+            assert(false && "Unknown / Unsupported CPU architecture");
+        break;
+    }
+
+    Argc -= optind;
+    if(Argc <= 0) {
+        cerr << Argv[0] << ": "ERR_NO_INPUT_FILE << endl;
+        return false;
+    }
+
+    if(Argc > 1) 
+        WARN(MULTIPLE_INPUT_FILES);
+    InputFileName = Argv[optind];
+
+    if(Verbose) {
+        cout << "Input: " << InputFileName << endl;
+
+        if(CPU != NULL)
+            cout << "Use CPU: " << CPU->Name << endl;
+        cout << "Use triple string: " << TripleString << endl;
+        cout << "Expected architecture: " << TargetArchTable[ExpectedArch].Name << endl;
+        
+        cout << "Enable target feature: " << endl;
+        for(int i=0;FeatureEnabledList[i]!=NULL;i++) 
+            if(*FeatureEnabledList[i] == '+')
+                cout << "\t" << &FeatureEnabledList[i][1] << endl;
+        cout << endl;
+
+        cout << "Disable target feature: " << endl;
+        for(int i=0;FeatureEnabledList[i]!=NULL;i++) 
+            if(*FeatureEnabledList[i] == '-')
+                cout << "\t" << &FeatureEnabledList[i][1] << endl;
+        cout << endl;
+
+        cout << "Output to: " << ((strcmp(OutputFileName, "-")) ? OutputFileName : "(standard output)") << ", type: ";
+        switch(OutputFileType) {
+            case SlangCompilerOutput_Assembly: cout << "Target Assembly"; break;
+            case SlangCompilerOutput_LL: cout << "LLVM Assembly"; break;
+            case SlangCompilerOutput_Bitcode: cout << "Bitcode"; break;
+            case SlangCompilerOutput_Nothing: cout << "No output (test)"; break;
+            case SlangCompilerOutput_Obj: cout << "Object file"; break;
+            default: assert(false && "Unknown output type"); break;
+        }
+        cout << endl;
+    }
+
+    return true;
+}
+
+static void DestroyCommandOptions() {
+    if(SlangOpts != NULL) {
+        delete [] SlangOpts;
+        SlangOpts = NULL;
+    }
+    return;
+}
+
+#define SLANG_CALL_AND_CHECK(expr)   \
+    if(!(expr)) { \
+        if(slangGetInfoLog(slang))  \
+            cerr << slangGetInfoLog(slang); \
+        goto on_slang_error;    \
+    } 
+
+int main(int argc, char** argv) {
+    if(argc < 2) {
+        cerr << argv[0] << ": "ERR_NO_INPUT_FILE << endl;
+        return 1;
+    }
+
+    ConstructCommandOptions();
+
+    if(ParseOption(argc, argv)) {
+        /* Start compilation */
+        SlangCompiler* slang = slangCreateCompiler(TripleString, CPUString, FeatureEnabledList);
+        if(slang != NULL) {
+            SLANG_CALL_AND_CHECK( slangSetSourceFromFile(slang, InputFileName) );
+
+            slangSetOutputType(slang, OutputFileType);
+
+            SLANG_CALL_AND_CHECK( slangSetOutputToFile(slang, OutputFileName) );
+
+            SLANG_CALL_AND_CHECK( slangCompile(slang) <= 0 );
+
+            /* output log anyway */
+            if(slangGetInfoLog(slang))
+                cout << slangGetInfoLog(slang);
+
+            if(JavaReflectionPackageName != NULL)
+                SLANG_CALL_AND_CHECK( slangReflectToJava(slang, JavaReflectionPackageName) );
+
+on_slang_error:
+            delete slang;
+        }
+    }
+
+    DestroyCommandOptions();
+
+    return 0;
+}
diff --git a/slang_pragma_recorder.cpp b/slang_pragma_recorder.cpp
new file mode 100644
index 0000000..c445994
--- /dev/null
+++ b/slang_pragma_recorder.cpp
@@ -0,0 +1,71 @@
+#include "slang_pragma_recorder.hpp"
+
+#include "clang/Lex/Token.h"            /* for class clang::Token */
+
+#include "clang/Basic/TokenKinds.h"     /* for enum clang::tok::* */
+
+#include "clang/Lex/Preprocessor.h"     /* for class clang::Preprocessor */
+
+namespace slang {
+
+bool PragmaRecorder::GetPragmaNameFromToken(const Token& Token, std::string& PragmaName) {
+    if(Token.isLiteral())
+        PragmaName.assign(Token.getLiteralData(), Token.getLength());
+    else if(Token.is(clang::tok::identifier))
+        PragmaName.assign(Token.getIdentifierInfo()->getNameStart(), Token.getIdentifierInfo()->getLength());
+    else
+        return false;
+    return true;
+}
+
+bool PragmaRecorder::GetPragmaValueFromToken(const Token& Token, std::string& PragmaValue) {
+    /* Same as the GetPragmaName() */
+    if(Token.is(clang::tok::r_paren))
+        PragmaValue.clear();
+    else
+        return GetPragmaNameFromToken(Token, PragmaValue);
+    return true;
+}
+
+PragmaRecorder::PragmaRecorder(PragmaList& Pragmas) : PragmaHandler(NULL), mPragmas(Pragmas) { return; }
+
+void PragmaRecorder::HandlePragma(Preprocessor &PP, Token &FirstToken) {
+    Token& CurrentToken = FirstToken;
+    std::string PragmaName, PragmaValue = "";
+    /* Pragma in ACC should be a name/value pair */
+
+    if(GetPragmaNameFromToken(FirstToken, PragmaName)) {
+        /* start parsing the value '(' PragmaValue ')' */
+        const Token* NextToken = &PP.LookAhead(0);
+
+        if(NextToken->is(clang::tok::l_paren))
+            PP.LexUnexpandedToken(CurrentToken);
+        else
+            goto end_parsing_pragma_value;
+
+        NextToken = &PP.LookAhead(0);
+        if(GetPragmaValueFromToken(*NextToken, PragmaValue))
+            PP.Lex(CurrentToken);
+        else
+            goto end_parsing_pragma_value;
+
+        if(!NextToken->is(clang::tok::r_paren)) {
+            NextToken = &PP.LookAhead(0);
+            if(NextToken->is(clang::tok::r_paren))
+                PP.LexUnexpandedToken(CurrentToken);
+            else
+                goto end_parsing_pragma_value;
+        }
+
+        /* Until now, we ensure that we have a pragma name/value pair */
+        mPragmas.push_back( make_pair(PragmaName, PragmaValue) );
+    }
+
+end_parsing_pragma_value:
+    /* Infor lex to eat the token */
+    PP.LexUnexpandedToken(CurrentToken);
+
+    return;
+}
+
+}   /* namespace slang */
diff --git a/slang_pragma_recorder.hpp b/slang_pragma_recorder.hpp
new file mode 100644
index 0000000..55c5658
--- /dev/null
+++ b/slang_pragma_recorder.hpp
@@ -0,0 +1,38 @@
+#ifndef _SLANG_COMPILER_PRAGMA_HANDLER_HPP
+#   define _SLANG_COMPILER_PRAGMA_HANDLER_HPP
+
+#include <list>
+#include <string>
+
+#include "clang/Lex/Pragma.h"           /* for class clang::PragmaHandler */
+
+namespace clang {
+
+class Token;
+class Preprocessor;
+
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+typedef std::list< std::pair<std::string, std::string> > PragmaList;
+
+class PragmaRecorder : public PragmaHandler {
+private:
+    PragmaList& mPragmas;
+
+    static bool GetPragmaNameFromToken(const Token& Token, std::string& PragmaName);
+
+    static bool GetPragmaValueFromToken(const Token& Token, std::string& PragmaValue);
+
+public:
+    PragmaRecorder(PragmaList& Pragmas);
+
+    virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};  /* class PragmaRecorder */
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_PRAGMA_HANDLER_HPP */
diff --git a/slang_rs_backend.cpp b/slang_rs_backend.cpp
new file mode 100644
index 0000000..b849ae7
--- /dev/null
+++ b/slang_rs_backend.cpp
@@ -0,0 +1,234 @@
+#include <vector>
+#include <string>
+
+#include "slang_rs_backend.hpp"
+#include "slang_rs_context.hpp"
+#include "slang_rs_export_var.hpp"
+#include "slang_rs_export_func.hpp"
+#include "slang_rs_export_type.hpp"
+
+#include "llvm/Metadata.h"          /* for class llvm::NamedMDNode */
+#include "llvm/ADT/Twine.h"         /* for class llvm::Twine */
+
+#include "clang/AST/DeclGroup.h"    /* for class clang::DeclGroup */
+#include "llvm/ADT/StringExtras.h"  /* for function llvm::utostr_32() and llvm::itostr() */
+
+#include "llvm/Support/IRBuilder.h" /* for class llvm::IRBuilder */
+#include "llvm/Constant.h"          /* for class llvm::Constant */
+#include "llvm/Constants.h"          /* for class llvm::Constant* */
+#include "llvm/Module.h"            /* for class llvm::Module */
+#include "llvm/Function.h"          /* for class llvm::Function */
+#include "llvm/DerivedTypes.h"      /* for class llvm::*Type */
+
+#define MAKE
+
+namespace slang {
+
+RSBackend::RSBackend(RSContext* Context,
+                     Diagnostic &Diags,
+                     const CodeGenOptions& CodeGenOpts,
+                     const TargetOptions& TargetOpts,
+                     const PragmaList& Pragmas,
+                     llvm::raw_ostream* OS,
+                     SlangCompilerOutputTy OutputType) :
+    mContext(Context),
+    Backend(Diags,
+            CodeGenOpts,
+            TargetOpts,
+            Pragmas,
+            OS,
+            OutputType),
+    mExportVarMetadata(NULL)
+{
+    return;
+}
+
+void RSBackend::HandleTopLevelDecl(DeclGroupRef D) {
+    Backend::HandleTopLevelDecl(D);
+    return;
+}
+
+void RSBackend::HandleTranslationUnitEx(ASTContext& Ctx) {
+    mContext->processExport(Ctx);
+
+    /* Dump export variable info */
+    if(mContext->hasExportVar()) {
+        if(mExportVarMetadata == NULL)
+            mExportVarMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_var", NULL, 0, mpModule);
+
+        llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
+
+        for(RSContext::const_export_var_iterator I = mContext->export_vars_begin();
+            I != mContext->export_vars_end();
+            I++)
+        {
+            const RSExportVar* EV = *I;
+            const RSExportType* ET = EV->getType();
+
+            /* variable name */
+            ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, EV->getName().c_str()) );
+
+            /* type name */
+            if(ET->getClass() == RSExportType::ExportClassPrimitive) 
+                ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::utostr_32(static_cast<const RSExportPrimitiveType*>(ET)->getType())) );
+            else if(ET->getClass() == RSExportType::ExportClassPointer)
+                ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)->getPointeeType()->getName()).c_str()) );
+            else
+                ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, EV->getType()->getName().c_str()) );
+
+            mExportVarMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportVarInfo.data(), ExportVarInfo.size()) );
+
+            ExportVarInfo.clear();
+        }
+    }
+
+    /* Dump export function info */
+    if(mContext->hasExportFunc()) {
+        if(mExportFuncMetadata == NULL)
+            mExportFuncMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_func", NULL, 0, mpModule);
+
+        llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
+
+        for(RSContext::const_export_func_iterator I = mContext->export_funcs_begin();
+            I != mContext->export_funcs_end();
+            I++)
+        {
+            const RSExportFunc* EF = *I;
+
+            /* function name */
+            if(!EF->hasParam()) 
+                ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, EF->getName().c_str()) );
+            else {
+                llvm::Function* F = mpModule->getFunction(EF->getName());
+                llvm::Function* HelperFunction;
+                const std::string HelperFunctionName = ".helper_" + EF->getName();
+
+                assert(F && "Function marked as exported disappeared in Bitcode");
+
+                /* Create helper function */
+                {
+                    llvm::PointerType* HelperFunctionParameterTypeP = llvm::PointerType::getUnqual(EF->getParamPacketType()->getLLVMType());
+                    llvm::FunctionType* HelperFunctionType;
+                    std::vector<const llvm::Type*> Params;
+
+                    Params.push_back(HelperFunctionParameterTypeP);
+                    HelperFunctionType = llvm::FunctionType::get(F->getReturnType(), Params, false);
+
+                    HelperFunction = llvm::Function::Create(HelperFunctionType, llvm::GlobalValue::ExternalLinkage, HelperFunctionName, mpModule);
+
+                    HelperFunction->addFnAttr(llvm::Attribute::NoInline);
+                    HelperFunction->setCallingConv(F->getCallingConv());
+
+                    /* Create helper function body */
+                    {
+                        llvm::Argument* HelperFunctionParameter = &(*HelperFunction->arg_begin());
+                        llvm::BasicBlock* BB = llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
+                        llvm::IRBuilder<>* IB = new llvm::IRBuilder<>(BB);
+                        llvm::SmallVector<llvm::Value*, 6> Params;
+                        llvm::Value* Idx[2];
+
+                        Idx[0] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
+
+                        /* getelementptr and load instruction for all elements in parameter .p */
+                        for(int i=0;i<EF->getNumParameters();i++) {
+                            /* getelementptr */
+                            Idx[1] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), i);
+                            llvm::Value* Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx, Idx + 2); 
+                            /* load */
+                            llvm::Value* V = IB->CreateLoad(Ptr);
+                            Params.push_back(V);
+                        }
+
+                        /* call and pass the all elements as paramter to F */
+                        llvm::CallInst* CI = IB->CreateCall(F, Params.data(), Params.data() + Params.size());
+                        CI->setCallingConv(F->getCallingConv());
+
+                        if(F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
+                            IB->CreateRetVoid();
+                        else
+                            IB->CreateRet(CI);
+
+                        delete IB;
+                    }
+                }
+
+                ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()) );
+            }
+
+            mExportFuncMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportFuncInfo.data(), ExportFuncInfo.size()) );
+
+            ExportFuncInfo.clear();
+        }
+    }
+
+    /* Dump export type info */
+    if(mContext->hasExportType()) {
+        llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
+
+        for(RSContext::const_export_type_iterator I = mContext->export_types_begin();
+            I != mContext->export_types_end();
+            I++)
+        {
+            /* First, dump type name list to export */
+            const RSExportType* ET = I->getValue();
+
+            ExportTypeInfo.clear();
+            /* type name */
+            ExportTypeInfo.push_back( llvm::MDString::get(mLLVMContext, ET->getName().c_str()) );
+
+            if(ET->getClass() == RSExportType::ExportClassRecord) {
+                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
+
+                if(mExportTypeMetadata == NULL)
+                    mExportTypeMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_type", NULL, 0, mpModule);
+
+                mExportTypeMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportTypeInfo.data(), ExportTypeInfo.size()) );
+
+                /* Now, export struct field information to %[struct name] */
+                std::string StructInfoMetadataName = "%" + ET->getName();
+                llvm::NamedMDNode* StructInfoMetadata = llvm::NamedMDNode::Create(mLLVMContext, StructInfoMetadataName.c_str(), NULL, 0, mpModule);
+                llvm::SmallVector<llvm::Value*, 3> FieldInfo;
+
+                assert(StructInfoMetadata->getNumOperands() == 0 && "Metadata with same name was created before");
+                for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
+                    FI != ERT->fields_end();
+                    FI++)
+                {
+                    const RSExportRecordType::Field* F = *FI;
+
+                    /* 1. field name */
+                    FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getName().c_str()) );
+                    /* 2. field type name */
+                    FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getType()->getName().c_str()) );
+
+                    /* 3. field kind */
+                    switch(F->getType()->getClass()) {
+                        case RSExportType::ExportClassPrimitive:
+                        case RSExportType::ExportClassVector:
+                        {
+                            RSExportPrimitiveType* EPT = (RSExportPrimitiveType*) F->getType();
+                            FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(EPT->getKind())) );
+                        }
+                        break;
+
+                        default:
+                            FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(RSExportPrimitiveType::DataKindUser)) );
+                        break;
+                    }
+
+                    StructInfoMetadata->addOperand( llvm::MDNode::get(mLLVMContext, FieldInfo.data(), FieldInfo.size()) );
+
+                    FieldInfo.clear();
+                }
+            }   /* ET->getClass() == RSExportType::ExportClassRecord */
+        }
+    }
+
+    return;
+}
+
+RSBackend::~RSBackend() {
+    return;
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_backend.hpp b/slang_rs_backend.hpp
new file mode 100644
index 0000000..e021c1e
--- /dev/null
+++ b/slang_rs_backend.hpp
@@ -0,0 +1,61 @@
+#ifndef _SLANG_COMPILER_RS_BACKEND_HPP
+#   define _SLANG_COMPILER_RENDER_SCRIPT_BACKEND_HPP
+
+#include "libslang.h"
+#include "slang_backend.hpp"
+#include "slang_pragma_recorder.hpp"
+
+#include "clang/CodeGen/CodeGenOptions.h"   /* for class clang::CodeGenOptions */
+
+namespace llvm {
+
+class NamedMDNode;
+
+}   /* namespace llvm */
+
+namespace clang {
+
+class ASTConsumer;
+class Diagnostic;
+class TargetOptions;
+class PragmaList;
+class CodeGenerator;
+class ASTContext;
+class DeclGroupRef;
+
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+class RSContext;
+
+class RSBackend : public Backend {
+private:
+    RSContext* mContext;
+
+    llvm::NamedMDNode* mExportVarMetadata;
+    llvm::NamedMDNode* mExportFuncMetadata;
+    llvm::NamedMDNode* mExportTypeMetadata;
+    llvm::NamedMDNode* mExportElementMetadata;
+
+    virtual void HandleTranslationUnitEx(ASTContext& Ctx);
+
+public:
+    RSBackend(RSContext* Context,
+              Diagnostic &Diags,
+              const CodeGenOptions& CodeGenOpts,
+              const TargetOptions& TargetOpts,
+              const PragmaList& Pragmas,
+              llvm::raw_ostream* OS,
+              SlangCompilerOutputTy OutputType);
+
+    virtual void HandleTopLevelDecl(DeclGroupRef D);
+
+    virtual ~RSBackend();
+};  /* class RSBackend */
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_BACKEND_HPP */
diff --git a/slang_rs_context.cpp b/slang_rs_context.cpp
new file mode 100644
index 0000000..2043d97
--- /dev/null
+++ b/slang_rs_context.cpp
@@ -0,0 +1,207 @@
+#include "slang.hpp"
+#include "slang_rs_context.hpp"
+#include "slang_rs_reflection.hpp"
+#include "slang_rs_export_var.hpp"
+#include "slang_rs_export_func.hpp"
+#include "slang_rs_export_type.hpp"
+#include "slang_rs_pragma_handler.hpp"
+
+#include "clang/AST/Type.h"             /* for class clang::QualType */
+#include "clang/AST/Decl.h"             /* for class clang::*Decl */
+#include "clang/Index/Utils.h"          /* for class clang::idx::ResolveLocationInAST() */
+#include "clang/AST/DeclBase.h"         /* for class clang::Decl and clang::DeclContext */
+#include "clang/AST/ASTContext.h"       /* for class clang::ASTContext */
+#include "clang/Basic/TargetInfo.h"     /* for class clang::TargetInfo */
+#include "clang/Index/ASTLocation.h"    /* for class clang::idx::ASTLocation */
+
+#include "llvm/LLVMContext.h"           /* for function llvm::getGlobalContext() */
+#include "llvm/Target/TargetData.h"     /* for class llvm::TargetData */
+
+using namespace clang::idx;
+
+namespace slang {
+
+RSContext::RSContext(Preprocessor* PP, const TargetInfo* Target) : 
+    mPP(PP),
+    mTarget(Target),
+    mTargetData(NULL),
+    mLLVMContext(llvm::getGlobalContext()),
+    mRSExportVarPragma(NULL),
+    mRSExportFuncPragma(NULL),
+    mRSExportTypePragma(NULL)
+{
+    /* For #pragma rs export_var */
+    mRSExportVarPragma = RSPragmaHandler::CreatePragmaExportVarHandler(this);
+    if(mRSExportVarPragma != NULL)
+        PP->AddPragmaHandler("rs", mRSExportVarPragma);
+
+    /* For #pragma rs export_func */
+    mRSExportFuncPragma = RSPragmaHandler::CreatePragmaExportFuncHandler(this);
+    if(mRSExportFuncPragma != NULL)
+        PP->AddPragmaHandler("rs", mRSExportFuncPragma);
+
+    /* For #pragma rs export_type */
+    mRSExportTypePragma = RSPragmaHandler::CreatePragmaExportTypeHandler(this);
+    if(mRSExportTypePragma != NULL)
+        PP->AddPragmaHandler("rs", mRSExportTypePragma);
+
+    mTargetData = new llvm::TargetData(Slang::TargetDescription);
+
+    return;
+}
+
+bool RSContext::processExportVar(const VarDecl* VD) {
+    assert(!VD->getName().empty() && "Variable name should not be empty");
+
+    /* TODO: some check on variable */
+
+    RSExportType* ET = RSExportType::CreateFromDecl(this, VD);
+    if(!ET) 
+        return false;
+
+    RSExportVar* EV = new RSExportVar(this, VD, ET);
+    if(EV == NULL)
+        return false;
+    else
+        mExportVars.push_back(EV);
+
+    return true;
+}
+
+bool RSContext::processExportFunc(const FunctionDecl* FD) {
+    assert(!FD->getName().empty() && "Function name should not be empty");
+    
+    if(!FD->isThisDeclarationADefinition())
+        return false;
+
+    if(FD->getStorageClass() != FunctionDecl::None) {
+        printf("RSContext::processExportFunc : cannot export extern or static function '%s'\n", FD->getName().str().c_str());
+        return false;
+    }
+
+    RSExportFunc* EF = RSExportFunc::Create(this, FD);
+    if(EF == NULL)
+        return false;
+    else
+        mExportFuncs.push_back(EF);
+
+    return true;
+}
+
+
+bool RSContext::processExportType(ASTContext& Ctx, const llvm::StringRef& Name) {
+    TranslationUnitDecl* TUDecl = Ctx.getTranslationUnitDecl();
+
+    assert(TUDecl != NULL && "Translation unit declaration (top-level declaration) is null object");
+
+    const IdentifierInfo* II = mPP->getIdentifierInfo(Name);
+    if(II == NULL)
+        /* TODO: error: identifier @Name mark as an exportable type cannot be found */
+        return false;
+
+    DeclContext::lookup_const_result R = TUDecl->lookup(II);
+    bool Done = false;
+    RSExportType* ET = NULL;
+
+    RSExportPointerType::IntegerType = Ctx.IntTy.getTypePtr();
+
+    for(DeclContext::lookup_const_iterator I = R.first;
+        I != R.second;
+        I++) 
+    {
+        NamedDecl* const ND = *I;
+        ASTLocation* LastLoc = new ASTLocation(ND);
+        ASTLocation AL = ResolveLocationInAST(Ctx, ND->getLocStart(), LastLoc);
+
+        delete LastLoc;
+        if(AL.isDecl()) {
+            Decl* D = AL.dyn_AsDecl();
+            const Type* T = NULL;
+
+            switch(D->getKind()) {
+                case Decl::Typedef:
+                    T = static_cast<const TypedefDecl*>(D)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
+                break;
+
+                case Decl::Record:
+                    T = static_cast<const RecordDecl*>(D)->getTypeForDecl();
+                break;
+
+                default:
+                    /* unsupported, skip */
+                break;
+            }
+
+            if(T != NULL)
+                ET = RSExportType::Create(this, T);
+        }
+    }
+
+    RSExportPointerType::IntegerType = NULL;
+
+    return (ET != NULL);
+}
+
+void RSContext::processExport(ASTContext& Ctx) {
+    /* Export variable */
+    TranslationUnitDecl* TUDecl = Ctx.getTranslationUnitDecl();
+    for(DeclContext::decl_iterator DI = TUDecl->decls_begin();
+        DI != TUDecl->decls_end();
+        DI++)
+    {
+        if(DI->getKind() == Decl::Var) {
+            VarDecl* VD = (VarDecl*) (*DI);
+            NeedExportVarSet::iterator EI = mNeedExportVars.find(VD->getName());
+            if(EI != mNeedExportVars.end() && processExportVar(VD))
+                mNeedExportVars.erase(EI);
+        } else if(DI->getKind() == Decl::Function) {
+            FunctionDecl* FD = (FunctionDecl*) (*DI);
+            NeedExportFuncSet::iterator EI = mNeedExportFuncs.find(FD->getName());
+            if(EI != mNeedExportFuncs.end() && processExportFunc(FD))
+                mNeedExportFuncs.erase(EI);
+        }
+    }
+
+    /* Finally, export type forcely set to be exported by user */
+    for(NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin();
+        EI != mNeedExportTypes.end();
+        EI++)
+        if(!processExportType(Ctx, EI->getKey()))
+            printf("RSContext::processExport : failed to export type '%s'\n", EI->getKey().str().c_str());
+
+    
+    return;
+}
+
+bool RSContext::insertExportType(const llvm::StringRef& TypeName, RSExportType* ET) {
+    ExportTypeMap::value_type* NewItem = ExportTypeMap::value_type::Create(TypeName.begin(), TypeName.end(), mExportTypes.getAllocator(), ET);
+
+    if(mExportTypes.insert(NewItem)) {
+        return true;
+    } else {
+        delete NewItem;
+        return false;
+    }
+}
+
+bool RSContext::reflectToJava(const char* OutputClassPath, const std::string& InputFileName, const std::string& OutputBCFileName) {
+    RSReflection* R = new RSReflection(this);
+    bool ret = R->reflect(OutputClassPath, InputFileName, OutputBCFileName); 
+    if(!ret)
+        printf("RSContext::reflectToJava : failed to do reflection (%s)\n", R->getLastError());
+    delete R;
+    return ret;
+}
+
+RSContext::~RSContext() {
+    if(mRSExportVarPragma != NULL)
+        delete mRSExportVarPragma;
+    if(mRSExportFuncPragma != NULL)
+        delete mRSExportFuncPragma;
+    if(mRSExportTypePragma != NULL)
+        delete mRSExportTypePragma;
+    if(mTargetData != NULL)
+        delete mTargetData;
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_context.hpp b/slang_rs_context.hpp
new file mode 100644
index 0000000..811af7e
--- /dev/null
+++ b/slang_rs_context.hpp
@@ -0,0 +1,121 @@
+#ifndef _SLANG_COMPILER_RS_CONTEXT_HPP
+#   define _SLANG_COMPILER_RS_CONTEXT_HPP
+
+#include "slang_rs_export_element.hpp"
+
+#include <map>
+#include <list>
+#include <string>
+#include <cstdio>
+
+#include "llvm/ADT/StringSet.h"     /* for class llvm::StringSet */
+#include "llvm/ADT/StringMap.h"     /* for class llvm::StringMap */
+
+#include "clang/Lex/Preprocessor.h"     /* for class clang::Preprocessor */
+
+namespace llvm {
+    class LLVMContext;
+    class TargetData;
+}   /* namespace llvm */
+
+namespace clang {
+
+class VarDecl;
+class ASTContext;
+class TargetInfo;
+class FunctionDecl;
+class SourceManager;
+    
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+class RSExportVar;
+class RSExportFunc;
+class RSExportType;
+class RSPragmaHandler;
+
+class RSContext {
+    typedef llvm::StringSet<> NeedExportVarSet;
+    typedef llvm::StringSet<> NeedExportFuncSet;
+    typedef llvm::StringSet<> NeedExportTypeSet;
+
+public:
+    typedef std::list<RSExportVar*> ExportVarList;
+    typedef std::list<RSExportFunc*> ExportFuncList;
+    typedef llvm::StringMap<RSExportType*> ExportTypeMap;
+
+private:
+    Preprocessor* mPP;
+    const TargetInfo* mTarget;
+
+    llvm::TargetData* mTargetData;
+    llvm::LLVMContext& mLLVMContext;
+
+    RSPragmaHandler* mRSExportVarPragma;
+    RSPragmaHandler* mRSExportFuncPragma;
+    RSPragmaHandler* mRSExportTypePragma;
+
+    /* Remember the variables/types/elements annotated in #pragma to be exported */
+    NeedExportVarSet mNeedExportVars;
+    NeedExportFuncSet mNeedExportFuncs;
+    NeedExportTypeSet mNeedExportTypes;
+
+    bool processExportVar(const VarDecl* VD);
+    bool processExportFunc(const FunctionDecl* FD);
+    bool processExportType(ASTContext& Ctx, const llvm::StringRef& Name);
+
+    ExportVarList mExportVars;
+    ExportFuncList mExportFuncs;
+    ExportTypeMap mExportTypes;
+
+public:
+    RSContext(Preprocessor* PP, const TargetInfo* Target);
+
+    inline Preprocessor* getPreprocessor() const { return mPP; }
+    inline const llvm::TargetData* getTargetData() const { return mTargetData; }
+    inline llvm::LLVMContext& getLLVMContext() const { return mLLVMContext; }
+    inline const SourceManager* getSourceManager() const { return &mPP->getSourceManager(); }
+
+    inline void addExportVar(const std::string& S) { mNeedExportVars.insert(S); return; }
+    inline void addExportFunc(const std::string& S) { mNeedExportFuncs.insert(S); return; }
+    inline void addExportType(const std::string& S) { mNeedExportTypes.insert(S); return; }
+
+    void processExport(ASTContext& Ctx);
+
+    typedef ExportVarList::const_iterator const_export_var_iterator;
+    const_export_var_iterator export_vars_begin() const { return mExportVars.begin(); }
+    const_export_var_iterator export_vars_end() const { return mExportVars.end(); }
+    inline bool hasExportVar() const { return !mExportVars.empty(); }
+
+    typedef ExportFuncList::const_iterator const_export_func_iterator;
+    const_export_func_iterator export_funcs_begin() const { return mExportFuncs.begin(); }
+    const_export_func_iterator export_funcs_end() const { return mExportFuncs.end(); }
+    inline bool hasExportFunc() const { return !mExportFuncs.empty(); }
+
+    typedef ExportTypeMap::iterator export_type_iterator;
+    typedef ExportTypeMap::const_iterator const_export_type_iterator;
+    export_type_iterator export_types_begin() { return mExportTypes.begin(); }
+    export_type_iterator export_types_end() { return mExportTypes.end(); }
+    const_export_type_iterator export_types_begin() const { return mExportTypes.begin(); }
+    const_export_type_iterator export_types_end() const { return mExportTypes.end(); }
+    inline bool hasExportType() const { return !mExportTypes.empty(); }
+    export_type_iterator findExportType(const llvm::StringRef& TypeName) { return mExportTypes.find(TypeName); }
+    const_export_type_iterator findExportType(const llvm::StringRef& TypeName) const { return mExportTypes.find(TypeName); }
+    /* 
+     * Insert the specified Typename/Type pair into the map. If the key
+     *  already exists in the map, return false and ignore the request, otherwise
+     *  insert it and return true.
+     */
+    bool insertExportType(const llvm::StringRef& TypeName, RSExportType* Type);
+
+    bool reflectToJava(const char* OutputClassPath, const std::string& InputFileName, const std::string& OutputBCFileName);
+
+    ~RSContext();
+};
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_RS_CONTEXT_HPP */
diff --git a/slang_rs_export_element.cpp b/slang_rs_export_element.cpp
new file mode 100644
index 0000000..c5c66ec
--- /dev/null
+++ b/slang_rs_export_element.cpp
@@ -0,0 +1,143 @@
+#include "slang_rs_context.hpp"
+#include "slang_rs_export_type.hpp"
+#include "slang_rs_export_element.hpp"
+
+#include "clang/AST/Decl.h"                 /* for class clang::*Decl */
+#include "clang/AST/Type.h"                 /* for class clang::*Type */
+
+#include "clang/Basic/SourceLocation.h"     /* for class clang::SourceLocation */
+#include "clang/Basic/IdentifierTable.h"    /* for class clang::IdentifierInfo */
+
+namespace slang {
+
+bool RSExportElement::Initialized = false;
+RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap;
+
+void RSExportElement::Init() {
+    if(!Initialized) {
+        /* Initialize ElementInfoMap */
+#define USE_ELEMENT_DATA_TYPE
+#define USE_ELEMENT_DATA_KIND
+#define DEF_ELEMENT(_name, _dk, _dt, _norm, _vsize) \
+        {   \
+            ElementInfo* EI = new ElementInfo;  \
+            EI->kind = GET_ELEMENT_DATA_KIND(_dk);  \
+            EI->type = GET_ELEMENT_DATA_TYPE(_dt);  \
+            EI->normalized = _norm;  \
+            EI->vsize = _vsize;  \
+            \
+            llvm::StringRef Name(_name);  \
+            ElementInfoMap.insert( ElementInfoMapTy::value_type::Create(Name.begin(),   \
+                                                                        Name.end(), \
+                                                                        ElementInfoMap.getAllocator(),  \
+                                                                        EI));   \
+        }
+#include "slang_rs_export_element_support.inc"
+
+        Initialized = true;
+    }
+    return;
+}
+
+RSExportType* RSExportElement::Create(RSContext* Context, const Type* T, const ElementInfo* EI) {
+    /* Create RSExportType corresponded to the @T first and then verify */
+
+    llvm::StringRef TypeName;
+    RSExportType* ET = NULL;
+
+    if(!Initialized)
+        Init();
+
+    assert(EI != NULL && "Element info not found");
+
+    if(!RSExportType::NormalizeType(T, TypeName))
+        return NULL;
+
+    switch(T->getTypeClass()) {
+        case Type::Builtin:
+        case Type::Pointer:
+        {
+            assert(EI->vsize == 1 && "Element not a primitive class (please check your macro)");
+            RSExportPrimitiveType* EPT = RSExportPrimitiveType::Create(Context, T, TypeName, EI->kind, EI->normalized);
+            /* verify */
+            assert(EI->type == EPT->getType() && "Element has unexpected type");
+            ET = EPT;
+        }
+        break;
+
+        case Type::ExtVector:
+        {
+            assert(EI->vsize > 1 && "Element not a vector class (please check your macro)");
+            RSExportVectorType* EVT = RSExportVectorType::Create(Context, 
+                                                                 static_cast<ExtVectorType*>(T->getCanonicalTypeInternal().getTypePtr()), 
+                                                                 TypeName, 
+                                                                 EI->kind,
+                                                                 EI->normalized);
+            /* verify */
+            assert(EI->type == EVT->getType() && "Element has unexpected type");
+            assert(EI->vsize == EVT->getNumElement() && "Element has unexpected size of vector");
+            ET = EVT;
+        }
+        break;
+
+        case Type::Record:
+        {
+            /* Must be RS object type */
+            RSExportPrimitiveType* EPT = RSExportPrimitiveType::Create(Context, T, TypeName, EI->kind, EI->normalized);
+            /* verify */
+            assert(EI->type == EPT->getType() && "Element has unexpected type");
+            ET = EPT;
+        }
+        break;
+
+        default:
+            /* TODO: warning: type is not exportable */
+            printf("RSExportElement::Create : type '%s' is not exportable\n", T->getTypeClassName());
+        break;
+    } 
+
+    return ET;
+}
+
+RSExportType* RSExportElement::CreateFromDecl(RSContext* Context, const DeclaratorDecl* DD) {
+    const Type* T = RSExportType::GetTypeOfDecl(DD);
+    const Type* CT = GET_CANONICAL_TYPE(T);
+    const ElementInfo* EI = NULL;
+
+    /* Shortcut, rs element like rs_color4f should be the type of primitive or vector */
+    if((CT->getTypeClass() != Type::Builtin) && (CT->getTypeClass() != Type::ExtVector))
+        return RSExportType::Create(Context, T);
+
+    /* Iterative query the name of type to see whether it's element name like rs_color4f or its alias (via typedef) */
+    while(T != CT) {
+        if(T->getTypeClass() != Type::Typedef) 
+            break;
+        else {
+            const TypedefType* TT = static_cast<const TypedefType*>(T);
+            const TypedefDecl* TD = TT->getDecl();
+            EI = GetElementInfo(TD->getName());
+            if(EI != NULL)
+                break;
+                
+            T = TD->getUnderlyingType().getTypePtr();
+        }
+    }
+
+    if(EI == NULL)
+        return RSExportType::Create(Context, T);
+    else
+        return RSExportElement::Create(Context, T, EI);
+}
+
+const RSExportElement::ElementInfo* RSExportElement::GetElementInfo(const llvm::StringRef& Name) {
+    if(!Initialized)
+        Init();
+
+    ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
+    if(I == ElementInfoMap.end())
+        return NULL;
+    else
+        return I->getValue();
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_export_element.hpp b/slang_rs_export_element.hpp
new file mode 100644
index 0000000..707b5f6
--- /dev/null
+++ b/slang_rs_export_element.hpp
@@ -0,0 +1,57 @@
+#ifndef _SLANG_COMPILER_RS_EXPORT_ELEMENT_HPP
+#   define _SLANG_COMPILER_RS_EXPORT_ELEMENT_HPP
+
+#include <string>
+
+#include "slang_rs_export_type.hpp"
+
+#include "llvm/ADT/StringMap.h"     /* for class llvm::StringMap */
+#include "llvm/ADT/StringRef.h"     /* for class llvm::StringRef */
+
+#include "clang/Lex/Token.h"        /* for class clang::Token */
+
+namespace clang {
+
+class Type;
+class DeclaratorDecl;
+
+}   /* namespace clang */
+
+namespace slang {
+
+class RSContext;
+class RSExportType;
+
+using namespace clang;
+
+class RSExportElement {
+    /* This is an utility class for handling the RS_ELEMENT_ADD* marker */
+    RSExportElement() { return; }
+
+    typedef struct {
+        RSExportPrimitiveType::DataKind kind;
+        RSExportPrimitiveType::DataType type;
+        bool normalized;
+        int vsize;
+    } ElementInfo;
+
+    typedef llvm::StringMap<const ElementInfo*> ElementInfoMapTy;
+
+private:
+    /* Macro name <-> ElementInfo */
+    static ElementInfoMapTy ElementInfoMap;
+
+    static bool Initialized;
+
+    static RSExportType* Create(RSContext* Context, const Type* T, const ElementInfo* EI);
+
+    static const ElementInfo* GetElementInfo(const llvm::StringRef& Name);
+public:
+    static void Init();
+
+    static RSExportType* CreateFromDecl(RSContext* Context, const DeclaratorDecl* DD);
+};
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_RS_EXPORT_ELEMENT_HPP */
diff --git a/slang_rs_export_element_support.inc b/slang_rs_export_element_support.inc
new file mode 100644
index 0000000..204c48e
--- /dev/null
+++ b/slang_rs_export_element_support.inc
@@ -0,0 +1,181 @@
+#ifdef USE_ELEMENT_DATA_TYPE
+
+#   define GET_ELEMENT_DATA_TYPE(type)      ELEMENT_DATA_TYPE_ ## type
+
+#   define ELEMENT_DATA_TYPE_FLOAT_32       RSExportPrimitiveType::DataTypeFloat32
+#   define ELEMENT_DATA_TYPE_SIGNED_8       RSExportPrimitiveType::DataTypeSigned8
+#   define ELEMENT_DATA_TYPE_SIGNED_16      RSExportPrimitiveType::DataTypeSigned16
+#   define ELEMENT_DATA_TYPE_SIGNED_32      RSExportPrimitiveType::DataTypeSigned32
+#   define ELEMENT_DATA_TYPE_UNSIGNED_8     RSExportPrimitiveType::DataTypeUnsigned8
+#   define ELEMENT_DATA_TYPE_UNSIGNED_16    RSExportPrimitiveType::DataTypeUnsigned16
+#   define ELEMENT_DATA_TYPE_UNSIGNED_32    RSExportPrimitiveType::DataTypeUnsigned32
+#   define ELEMENT_DATA_TYPE_UNSIGNED_565   RSExportPrimitiveType::DataTypeUnsigned565
+#   define ELEMENT_DATA_TYPE_UNSIGNED_5551  RSExportPrimitiveType::DataTypeUnsigned5551
+#   define ELEMENT_DATA_TYPE_UNSIGNED_4444  RSExportPrimitiveType::DataTypeUnsigned4444
+#   define ELEMENT_DATA_TYPE_RS_ELEMENT     RSExportPrimitiveType::DataTypeRSElement
+#   define ELEMENT_DATA_TYPE_RS_TYPE        RSExportPrimitiveType::DataTypeRSType
+#   define ELEMENT_DATA_TYPE_RS_ALLOCATION  RSExportPrimitiveType::DataTypeRSAllocation
+#   define ELEMENT_DATA_TYPE_RS_SAMPLER     RSExportPrimitiveType::DataTypeRSSampler
+#   define ELEMENT_DATA_TYPE_RS_SCRIPT      RSExportPrimitiveType::DataTypeRSScript
+#   define ELEMENT_DATA_TYPE_RS_MESH        RSExportPrimitiveType::DataTypeRSMesh
+#   define ELEMENT_DATA_TYPE_RS_PROGRAM_FRAGMENT    RSExportPrimitiveType::DataTypeRSProgramFragment
+#   define ELEMENT_DATA_TYPE_RS_PROGRAM_VERTEX      RSExportPrimitiveType::DataTypeRSProgramVertex
+#   define ELEMENT_DATA_TYPE_RS_PROGRAM_RASTER      RSExportPrimitiveType::DataTypeRSProgramRaster
+#   define ELEMENT_DATA_TYPE_RS_PROGRAM_STORE       RSExportPrimitiveType::DataTypeRSProgramStore
+
+#endif  /* USE_ELEMENT_TYPE_NAME */
+
+#ifdef USE_ELEMENT_DATA_KIND
+
+#   define GET_ELEMENT_DATA_KIND(kind)  ELEMENT_DATA_KIND_ ## kind
+
+#   define ELEMENT_DATA_KIND_USER       RSExportPrimitiveType::DataKindUser
+#   define ELEMENT_DATA_KIND_COLOR      RSExportPrimitiveType::DataKindColor
+#   define ELEMENT_DATA_KIND_POSITION   RSExportPrimitiveType::DataKindPosition
+#   define ELEMENT_DATA_KIND_TEXTURE    RSExportPrimitiveType::DataKindTexture
+#   define ELEMENT_DATA_KIND_NORMAL     RSExportPrimitiveType::DataKindNormal
+#   define ELEMENT_DATA_KIND_INDEX      RSExportPrimitiveType::DataKindIndex
+#   define ELEMENT_DATA_KIND_POINT_SIZE RSExportPrimitiveType::DataKindPointSize
+#   define ELEMENT_DATA_KIND_PIXEL_L    RSExportPrimitiveType::DataKindPixelL
+#   define ELEMENT_DATA_KIND_PIXEL_A    RSExportPrimitiveType::DataKindPixelA
+#   define ELEMENT_DATA_KIND_PIXEL_LA   RSExportPrimitiveType::DataKindPixelLA
+#   define ELEMENT_DATA_KIND_PIXEL_RGB  RSExportPrimitiveType::DataKindPixelRGB
+#   define ELEMENT_DATA_KIND_PIXEL_RGBA RSExportPrimitiveType::DataKindPixelRGBA
+
+#endif  /* USE_ELEMENT_TYPE_KIND */
+
+/* DEF_ELEMENT(name, dk, dt, norm, vsize) */
+#ifdef DEF_ELEMENT
+
+    /* RS_KIND_INDEX */
+    DEF_ELEMENT("rs_index", INDEX, UNSIGNED_16, false, 1)
+
+    /* RS_KIND_COLOR */
+    DEF_ELEMENT("rs_color3f", COLOR, FLOAT_32, false, 3)
+    DEF_ELEMENT("rs_color4f", COLOR, FLOAT_32, false, 4)
+    DEF_ELEMENT("rs_color3u", COLOR, UNSIGNED_8, true, 3)
+    DEF_ELEMENT("rs_color4u", COLOR, UNSIGNED_8, true, 4)
+
+    /* RS_KIND_POSITION */
+    DEF_ELEMENT("rs_position1", POSITION, FLOAT_32, false, 1)
+    DEF_ELEMENT("rs_position2", POSITION, FLOAT_32, false, 2)
+    DEF_ELEMENT("rs_position3", POSITION, FLOAT_32, false, 3)
+    DEF_ELEMENT("rs_position4", POSITION, FLOAT_32, false, 4)
+
+    /* RS_KIND_TEXTURE */
+    DEF_ELEMENT("rs_texture_coord1", TEXTURE, FLOAT_32, false, 1)
+    DEF_ELEMENT("rs_texture_coord2", TEXTURE, FLOAT_32, false, 2)
+    DEF_ELEMENT("rs_texture_coord3", TEXTURE, FLOAT_32, false, 3)
+    DEF_ELEMENT("rs_texture_coord4", TEXTURE, FLOAT_32, false, 4)
+
+    /* RS_KIND_NORMAL */
+    DEF_ELEMENT("rs_normal", NORMAL, FLOAT_32, false, 3)
+
+    /* RS_KIND_POINT_SIZE */
+    DEF_ELEMENT("rs_point_size", POINT_SIZE, FLOAT_32, false, 3)
+
+#endif  /* DEF_ELEMENT */
+
+#if 0
+
+/* Element.createPixel(), always normalized */
+#ifdef DEF_PIXEL_ELEMENT /* (dk, dt, vsize) */
+    DEF_PIXEL_ELEMENT(PIXEL_L, UNSIGNED_8, 1)
+    DEF_PIXEL_ELEMENT(PIXEL_A, UNSIGNED_8, 1)
+    DEF_PIXEL_ELEMENT(PIXEL_LA, UNSIGNED_8, 2)
+    DEF_PIXEL_ELEMENT(PIXEL_RGB, UNSIGNED_8, 3)
+    DEF_PIXEL_ELEMENT(PIXEL_RGBA, UNSIGNED_8, 4)
+    DEF_PIXEL_ELEMENT(PIXEL_RGB, UNSIGNED_565, 1)
+    DEF_PIXEL_ELEMENT(PIXEL_RGBA, UNSIGNED_5551, 1)
+    DEF_PIXEL_ELEMENT(PIXEL_RGBA, UNSIGNED_4444, 1)
+#   undef DEF_PIXEL_ELEMENT
+#endif  /* DEF_PIXEL_ELEMENT */
+
+#endif
+
+
+#ifdef DEF_PRIMITIVE_DATA_TYPE /* (type, name) */
+
+    DEF_PRIMITIVE_DATA_TYPE(FLOAT_32, "float")
+    DEF_PRIMITIVE_DATA_TYPE(SIGNED_8, "char")
+    DEF_PRIMITIVE_DATA_TYPE(SIGNED_16, "short")
+    DEF_PRIMITIVE_DATA_TYPE(SIGNED_32, "int")
+    DEF_PRIMITIVE_DATA_TYPE(UNSIGNED_8, "uchar")
+    DEF_PRIMITIVE_DATA_TYPE(UNSIGNED_16, "ushort")
+    DEF_PRIMITIVE_DATA_TYPE(UNSIGNED_32, "uint")
+    DEF_PRIMITIVE_DATA_TYPE(UNSIGNED_565, "u565")
+    DEF_PRIMITIVE_DATA_TYPE(UNSIGNED_5551, "u5551")
+    DEF_PRIMITIVE_DATA_TYPE(UNSIGNED_4444, "u4444")
+
+#   undef DEF_PRIMITIVE_DATA_TYPE
+#endif  /* DEF_PRIMITIVE_DATA_TYPE */
+
+#ifdef DEF_RS_OBJECT_TYPE /* (type, name) */
+
+    DEF_RS_OBJECT_TYPE(RS_ELEMENT, "rs_element")
+    DEF_RS_OBJECT_TYPE(RS_TYPE, "rs_type")
+    DEF_RS_OBJECT_TYPE(RS_ALLOCATION, "rs_allocation")
+    DEF_RS_OBJECT_TYPE(RS_SAMPLER, "rs_sampler")
+    DEF_RS_OBJECT_TYPE(RS_SCRIPT, "rs_script")
+    DEF_RS_OBJECT_TYPE(RS_MESH, "rs_mesh")
+    DEF_RS_OBJECT_TYPE(RS_PROGRAM_FRAGMENT, "rs_program_fragment")
+    DEF_RS_OBJECT_TYPE(RS_PROGRAM_VERTEX, "rs_program_vertex")
+    DEF_RS_OBJECT_TYPE(RS_PROGRAM_RASTER, "rs_program_raster")
+    DEF_RS_OBJECT_TYPE(RS_PROGRAM_STORE, "rs_program_store")
+
+#   undef DEF_RS_OBJECT_TYPE
+#endif  /* DEF_RS_OBJECT_TYPE */
+
+#ifdef DEF_ELEMENT
+#   undef DEF_ELEMENT
+#endif
+
+#ifdef USE_ELEMENT_DATA_TYPE
+
+#   undef GET_ELEMENT_DATA_TYPE
+
+#   undef ELEMENT_DATA_TYPE_FLOAT_32
+#   undef ELEMENT_DATA_TYPE_SIGNED_8
+#   undef ELEMENT_DATA_TYPE_SIGNED_16
+#   undef ELEMENT_DATA_TYPE_SIGNED_32
+#   undef ELEMENT_DATA_TYPE_UNSIGNED_8
+#   undef ELEMENT_DATA_TYPE_UNSIGNED_16
+#   undef ELEMENT_DATA_TYPE_UNSIGNED_32
+#   undef ELEMENT_DATA_TYPE_UNSIGNED_565
+#   undef ELEMENT_DATA_TYPE_UNSIGNED_5551
+#   undef ELEMENT_DATA_TYPE_UNSIGNED_4444
+#   undef ELEMENT_DATA_TYPE_RS_ELEMENT
+#   undef ELEMENT_DATA_TYPE_RS_TYPE
+#   undef ELEMENT_DATA_TYPE_RS_ALLOCATION
+#   undef ELEMENT_DATA_TYPE_RS_SAMPLER
+#   undef ELEMENT_DATA_TYPE_RS_SCRIPT
+#   undef ELEMENT_DATA_TYPE_RS_MESH
+#   undef ELEMENT_DATA_TYPE_RS_PROGRAM_FRAGMENT
+#   undef ELEMENT_DATA_TYPE_RS_PROGRAM_VERTEX
+#   undef ELEMENT_DATA_TYPE_RS_PROGRAM_RASTER
+#   undef ELEMENT_DATA_TYPE_RS_PROGRAM_STORE
+
+#   undef USE_ELEMENT_DATA_TYPE
+
+#endif
+
+#ifdef USE_ELEMENT_DATA_KIND
+
+#   undef GET_ELEMENT_DATA_KIND
+
+#   undef ELEMENT_DATA_KIND_USER
+#   undef ELEMENT_DATA_KIND_COLOR
+#   undef ELEMENT_DATA_KIND_POSITION
+#   undef ELEMENT_DATA_KIND_TEXTURE
+#   undef ELEMENT_DATA_KIND_NORMAL
+#   undef ELEMENT_DATA_KIND_INDEX
+#   undef ELEMENT_DATA_KIND_POINT_SIZE
+#   undef ELEMENT_DATA_KIND_PIXEL_L
+#   undef ELEMENT_DATA_KIND_PIXEL_A
+#   undef ELEMENT_DATA_KIND_PIXEL_LA
+#   undef ELEMENT_DATA_KIND_PIXEL_RGB
+#   undef ELEMENT_DATA_KIND_PIXEL_RGBA
+
+#   undef USE_ELEMENT_DATA_KIND
+
+#endif
diff --git a/slang_rs_export_func.cpp b/slang_rs_export_func.cpp
new file mode 100644
index 0000000..426d384
--- /dev/null
+++ b/slang_rs_export_func.cpp
@@ -0,0 +1,70 @@
+#include "slang_rs_context.hpp"
+#include "slang_rs_export_func.hpp"
+#include "slang_rs_export_type.hpp"
+
+#include "clang/AST/Decl.h"         /* for clang::*Decl */
+
+namespace slang {
+
+RSExportFunc* RSExportFunc::Create(RSContext* Context, const FunctionDecl* FD) {
+    llvm::StringRef Name = FD->getName();
+    RSExportFunc* F;
+
+    assert(!Name.empty() && "Function must have a name");
+
+    F = new RSExportFunc(Context, Name);
+
+    /* Check whether the parameters passed to the function is exportable */
+    for(int i=0;i<FD->getNumParams();i++) {
+        const ParmVarDecl* PVD = FD->getParamDecl(i); 
+        const llvm::StringRef ParamName = PVD->getName();
+
+        assert(!ParamName.empty() && "Parameter must have a name");
+
+        if(PVD->hasDefaultArg())
+            printf("Note: parameter '%s' in function '%s' has default value will not support\n", ParamName.str().c_str(), Name.str().c_str());
+
+        /* Check type */
+        RSExportType* PET = RSExportType::CreateFromDecl(Context, PVD);
+        if(PET != NULL) {
+            F->mParams.push_back(new Parameter(PET, ParamName));
+        } else {
+            printf("Note: parameter '%s' in function '%s' uses unsupported type", ParamName.str().c_str(), Name.str().c_str());
+            delete F;
+            return NULL;
+        }
+    }
+
+    return F;
+}
+
+const RSExportRecordType* RSExportFunc::getParamPacketType() const {
+    /* Pack parameters */
+    if((mParamPacketType == NULL) && hasParam()) {
+        int Index = 0;
+        RSExportRecordType* ParamPacketType = new RSExportRecordType(mContext, "", false /* IsPacked */, true /* IsArtificial */);
+
+        for(const_param_iterator PI = params_begin();
+            PI != params_end();
+            PI++, Index++)
+            ParamPacketType->mFields.push_back( new RSExportRecordType::Field((*PI)->getType(), (*PI)->getName(), ParamPacketType, Index) );
+
+        mParamPacketType = ParamPacketType;
+    }
+
+    return mParamPacketType;
+}
+
+RSExportFunc::~RSExportFunc() {
+    for(const_param_iterator PI = params_begin();
+        PI != params_end();
+        PI++)
+        delete *PI;
+
+    if(mParamPacketType != NULL)
+        delete mParamPacketType;
+    
+    return;
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_export_func.hpp b/slang_rs_export_func.hpp
new file mode 100644
index 0000000..d78b7c9
--- /dev/null
+++ b/slang_rs_export_func.hpp
@@ -0,0 +1,78 @@
+#ifndef _SLANG_COMPILER_RS_EXPORT_FUNC_HPP
+#   define _SLANG_COMPILER_RS_EXPORT_FUNC_HPP
+
+#include "llvm/ADT/StringRef.h"     /* for class llvm::StringRef */
+
+#include <list>
+#include <string>
+
+namespace clang {
+    class FunctionDecl;
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+class RSContext;
+class RSExportType;
+class RSExportRecordType;
+
+class RSExportFunc {
+    friend class RSContext;
+public:
+    class Parameter {
+    private:
+        RSExportType* mType;
+        std::string mName;
+    
+    public:
+        Parameter(RSExportType* T, const llvm::StringRef& Name) :
+            mType(T),
+            mName(Name.data(), Name.size())
+        {
+            return;
+        }
+
+        inline const RSExportType* getType() const { return mType; }
+        inline const std::string& getName() const { return mName; }
+    };
+
+private:
+    RSContext* mContext;
+    std::string mName;
+    std::list<const Parameter*> mParams;
+    mutable RSExportRecordType* mParamPacketType;
+
+    RSExportFunc(RSContext* Context, const llvm::StringRef& Name) :
+        mContext(Context),
+        mName(Name.data(), Name.size()),
+        mParamPacketType(NULL)
+    {
+        return;
+    }
+
+public:
+    static RSExportFunc* Create(RSContext* Context, const FunctionDecl* FD);
+
+    typedef std::list<const Parameter*>::const_iterator const_param_iterator;
+
+    inline const_param_iterator params_begin() const { return this->mParams.begin(); }
+    inline const_param_iterator params_end() const { return this->mParams.end(); }
+
+    inline const std::string& getName() const { return mName; }
+    inline RSContext* getRSContext() const { return mContext; }
+
+    inline bool hasParam() const { return !mParams.empty(); }
+    inline int getNumParameters() const { return mParams.size(); }
+
+    const RSExportRecordType* getParamPacketType() const;
+
+    ~RSExportFunc();
+
+};  /* RSExportFunc */
+
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_RS_EXPORT_FUNC_HPP */
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
new file mode 100644
index 0000000..f8ec2e7
--- /dev/null
+++ b/slang_rs_export_type.cpp
@@ -0,0 +1,642 @@
+#include <vector>
+
+#include "slang_rs_context.hpp"
+#include "slang_rs_export_type.hpp"
+#include "slang_rs_export_element.hpp"
+
+#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
+
+#include "llvm/ADT/StringExtras.h"  /* for function llvm::utostr_32() */
+#include "llvm/Target/TargetData.h" /* for class llvm::TargetData and class llvm::StructLayout */
+
+namespace slang {
+
+/****************************** RSExportType ******************************/
+bool RSExportType::NormalizeType(const Type*& T, llvm::StringRef& TypeName) {
+    llvm::SmallPtrSet<const Type*, 8> SPS = llvm::SmallPtrSet<const Type*, 8>();
+
+    if((T = RSExportType::TypeExportable(T, SPS)) == NULL) 
+        /* TODO: warning the user: type not exportable */
+        return false;
+
+    /* Get type name */
+    TypeName = RSExportType::GetTypeName(T);
+    if(TypeName.empty())
+        /* TODO: warning the user: the type is unnmaed */
+        return false;
+
+    return true;
+}
+
+const Type* RSExportType::GetTypeOfDecl(const DeclaratorDecl* DD) {
+    if(DD && DD->getTypeSourceInfo()) {
+        QualType T = DD->getTypeSourceInfo()->getType();
+        if(T.isNull())
+            return NULL;
+        else
+            return T.getTypePtr();
+    }
+}
+
+llvm::StringRef RSExportType::GetTypeName(const Type* T) {
+    T = GET_CANONICAL_TYPE(T);
+    if(T == NULL)
+        return llvm::StringRef();
+
+    switch(T->getTypeClass()) {
+        case Type::Builtin:
+        {
+            const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
+
+            switch(BT->getKind()) {
+#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
+                case builtin_type:  \
+                    /* Compiler is smart enough to optimize following *big if branches* since they all become "constant comparison" after macro expansion */  \
+                    if(type == RSExportPrimitiveType::DataTypeFloat32) return "float";  \
+                    else if(type == RSExportPrimitiveType::DataTypeUnsigned8) return "uchar";   \
+                    else if(type == RSExportPrimitiveType::DataTypeUnsigned16) return "ushort"; \
+                    else if(type == RSExportPrimitiveType::DataTypeUnsigned32) return "uint";   \
+                    else if(type == RSExportPrimitiveType::DataTypeSigned8) return "char";  \
+                    else if(type == RSExportPrimitiveType::DataTypeSigned16) return "short";    \
+                    else if(type == RSExportPrimitiveType::DataTypeSigned32) return "int";  \
+                    else assert(false && "Unknow data type of supported builtin");  \
+                break;
+#include "slang_rs_export_type_support.inc"
+
+                default: assert(false && "Unknow data type of the builtin"); break;
+            }
+        }
+        break;
+
+        case Type::Record:
+        {
+            const RecordDecl* RD = T->getAsStructureType()->getDecl();
+            llvm::StringRef Name = RD->getName();
+            if(Name.empty()) {
+                if(RD->getTypedefForAnonDecl() != NULL) 
+                    Name = RD->getTypedefForAnonDecl()->getName();
+
+                if(Name.empty())
+                    /* Try to find a name from redeclaration (i.e. typedef) */
+                    for(TagDecl::redecl_iterator RI = RD->redecls_begin();
+                        RI != RD->redecls_end();
+                        RI++)
+                    {
+                        assert(*RI != NULL && "cannot be NULL object");
+
+                        Name = (*RI)->getName();
+                        if(!Name.empty())
+                            break;
+                    }
+            }
+            return Name;
+        }
+        break;
+
+        case Type::Pointer:
+        {
+            /* "*" plus pointee name */
+            const Type* PT = GET_POINTEE_TYPE(T);
+            llvm::StringRef PointeeName;
+            if(NormalizeType(PT, PointeeName)) {
+                char* Name = new char[ 1 /* * */ + PointeeName.size() ];
+                Name[0] = '*';
+                memcpy(Name + 1, PointeeName.data(), PointeeName.size());
+                return Name;
+            }
+        }
+        break;
+
+        case Type::ExtVector:
+        {
+            const ExtVectorType* EVT = UNSAFE_CAST_TYPE(ExtVectorType, T);
+            return RSExportVectorType::GetTypeName(EVT);
+        }
+        break;
+
+        default:
+        break;
+    }
+
+    return llvm::StringRef();
+}
+
+const Type* RSExportType::TypeExportable(const Type* T, llvm::SmallPtrSet<const Type*, 8>& SPS) {
+    /* Normailize first */
+    if((T = GET_CANONICAL_TYPE(T)) == NULL)
+        return NULL;
+
+    if(SPS.count(T))
+        return T;
+        
+    switch(T->getTypeClass()) {
+        case Type::Builtin:
+        {
+            const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
+
+            switch(BT->getKind()) {
+#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
+                case builtin_type:
+#include "slang_rs_export_type_support.inc"
+                    return T;
+                break;
+
+                default:
+                    return NULL;
+                break;
+            }
+        }
+        break;
+
+        case Type::Record:
+        {
+            if(RSExportPrimitiveType::GetRSObjectType(T) != RSExportPrimitiveType::DataTypeUnknown)
+                return T; /* RS object type, no further checks are needed */
+
+            /* Check internal struct */
+            const RecordDecl* RD = T->getAsStructureType()->getDecl();
+            if(RD != NULL)
+                RD = RD->getDefinition();
+
+            /* Fast check */
+            if(RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 
+                return NULL;
+            
+            /* Insert myself into checking set */
+            SPS.insert(T);
+
+            /* Check all element */
+            for(RecordDecl::field_iterator F = RD->field_begin();
+                F != RD->field_end();
+                F++)
+            {
+                const Type* FT = GetTypeOfDecl(*F);
+                FT = GET_CANONICAL_TYPE(FT);
+
+                if(!TypeExportable(FT, SPS)) 
+                    /*  TODO: warning: unsupported field type */
+                    return NULL;
+            }
+
+            return T;
+        }
+        break;
+
+        case Type::Pointer:
+        {
+            const PointerType* PT = UNSAFE_CAST_TYPE(PointerType, T);
+            const Type* PointeeType = GET_POINTEE_TYPE(PT);
+
+            if((PointeeType->getTypeClass() != Type::Pointer) && (TypeExportable(PointeeType, SPS) == NULL) )
+                return NULL;
+            return T;
+        }
+        break;
+
+        case Type::ExtVector:
+        {
+            const ExtVectorType* EVT = UNSAFE_CAST_TYPE(ExtVectorType, T);
+            /* Check element numbers */
+            if(EVT->getNumElements() < 2 || EVT->getNumElements() > 4)  /* only support vector with size 2, 3 and 4 */
+                return NULL;
+
+            /* Check base element type */
+            const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
+
+            if((ElementType->getTypeClass() != Type::Builtin) || (TypeExportable(ElementType, SPS) == NULL))
+                return NULL;
+            return T;
+        }
+        break;
+
+        default:
+            return NULL;
+        break;
+    }
+}
+
+RSExportType* RSExportType::Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName) {
+    /* 
+     * Lookup the context to see whether the type was processed before. 
+     *  Newly create RSExportType will insert into context in RSExportType::RSExportType() 
+     */
+    RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
+
+    if(ETI != Context->export_types_end()) 
+        return ETI->second;
+
+    RSExportType* ET = NULL;
+    switch(T->getTypeClass()) {
+        case Type::Record:
+            if(RSExportPrimitiveType::GetRSObjectType(TypeName) != RSExportPrimitiveType::DataTypeUnknown)
+                ET = RSExportPrimitiveType::Create(Context, T, TypeName);
+            else
+                ET = RSExportRecordType::Create(Context, T->getAsStructureType(), TypeName);
+        break;
+
+        case Type::Builtin:
+            ET = RSExportPrimitiveType::Create(Context, T, TypeName);
+        break;
+
+        case Type::Pointer:
+            ET = RSExportPointerType::Create(Context, UNSAFE_CAST_TYPE(PointerType, T), TypeName);
+            /* free the name (allocated in RSExportType::GetTypeName) */
+            delete [] TypeName.data();
+        break;
+
+        case Type::ExtVector:
+            ET = RSExportVectorType::Create(Context, UNSAFE_CAST_TYPE(ExtVectorType, T), TypeName);
+        break;
+
+        default:
+            /* TODO: warning: type is not exportable */
+            printf("RSExportType::Create : type '%s' is not exportable\n", T->getTypeClassName());
+        break;
+    }
+
+    return ET;
+}
+    
+RSExportType* RSExportType::Create(RSContext* Context, const Type* T) {
+    llvm::StringRef TypeName;
+    if(NormalizeType(T, TypeName))
+        return Create(Context, T, TypeName);
+    else
+        return NULL;
+}
+
+RSExportType* RSExportType::CreateFromDecl(RSContext* Context, const VarDecl* VD) {
+    return RSExportType::Create(Context, GetTypeOfDecl(VD));
+}
+
+size_t RSExportType::GetTypeStoreSize(const RSExportType* ET) {
+    return ET->getRSContext()->getTargetData()->getTypeStoreSize(ET->getLLVMType());
+}
+
+size_t RSExportType::GetTypeAllocSize(const RSExportType* ET) {
+    return ET->getRSContext()->getTargetData()->getTypeAllocSize(ET->getLLVMType());
+}
+
+RSExportType::RSExportType(RSContext* Context, const llvm::StringRef& Name) : 
+    mContext(Context), 
+    mName(Name.data(), Name.size()), /* make a copy on Name since data of @Name which is stored in ASTContext will be destroyed later */ 
+    mLLVMType(NULL)
+{   
+    /* TODO: need to check whether the insertion is successful or not */
+    Context->insertExportType(Name, this);
+    return; 
+}
+
+/****************************** RSExportPrimitiveType ******************************/
+RSExportPrimitiveType::RSObjectTypeMapTy* RSExportPrimitiveType::RSObjectTypeMap = NULL;
+llvm::Type* RSExportPrimitiveType::RSObjectLLVMType = NULL;
+
+bool RSExportPrimitiveType::IsPrimitiveType(const Type* T) {
+    if((T != NULL) && (T->getTypeClass() == Type::Builtin))
+        return true;
+    else
+        return false;
+}
+
+RSExportPrimitiveType::DataType RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef& TypeName) {
+    if(TypeName.empty())
+        return DataTypeUnknown;
+
+    if(RSObjectTypeMap == NULL) {
+        RSObjectTypeMap = new RSObjectTypeMapTy(16);
+
+#define USE_ELEMENT_DATA_TYPE
+#define DEF_RS_OBJECT_TYPE(type, name)  \
+        RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type));
+#include "slang_rs_export_element_support.inc"
+    }
+
+    RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
+    if(I == RSObjectTypeMap->end())
+        return DataTypeUnknown;
+    else
+        return I->getValue();
+}
+
+RSExportPrimitiveType::DataType RSExportPrimitiveType::GetRSObjectType(const Type* T) {
+    T = GET_CANONICAL_TYPE(T);
+    if((T == NULL) || (T->getTypeClass() != Type::Record))
+        return DataTypeUnknown;
+
+    return GetRSObjectType( RSExportType::GetTypeName(T) );
+}
+
+const size_t RSExportPrimitiveType::SizeOfDataTypeInBytes[RSExportPrimitiveType::DataTypeMax + 1] = {
+    0,
+    2, /* DataTypeFloat16 */
+    4, /* DataTypeFloat32 */ 
+    8, /* DataTypeFloat64 */ 
+    1, /* DataTypeSigned8 */ 
+    2, /* DataTypeSigned16 */ 
+    4, /* DataTypeSigned32 */ 
+    8, /* DataTypeSigned64 */ 
+    1, /* DataTypeUnsigned8 */ 
+    2, /* DataTypeUnsigned16 */ 
+    4, /* DataTypeUnsigned32 */ 
+    8, /* DataTypeUnSigned64 */ 
+
+    2, /* DataTypeUnsigned565 */
+    2, /* DataTypeUnsigned5551 */
+    2, /* DataTypeUnsigned4444 */
+
+    4, /* DataTypeRSElement */
+    4, /* DataTypeRSType */
+    4, /* DataTypeRSAllocation */
+    4, /* DataTypeRSSampler */
+    4, /* DataTypeRSScript */
+    4, /* DataTypeRSMesh */
+    4, /* DataTypeRSProgramFragment */
+    4, /* DataTypeRSProgramVertex */
+    4, /* DataTypeRSProgramRaster */
+    4, /* DataTypeRSProgramStore */       
+    0
+};
+
+size_t RSExportPrimitiveType::GetSizeInBytes(const RSExportPrimitiveType* EPT) {
+    assert(((EPT->getType() >= DataTypeFloat32) && (EPT->getType() < DataTypeMax)) && "RSExportPrimitiveType::GetSizeInBytes : unknown data type");
+    return SizeOfDataTypeInBytes[ static_cast<int>(EPT->getType()) ];
+}
+
+RSExportPrimitiveType::DataType RSExportPrimitiveType::GetDataType(const Type* T) {
+    if(T == NULL)
+        return DataTypeUnknown;
+
+    switch(T->getTypeClass()) {
+        case Type::Builtin:
+        {
+            const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
+            switch(BT->getKind()) {
+#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
+                case builtin_type:  \
+                    return type;  \
+                break;
+#include "slang_rs_export_type_support.inc"
+
+                /* The size of types Long, ULong and WChar depend on platform so we abandon the support to them */
+                /* Type of its size exceeds 32 bits (e.g. int64_t, double, etc.) does not support */
+
+                default:
+                    /* TODO: warning the user: unsupported type */
+                    printf("RSExportPrimitiveType::GetDataType : built-in type has no corresponding data type for built-in type");
+                break;
+            }
+        }
+        break;
+
+        case Type::Record:
+            /* must be RS object type */
+            return RSExportPrimitiveType::GetRSObjectType(T);
+        break;
+
+        default:
+            printf("RSExportPrimitiveType::GetDataType : type '%s' is not supported primitive type", T->getTypeClassName());
+        break;
+    }
+
+    return DataTypeUnknown;
+}
+
+RSExportPrimitiveType* RSExportPrimitiveType::Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
+    DataType DT = GetDataType(T);
+
+    if((DT == DataTypeUnknown) || TypeName.empty())
+        return NULL;
+    else
+        return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
+}
+
+RSExportPrimitiveType* RSExportPrimitiveType::Create(RSContext* Context, const Type* T, DataKind DK) {
+    llvm::StringRef TypeName;
+    if(RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
+        return Create(Context, T, TypeName, DK);
+    else
+        return NULL;
+}
+
+RSExportType::ExportClass RSExportPrimitiveType::getClass() const { 
+    return RSExportType::ExportClassPrimitive; 
+}
+
+const llvm::Type* RSExportPrimitiveType::convertToLLVMType() const {
+    llvm::LLVMContext& C = getRSContext()->getLLVMContext();
+
+    if(isRSObjectType()) {
+        /* struct { int* p; } __attribute__((packed, aligned(pointer_size))) which is <{ [1 x i32] }> in LLVM */
+        if(RSObjectLLVMType == NULL) {
+            std::vector<const llvm::Type*> Elements;
+            Elements.push_back( llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1) );
+            RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
+        }
+        return RSObjectLLVMType;
+    }
+
+    switch(mType) {
+        case DataTypeFloat32: 
+            return llvm::Type::getFloatTy(C); 
+        break;
+
+        case DataTypeSigned8:
+        case DataTypeUnsigned8:
+            return llvm::Type::getInt8Ty(C); 
+        break;
+
+        case DataTypeSigned16:
+        case DataTypeUnsigned16:
+        case DataTypeUnsigned565:
+        case DataTypeUnsigned5551:
+        case DataTypeUnsigned4444:
+            return llvm::Type::getInt16Ty(C); 
+        break;
+
+        case DataTypeSigned32:
+        case DataTypeUnsigned32:
+            return llvm::Type::getInt32Ty(C); 
+        break;
+
+        default:
+            assert(false && "Unknown data type");
+        break;
+    }
+
+    return NULL;
+}
+
+/****************************** RSExportPointerType ******************************/
+
+const Type* RSExportPointerType::IntegerType = NULL;
+
+RSExportPointerType* RSExportPointerType::Create(RSContext* Context, const PointerType* PT, const llvm::StringRef& TypeName) {
+    const Type* PointeeType = GET_POINTEE_TYPE(PT);
+    const RSExportType* PointeeET;
+
+    if(PointeeType->getTypeClass() != Type::Pointer) {
+        PointeeET = RSExportType::Create(Context, PointeeType);
+    } else {
+        /* Double or higher dimension of pointer, export as int* */
+        assert(IntegerType != NULL && "Built-in integer type is not set");
+        PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
+    }
+
+    if(PointeeET == NULL) {
+        printf("Failed to create type for pointee");
+        return NULL;
+    }
+
+    return new RSExportPointerType(Context, TypeName, PointeeET);
+}
+
+RSExportType::ExportClass RSExportPointerType::getClass() const { 
+    return RSExportType::ExportClassPointer;
+}
+
+const llvm::Type* RSExportPointerType::convertToLLVMType() const {
+    const llvm::Type* PointeeType = mPointeeType->getLLVMType();
+    return llvm::PointerType::getUnqual(PointeeType);
+}
+
+/****************************** RSExportVectorType ******************************/
+const char* RSExportVectorType::VectorTypeNameStore[][3] = { 
+    /* 0 */ { "char2",      "char3",    "char4" },
+    /* 1 */ { "uchar2",     "uchar3",   "uchar4" },
+    /* 2 */ { "short2",     "short3",   "short4" },
+    /* 3 */ { "ushort2",    "ushort3",  "ushort4" },
+    /* 4 */ { "int2",       "int3",     "int4" },
+    /* 5 */ { "uint2",      "uint3",    "uint4" },
+    /* 6 */ { "float2",     "float3",   "float4" },
+};  
+
+llvm::StringRef RSExportVectorType::GetTypeName(const ExtVectorType* EVT) {
+    const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
+
+    if((ElementType->getTypeClass() != Type::Builtin))
+        return llvm::StringRef();
+
+    const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, ElementType);
+    const char** BaseElement = NULL;
+
+    switch(BT->getKind()) {
+#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
+        case builtin_type:  \
+            /* Compiler is smart enough to optimize following *big if branches* since they all become "constant comparison" after macro expansion */  \
+            if(type == RSExportPrimitiveType::DataTypeSigned8) BaseElement = VectorTypeNameStore[0];    \
+            else if(type == RSExportPrimitiveType::DataTypeUnsigned8) BaseElement = VectorTypeNameStore[1]; \
+            else if(type == RSExportPrimitiveType::DataTypeSigned16) BaseElement = VectorTypeNameStore[2];  \
+            else if(type == RSExportPrimitiveType::DataTypeUnsigned16) BaseElement = VectorTypeNameStore[3];    \
+            else if(type == RSExportPrimitiveType::DataTypeSigned32) BaseElement = VectorTypeNameStore[4];  \
+            else if(type == RSExportPrimitiveType::DataTypeUnsigned32) BaseElement = VectorTypeNameStore[5];    \
+            else if(type == RSExportPrimitiveType::DataTypeFloat32) BaseElement = VectorTypeNameStore[6];   \
+        break;
+#include "slang_rs_export_type_support.inc"
+
+        default: return llvm::StringRef(); break;
+    }
+
+    if((BaseElement != NULL) && (EVT->getNumElements() > 1) && (EVT->getNumElements() <= 4))
+        return BaseElement[EVT->getNumElements() - 2];
+    else
+        return llvm::StringRef();
+}
+
+RSExportVectorType* RSExportVectorType::Create(RSContext* Context, const ExtVectorType* EVT, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
+    assert(EVT != NULL && EVT->getTypeClass() == Type::ExtVector);
+
+    const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
+    RSExportPrimitiveType::DataType DT = RSExportPrimitiveType::GetDataType(ElementType);
+
+    if(DT != RSExportPrimitiveType::DataTypeUnknown) 
+        return new RSExportVectorType(Context, TypeName, DT, DK, Normalized, EVT->getNumElements());
+    else
+        printf("RSExportVectorType::Create : unsupported base element type\n");
+}
+
+RSExportType::ExportClass RSExportVectorType::getClass() const { 
+    return RSExportType::ExportClassVector; 
+}
+
+const llvm::Type* RSExportVectorType::convertToLLVMType() const {
+    const llvm::Type* ElementType = RSExportPrimitiveType::convertToLLVMType();
+    return llvm::VectorType::get(ElementType, getNumElement());
+}
+
+/****************************** RSExportRecordType ******************************/
+RSExportRecordType* RSExportRecordType::Create(RSContext* Context, const RecordType* RT, const llvm::StringRef& TypeName, bool mIsArtificial) {
+    assert(RT != NULL && RT->getTypeClass() == Type::Record);
+
+    const RecordDecl* RD = RT->getDecl();
+    assert(RD->isStruct());
+
+    RD = RD->getDefinition();
+    if(RD == NULL) {
+        /* TODO: warning: actual struct definition isn't declared in this moudle */
+        printf("RSExportRecordType::Create : this struct is not defined in this module.");
+        return NULL;
+    }
+
+    RSExportRecordType* ERT = new RSExportRecordType(Context, TypeName, RD->hasAttr<PackedAttr>(), mIsArtificial);
+    unsigned int Index = 0;
+
+    for(RecordDecl::field_iterator fit = RD->field_begin();
+        fit != RD->field_end();
+        fit++, Index++)
+    {
+#define FAILED_CREATE_FIELD(err)    do {    \
+                                        if(*err) \
+                                            printf("RSExportRecordType::Create : failed to create field (%s)\n", err);   \
+                                        delete ERT;  \
+                                        return NULL;    \
+                                    } while(false)
+        /* FIXME: All fields should be primitive type */
+        assert((*fit)->getKind() == Decl::Field);
+        FieldDecl* FD = *fit;
+
+        /* We don't support bit field TODO: allow bitfield with size 8, 16, 32 */
+        if(FD->isBitField())
+            FAILED_CREATE_FIELD("bit field is not supported");
+
+        /* Type */
+        RSExportType* ET = RSExportElement::CreateFromDecl(Context, FD);
+
+        if(ET != NULL)
+            ERT->mFields.push_back( new Field(ET, FD->getName(), ERT, Index) );
+        else
+            FAILED_CREATE_FIELD(FD->getName().str().c_str());
+#undef FAILED_CREATE_FIELD
+    }
+
+    return ERT;
+}
+
+RSExportType::ExportClass RSExportRecordType::getClass() const {
+    return RSExportType::ExportClassRecord;
+}
+
+const llvm::Type* RSExportRecordType::convertToLLVMType() const {
+    std::vector<const llvm::Type*> FieldTypes;
+
+    for(const_field_iterator FI = fields_begin();
+        FI != fields_end();
+        FI++)
+    {
+        const Field* F = *FI;
+        const RSExportType* FET = F->getType();
+        
+        FieldTypes.push_back(FET->getLLVMType());
+    }
+
+    return llvm::StructType::get(getRSContext()->getLLVMContext(), FieldTypes, mIsPacked);
+}
+
+/****************************** RSExportRecordType::Field ******************************/
+size_t RSExportRecordType::Field::getOffsetInParent() const {
+    /* Struct layout obtains below will be cached by LLVM */
+    const llvm::StructLayout* SL = mParent->getRSContext()->getTargetData()->getStructLayout(static_cast<const llvm::StructType*>(mParent->getLLVMType()));
+    return SL->getElementOffset(mIndex);
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_export_type.hpp b/slang_rs_export_type.hpp
new file mode 100644
index 0000000..152a541
--- /dev/null
+++ b/slang_rs_export_type.hpp
@@ -0,0 +1,347 @@
+#ifndef _SLANG_COMPILER_RS_EXPORT_TYPE_HPP
+#   define _SLANG_COMPILER_RS_EXPORT_TYPE_HPP
+
+#include <set>
+#include <list>
+#include <string>
+
+#include "llvm/ADT/StringRef.h"     /* for class llvm::StringRef */
+#include "llvm/ADT/StringMap.h"     /* for class llvm::StringMap */
+#include "llvm/ADT/SmallPtrSet.h"   /* for class llvm::SmallPtrSet */
+
+#include "clang/AST/Type.h"         /* for clang::Type and clang::QualType */
+#include "clang/AST/Decl.h"         /* for clang::VarDecl and clang::DeclaratorDecl */
+
+#define GET_CANONICAL_TYPE(T)   (((T) == NULL) ? NULL : (T)->getCanonicalTypeInternal().getTypePtr()) 
+#define UNSAFE_CAST_TYPE(TT, T) static_cast<TT*>(T->getCanonicalTypeInternal().getTypePtr())
+#define GET_EXT_VECTOR_ELEMENT_TYPE(T)  (((T) == NULL) ? NULL : GET_CANONICAL_TYPE((T)->getElementType().getTypePtr()))
+#define GET_POINTEE_TYPE(T) (((T) == NULL) ? NULL : GET_CANONICAL_TYPE((T)->getPointeeType().getTypePtr()))
+
+namespace llvm {
+    class Type;
+}   /* namespace llvm */
+
+namespace slang {
+
+class RSContext;
+class RSExportPrimitiveType;
+class RSExportVectorType;
+class RSExportRecordType;
+class RSExportFunction;
+
+using namespace clang;
+
+class RSExportType {
+    friend class RSExportElement;
+public:
+    typedef enum {
+        ExportClassPrimitive,
+        ExportClassPointer,
+        ExportClassVector,
+        ExportClassRecord
+    } ExportClass;
+
+private:
+    RSContext* mContext;
+    std::string mName;
+
+    mutable const llvm::Type* mLLVMType;  /* Cache the result after calling convertToLLVMType() at the first time */
+
+protected:
+    RSExportType(RSContext* Context, const llvm::StringRef& Name);
+
+    /* 
+     * Let's make it private since there're some prerequisites to call this function.
+     *
+     * @T was normalized by calling RSExportType::TypeExportable(). 
+     * @TypeName was retrieve from RSExportType::GetTypeName() before calling this.
+     */
+    static RSExportType* Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName);
+
+    static llvm::StringRef GetTypeName(const Type* T);
+    /* Return the type that can be used to create RSExportType, will always return the canonical type */
+    static const Type* TypeExportable(const Type* T, llvm::SmallPtrSet<const Type*, 8>& SPS /* contain the checked type for recursion */);
+
+    /* This function convert the RSExportType to LLVM type. Actually, it should be "convert Clang type to LLVM type." 
+     *  However, clang doesn't make this API (lib/CodeGen/CodeGenTypes.h) public, we need to do by ourselves.
+     *
+     * Once we can get LLVM type, we can use LLVM to get alignment information, allocation size of a given type and structure
+     *  layout that LLVM used (all of these information are target dependent) without deal with these by ourselves.
+     */
+    virtual const llvm::Type* convertToLLVMType() const = 0;
+
+public:
+    static bool NormalizeType(const Type*& T, llvm::StringRef& TypeName);
+    /* @T may not be normalized */
+    static RSExportType* Create(RSContext* Context, const Type* T);
+    static RSExportType* CreateFromDecl(RSContext* Context, const VarDecl* VD);
+
+    static const Type* GetTypeOfDecl(const DeclaratorDecl* DD);
+
+    virtual ExportClass getClass() const = 0;
+
+    inline const llvm::Type* getLLVMType() const {
+        if(mLLVMType == NULL)
+            mLLVMType = convertToLLVMType();
+        return mLLVMType;
+    }
+
+    /* Return the number of bits necessary to hold the specified RSExportType */
+    static size_t GetTypeStoreSize(const RSExportType* ET);
+
+    /* The size of allocation of specified RSExportType (alignment considered) */
+    static size_t GetTypeAllocSize(const RSExportType* ET);
+
+    const std::string& getName() const { return mName; }
+    inline RSContext* getRSContext() const { return mContext; }
+};  /* RSExportType */
+
+/* Primitive types */
+class RSExportPrimitiveType : public RSExportType {
+    friend class RSExportType;
+    friend class RSExportElement;
+public:
+    /* From graphics/java/android/renderscript/Element.java: Element.DataType */
+    typedef enum {
+        DataTypeUnknown = -1,
+
+        //DataTypeFloat16 = 1,
+        DataTypeFloat32 = 2, 
+        //DataTypeFloat64 = 3, 
+        DataTypeSigned8 = 4, 
+        DataTypeSigned16 = 5, 
+        DataTypeSigned32 = 6, 
+        //DataTypeSigned64 = 7, 
+        DataTypeUnsigned8 = 8, 
+        DataTypeUnsigned16 = 9, 
+        DataTypeUnsigned32 = 10, 
+        //DataTypeUnSigned64 = 11, 
+
+        DataTypeUnsigned565 = 12,
+        DataTypeUnsigned5551 = 13,
+        DataTypeUnsigned4444 = 14,
+
+        DataTypeRSElement = 15,
+        DataTypeRSType = 16,
+        DataTypeRSAllocation = 17,
+        DataTypeRSSampler = 18,
+        DataTypeRSScript = 19,
+        DataTypeRSMesh = 20,
+        DataTypeRSProgramFragment = 21,
+        DataTypeRSProgramVertex = 22,
+        DataTypeRSProgramRaster = 23,
+        DataTypeRSProgramStore = 24,       
+
+        DataTypeMax
+    } DataType;
+
+    /* From graphics/java/android/renderscript/Element.java: Element.DataKind */
+    typedef enum {
+        DataKindUser = 0, 
+        DataKindColor = 1,
+        DataKindPosition = 2,
+        DataKindTexture = 3,
+        DataKindNormal = 4,
+        DataKindIndex = 5,
+        DataKindPointSize = 6,
+        DataKindPixelL = 7,
+        DataKindPixelA = 8,
+        DataKindPixelLA = 9,
+        DataKindPixelRGB = 10,
+        DataKindPixelRGBA = 11
+    } DataKind;
+
+private:
+    DataType mType;
+    DataKind mKind;
+    bool mNormalized;
+
+    typedef llvm::StringMap<DataType> RSObjectTypeMapTy;
+    static RSObjectTypeMapTy* RSObjectTypeMap;
+
+    static llvm::Type* RSObjectLLVMType;
+
+    static const size_t SizeOfDataTypeInBytes[];
+    /* 
+     * @T was normalized by calling RSExportType::TypeExportable() before calling this. 
+     * @TypeName was retrieved from RSExportType::GetTypeName() before calling this 
+     */
+    static RSExportPrimitiveType* Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName, DataKind DK = DataKindUser, bool Normalized = false);
+
+protected:
+    /* T is normalized by calling RSExportType::TypeExportable() before calling this */
+    static bool IsPrimitiveType(const Type* T);
+
+    static DataType GetDataType(const Type* T);
+
+    RSExportPrimitiveType(RSContext* Context, const llvm::StringRef& Name, DataType DT, DataKind DK, bool Normalized) :
+        RSExportType(Context, Name),
+        mType(DT),
+        mKind(DK),
+        mNormalized(Normalized)
+    {
+        return;
+    }
+
+    virtual const llvm::Type* convertToLLVMType() const;
+public:
+    /* @T may not be normalized */
+    static RSExportPrimitiveType* Create(RSContext* Context, const Type* T, DataKind DK = DataKindUser);
+
+    static DataType GetRSObjectType(const llvm::StringRef& TypeName);
+    static DataType GetRSObjectType(const Type* T);
+
+    static size_t GetSizeInBytes(const RSExportPrimitiveType* EPT);
+
+    virtual ExportClass getClass() const;
+
+    inline DataType getType() const { return mType; }
+    inline DataKind getKind() const { return mKind; }
+    inline bool isRSObjectType() const { return ((mType >= DataTypeRSElement) && (mType <= DataTypeRSProgramStore)); }
+};  /* RSExportPrimitiveType */
+
+
+class RSExportPointerType : public RSExportType {
+    friend class RSExportType;
+    friend class RSExportElement;
+private:
+    const RSExportType* mPointeeType;
+
+    RSExportPointerType(RSContext* Context,
+                        const llvm::StringRef& Name, 
+                        const RSExportType* PointeeType) :
+        RSExportType(Context, Name), 
+        mPointeeType(PointeeType)
+    {
+        return;
+    }
+
+    /* 
+     * @PT was normalized by calling RSExportType::TypeExportable() before calling this. 
+     */
+    static RSExportPointerType* Create(RSContext* Context, const PointerType* PT, const llvm::StringRef& TypeName);
+
+    virtual const llvm::Type* convertToLLVMType() const;
+public:
+    static const Type* IntegerType;
+
+    virtual ExportClass getClass() const;
+
+    inline const RSExportType* getPointeeType() const { return mPointeeType; }
+};  /* RSExportPointerType */
+
+
+class RSExportVectorType : public RSExportPrimitiveType {
+    friend class RSExportType;
+    friend class RSExportElement;
+
+private:
+    int mNumElement;   /* number of element */
+
+    RSExportVectorType(RSContext* Context,
+                       const llvm::StringRef& Name, 
+                       DataType DT, 
+                       DataKind DK, 
+                       bool Normalized,
+                       int NumElement) : 
+        RSExportPrimitiveType(Context, Name, DT, DK, Normalized),
+        mNumElement(NumElement)
+    {
+        return;
+    }
+
+    /* 
+     * @EVT was normalized by calling RSExportType::TypeExportable() before calling this. 
+     */
+    static RSExportVectorType* Create(RSContext* Context, const ExtVectorType* EVT, const llvm::StringRef& TypeName, DataKind DK = DataKindUser, bool Normalized = false);
+
+    static const char* VectorTypeNameStore[][3];
+
+    virtual const llvm::Type* convertToLLVMType() const;
+public:
+    static llvm::StringRef GetTypeName(const ExtVectorType* EVT);
+
+    virtual ExportClass getClass() const;
+
+    inline int getNumElement() const { return mNumElement; }
+};
+
+class RSExportRecordType : public RSExportType {
+    friend class RSExportType;
+    friend class RSExportElement;
+    friend class RSExportFunc;
+public:
+    class Field {
+    private:
+        /* Link to the struct that contain this field */
+        const RSExportRecordType* mParent;
+        /* Index in the container */
+        unsigned int mIndex;
+        const RSExportType* mType;
+        /* Field name */
+        std::string mName;
+
+    public:
+        Field(const RSExportType* T, const llvm::StringRef& Name, const RSExportRecordType* Parent, unsigned int Index) : 
+            mType(T), 
+            mName(Name.data(), Name.size()),
+            mParent(Parent),
+            mIndex(Index)
+        {
+            return;
+        }
+
+        inline const RSExportRecordType* getParent() const { return mParent; }
+        inline unsigned int getIndex() const { return mIndex; }
+        inline const RSExportType* getType() const { return mType; }
+        inline const std::string& getName() const { return mName; }
+        size_t getOffsetInParent() const;
+    };
+
+    typedef std::list<const Field*>::const_iterator const_field_iterator;
+
+    inline const_field_iterator fields_begin() const { return this->mFields.begin(); }
+    inline const_field_iterator fields_end() const { return this->mFields.end(); }
+
+private:
+    std::list<const Field*> mFields;
+    bool mIsPacked;
+    bool mIsArtificial; /* Artificial export struct type is not exported by user (and thus it won't get reflected) */
+
+    RSExportRecordType(RSContext* Context, 
+                       const llvm::StringRef& Name,
+                       bool IsPacked,
+                       bool IsArtificial = false) : 
+        RSExportType(Context, Name), 
+        mIsPacked(IsPacked), 
+        mIsArtificial(IsArtificial)
+    {
+        return;
+    }
+
+    /* 
+     * @RT was normalized by calling RSExportType::TypeExportable() before calling this. 
+     * @TypeName was retrieved from RSExportType::GetTypeName() before calling this. 
+     */
+    static RSExportRecordType* Create(RSContext* Context, const RecordType* RT, const llvm::StringRef& TypeName, bool mIsArtificial = false);
+
+    virtual const llvm::Type* convertToLLVMType() const;
+public:
+    virtual ExportClass getClass() const;
+
+    inline bool isPacked() const { return mIsPacked; }
+    inline bool isArtificial() const { return mIsArtificial; }
+
+    ~RSExportRecordType() {
+        for(std::list<const Field*>::iterator it = mFields.begin();
+            it != mFields.end();
+            it++)
+            if(*it != NULL)
+                delete *it;
+        return;
+    }
+};  /* RSExportRecordType */
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_RS_EXPORT_TYPE_HPP */
diff --git a/slang_rs_export_type_support.inc b/slang_rs_export_type_support.inc
new file mode 100644
index 0000000..be857f5
--- /dev/null
+++ b/slang_rs_export_type_support.inc
@@ -0,0 +1,16 @@
+
+/* SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, bits, type) */
+#ifdef SLANG_RS_SUPPORT_BUILTIN_TYPE
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Char_U, RSExportPrimitiveType::DataTypeUnsigned8)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::UChar,  RSExportPrimitiveType::DataTypeUnsigned8)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Char_S, RSExportPrimitiveType::DataTypeSigned8)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::SChar,  RSExportPrimitiveType::DataTypeSigned8)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Char16, RSExportPrimitiveType::DataTypeSigned16)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::UShort, RSExportPrimitiveType::DataTypeUnsigned16)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Short,  RSExportPrimitiveType::DataTypeSigned16)  
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Char32, RSExportPrimitiveType::DataTypeSigned32)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::UInt,   RSExportPrimitiveType::DataTypeUnsigned32)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Int,    RSExportPrimitiveType::DataTypeSigned32)
+    SLANG_RS_SUPPORT_BUILTIN_TYPE(BuiltinType::Float,  RSExportPrimitiveType::DataTypeFloat32)
+#   undef SLANG_RS_SUPPORT_BUILTIN_TYPE
+#endif
diff --git a/slang_rs_export_var.cpp b/slang_rs_export_var.cpp
new file mode 100644
index 0000000..ece693c
--- /dev/null
+++ b/slang_rs_export_var.cpp
@@ -0,0 +1,16 @@
+#include "slang_rs_export_var.hpp"
+#include "slang_rs_export_type.hpp" /* for macro GET_CANONICAL_TYPE() */
+
+#include "clang/AST/Type.h"         /* for clang::Type and clang::QualType */
+
+namespace slang {
+
+RSExportVar::RSExportVar(RSContext* Context, const VarDecl* VD, const RSExportType* ET) :
+    mContext(Context),
+    mName(VD->getName().data(), VD->getName().size()),
+    mET(ET)
+{
+    return; 
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_export_var.hpp b/slang_rs_export_var.hpp
new file mode 100644
index 0000000..1b1cf0a
--- /dev/null
+++ b/slang_rs_export_var.hpp
@@ -0,0 +1,36 @@
+#ifndef _SLANG_COMPILER_RS_EXPORT_VAR_HPP
+#   define _SLANG_COMPILER_RS_EXPORT_VAR_HPP
+
+#include "llvm/ADT/StringRef.h"     /* for class llvm::StringRef */
+
+#include "clang/AST/Decl.h"         /* for clang::VarDecl */
+
+#include <string>
+
+namespace slang {
+
+using namespace clang;
+
+class RSContext;
+class RSExportType;
+
+class RSExportVar {
+    friend class RSContext;
+private:
+    RSContext* mContext;
+    std::string mName;
+    const RSExportType* mET;
+
+    RSExportVar(RSContext* Context, const VarDecl* VD, const RSExportType* ET);
+
+public:
+    inline const std::string& getName() const { return mName; }
+    inline const RSExportType* getType() const { return mET; }
+    inline RSContext* getRSContext() const { return mContext; }
+
+};  /* RSExportVar */
+
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_RS_EXPORT_VAR_HPP */
diff --git a/slang_rs_pragma_handler.cpp b/slang_rs_pragma_handler.cpp
new file mode 100644
index 0000000..0ef2ad8
--- /dev/null
+++ b/slang_rs_pragma_handler.cpp
@@ -0,0 +1,114 @@
+#include "slang_rs_context.hpp"
+#include "slang_rs_pragma_handler.hpp"
+
+#include "clang/Lex/Preprocessor.h"         /* for class Preprocessor */
+#include "clang/Lex/Token.h"                /* for class Token */
+#include "clang/Basic/TokenKinds.h"                /* for class Token */
+
+#include "clang/Basic/IdentifierTable.h"    /* for class IdentifierInfo */
+
+namespace {
+
+using namespace clang;
+using namespace slang;
+
+class RSExportVarPragmaHandler : public RSPragmaHandler {
+private:
+    void handleItem(const std::string& Item) {
+        mContext->addExportVar(Item);
+    }
+
+public:
+    RSExportVarPragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
+
+    void HandlePragma(Preprocessor& PP, Token& FirstToken) {
+        this->handleItemListPragma(PP, FirstToken);
+    }
+};
+
+class RSExportFuncPragmaHandler : public RSPragmaHandler {
+private:
+    void handleItem(const std::string& Item) {
+        mContext->addExportFunc(Item);
+    }
+
+public:
+    RSExportFuncPragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
+
+    void HandlePragma(Preprocessor& PP, Token& FirstToken) {
+        this->handleItemListPragma(PP, FirstToken);
+    }
+};
+
+class RSExportTypePragmaHandler : public RSPragmaHandler {
+private:
+    void handleItem(const std::string& Item) {
+        mContext->addExportType(Item);
+    }
+
+public:
+    RSExportTypePragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
+
+    void HandlePragma(Preprocessor& PP, Token& FirstToken) {
+        this->handleItemListPragma(PP, FirstToken);
+    }
+};
+
+}   /* anonymous namespace */
+
+namespace slang {
+
+RSPragmaHandler* RSPragmaHandler::CreatePragmaExportVarHandler(RSContext* Context) {
+    IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_var");
+    if(II != NULL)
+        return new RSExportVarPragmaHandler(II, Context);
+    else
+        return NULL;
+}
+
+RSPragmaHandler* RSPragmaHandler::CreatePragmaExportFuncHandler(RSContext* Context) {
+    IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_func");
+    if(II != NULL)
+        return new RSExportFuncPragmaHandler(II, Context);
+    else
+        return NULL;
+}
+
+RSPragmaHandler* RSPragmaHandler::CreatePragmaExportTypeHandler(RSContext* Context) {
+    IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_type");
+    if(II != NULL)
+        return new RSExportTypePragmaHandler(II, Context);
+    else
+        return NULL;
+}
+
+void RSPragmaHandler::handleItemListPragma(Preprocessor& PP, Token& FirstToken) {
+    Token& PragmaToken = FirstToken;
+
+    /* Skip first token, like "export_var" */
+    PP.LexUnexpandedToken(PragmaToken);
+
+    /* Now, the current token must be tok::lpara */
+    if(PragmaToken.isNot(tok::l_paren))
+        return;
+
+    while(PragmaToken.isNot(tok::eom)) {
+        /* Lex variable name */
+        PP.LexUnexpandedToken(PragmaToken);
+        if(PragmaToken.is(tok::identifier))
+            this->handleItem( PP.getSpelling(PragmaToken) );
+        else
+            break;
+
+        assert(PragmaToken.isNot(tok::eom));
+
+        PP.LexUnexpandedToken(PragmaToken);
+
+        if(PragmaToken.isNot(tok::comma))
+            break;
+    }
+    return;
+}
+
+}   /* namespace slang */
+
diff --git a/slang_rs_pragma_handler.hpp b/slang_rs_pragma_handler.hpp
new file mode 100644
index 0000000..606015b
--- /dev/null
+++ b/slang_rs_pragma_handler.hpp
@@ -0,0 +1,45 @@
+#ifndef _SLANG_COMILER_RS_PRAGMA_HANDLER_HPP
+#   define _SLANG_COMILER_RS_PRAGMA_HANDLER_HPP
+
+#include <string>
+
+#include "clang/Lex/Pragma.h"   /* for class PragmaHandler */
+
+namespace clang {
+
+class Token;
+class IdentifierInfo;
+class Preprocessor;
+
+}   /* namespace clang */
+
+namespace slang {
+
+using namespace clang;
+
+class RSContext;
+
+class RSPragmaHandler : public PragmaHandler {
+protected:
+    RSContext* mContext;
+
+    RSPragmaHandler(const IdentifierInfo* name, RSContext* Context) : PragmaHandler(name), mContext(Context) { return; }
+
+    RSContext* getContext() const { return this->mContext; }
+
+    virtual void handleItem(const std::string& Item) { return; }
+
+    /* Handle pragma like #pragma rs [name] ([item #1],[item #2],...,[item #i]) */
+    void handleItemListPragma(Preprocessor& PP, Token& FirstToken);
+
+public:
+    static RSPragmaHandler* CreatePragmaExportVarHandler(RSContext* Context);
+    static RSPragmaHandler* CreatePragmaExportFuncHandler(RSContext* Context);
+    static RSPragmaHandler* CreatePragmaExportTypeHandler(RSContext* Context);
+
+    virtual void HandlePragma(Preprocessor& PP, Token& FirstToken) = 0;
+};
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMILER_RS_PRAGMA_HANDLER_HPP */
diff --git a/slang_rs_reflection.cpp b/slang_rs_reflection.cpp
new file mode 100644
index 0000000..a6ff8df
--- /dev/null
+++ b/slang_rs_reflection.cpp
@@ -0,0 +1,1101 @@
+#include "slang_rs_context.hpp"
+#include "slang_rs_export_var.hpp"
+#include "slang_rs_reflection.hpp"
+#include "slang_rs_export_func.hpp"
+
+#include <ctype.h>
+
+#include <utility>
+#include <cstdarg>
+
+using std::make_pair;
+using std::endl;
+
+
+#define RS_SCRIPT_CLASS_NAME_PREFIX         "ScriptC_"
+#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME    "ScriptC"
+
+#define RS_TYPE_CLASS_NAME_PREFIX           "ScriptField_"
+#define RS_TYPE_CLASS_SUPER_CLASS_NAME      "android.renderscript.Script.FieldBase"
+
+#define RS_TYPE_ITEM_CLASS_NAME             "Item"
+
+#define RS_TYPE_ITEM_BUFFER_NAME            "mItemArray"
+#define RS_TYPE_ITEM_BUFFER_PACKER_NAME     "mIOBuffer"
+
+#define RS_EXPORT_VAR_INDEX_PREFIX          "mExportVarIdx_"
+#define RS_EXPORT_VAR_PREFIX                "mExportVar_"
+
+#define RS_EXPORT_FUNC_INDEX_PREFIX         "mExportFuncIdx_"
+
+#define RS_EXPORT_VAR_ALLOCATION_PREFIX     "mAlloction_"
+#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX   "mData_"
+
+namespace slang {
+
+/* Some utility function using internal in RSReflection */
+static bool GetFileNameWithoutExtension(const std::string& FileName, std::string& OutFileName) {
+    OutFileName.clear();
+
+    if(FileName.empty() || (FileName == "-"))
+        return true;
+
+    /* find last component in given path */
+    size_t SlashPos = FileName.find_last_of("/\\");
+
+    if((SlashPos != std::string::npos) && ((SlashPos + 1) < FileName.length()))
+        OutFileName = FileName.substr(SlashPos + 1);
+    else
+        OutFileName = FileName;
+
+    size_t DotPos = OutFileName.find_first_of('.');
+    if(DotPos != std::string::npos) 
+        OutFileName.erase(DotPos); 
+
+    return true;
+}
+
+static const char* GetPrimitiveTypeName(const RSExportPrimitiveType* EPT) {
+    static const char* PrimitiveTypeJavaNameMap[] = {
+        "",
+        "",
+        "float",    /* RSExportPrimitiveType::DataTypeFloat32 */
+        "double",   /* RSExportPrimitiveType::DataTypeFloat64 */
+        "byte",     /* RSExportPrimitiveType::DataTypeSigned8 */
+        "short",    /* RSExportPrimitiveType::DataTypeSigned16 */
+        "int",      /* RSExportPrimitiveType::DataTypeSigned32 */
+        "long",     /* RSExportPrimitiveType::DataTypeSigned64 */
+        "byte",     /* RSExportPrimitiveType::DataTypeUnsigned8 */
+        "short",    /* RSExportPrimitiveType::DataTypeUnsigned16 */
+        "int",      /* RSExportPrimitiveType::DataTypeUnsigned32 */
+        "long",     /* RSExportPrimitiveType::DataTypeUnsigned64 */
+
+        "short",    /* RSExportPrimitiveType::DataTypeUnsigned565 */
+        "short",    /* RSExportPrimitiveType::DataTypeUnsigned5551 */
+        "short",    /* RSExportPrimitiveType::DataTypeUnsigned4444 */
+
+        "Element",  /* RSExportPrimitiveType::DataTypeRSElement */
+        "Type",     /* RSExportPrimitiveType::DataTypeRSType */
+        "Allocation",   /* RSExportPrimitiveType::DataTypeRSAllocation */
+        "Sampler",  /* RSExportPrimitiveType::DataTypeRSSampler */
+        "Script",   /* RSExportPrimitiveType::DataTypeRSScript */
+        "SimpleMesh",       /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
+        "ProgramFragment",  /* RSExportPrimitiveType::DataTypeRSProgramFragment */
+        "ProgramVertex",    /* RSExportPrimitiveType::DataTypeRSProgramVertex */
+        "ProgramRaster",    /* RSExportPrimitiveType::DataTypeRSProgramRaster */
+        "ProgramStore",     /* RSExportPrimitiveType::DataTypeRSProgramStore */
+    };
+
+    if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveTypeJavaNameMap) / sizeof(const char*))))
+        return PrimitiveTypeJavaNameMap[ EPT->getType() ];
+
+    assert(false && "GetPrimitiveTypeName : Unknown primitive data type");
+    return NULL;
+}
+
+static const char* GetVectorTypeName(const RSExportVectorType* EVT) {
+    static const char* VectorTypeJavaNameMap[][3] = {
+        /* 0 */ { "Byte2",  "Byte3",    "Byte4" },
+        /* 1 */ { "Short2", "Short3",   "Short4" },
+        /* 2 */ { "Int2",   "Int3",     "Int4" },
+        /* 3 */ { "Float2", "Float3",   "Float4" },
+    };
+
+    const char** BaseElement;
+
+    switch(EVT->getType()) {
+        case RSExportPrimitiveType::DataTypeSigned8:
+        case RSExportPrimitiveType::DataTypeUnsigned8:
+            BaseElement = VectorTypeJavaNameMap[0];
+        break;
+
+        case RSExportPrimitiveType::DataTypeSigned16:
+        case RSExportPrimitiveType::DataTypeUnsigned16:
+            BaseElement = VectorTypeJavaNameMap[1];
+        break;
+
+        case RSExportPrimitiveType::DataTypeSigned32:
+        case RSExportPrimitiveType::DataTypeUnsigned32:
+            BaseElement = VectorTypeJavaNameMap[2];
+        break;
+
+        case RSExportPrimitiveType::DataTypeFloat32: 
+            BaseElement = VectorTypeJavaNameMap[3];
+        break;
+
+        default:
+            assert(false && "RSReflection::genElementTypeName : Unsupported vector element data type");
+        break;
+    }
+
+    assert((EVT->getNumElement() > 1) && (EVT->getNumElement() <= 4) && "Number of element in vector type is invalid");
+
+    return BaseElement[EVT->getNumElement() - 2];
+}
+
+static const char* GetPackerAPIName(const RSExportPrimitiveType* EPT) {
+    static const char* PrimitiveTypePackerAPINameMap[] = {
+        "",
+        "",
+        "addF32",   /* RSExportPrimitiveType::DataTypeFloat32 */
+        "addF64",   /* RSExportPrimitiveType::DataTypeFloat64 */
+        "addI8",    /* RSExportPrimitiveType::DataTypeSigned8 */
+        "addI16",   /* RSExportPrimitiveType::DataTypeSigned16 */
+        "addI32",   /* RSExportPrimitiveType::DataTypeSigned32 */
+        "addI64",   /* RSExportPrimitiveType::DataTypeSigned64 */
+        "addU8",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
+        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned16 */
+        "addU32",   /* RSExportPrimitiveType::DataTypeUnsigned32 */
+        "addU64",   /* RSExportPrimitiveType::DataTypeUnsigned64 */
+
+        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
+        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
+        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
+
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSElement */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSType */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSAllocation */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSSampler */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSScript */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramFragment */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
+        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramStore */
+    };
+
+    if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*))))
+        return PrimitiveTypePackerAPINameMap[ EPT->getType() ];
+
+    assert(false && "GetPackerAPIName : Unknown primitive data type");
+    return NULL;
+}
+
+static std::string GetTypeName(const RSExportType* ET) {
+    switch(ET->getClass()) {
+        case RSExportType::ExportClassPrimitive:
+            return GetPrimitiveTypeName(static_cast<const RSExportPrimitiveType*>(ET));
+        break;
+
+        case RSExportType::ExportClassPointer:
+        {
+            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
+
+            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
+                return "Allocation";
+            else
+                return RS_TYPE_CLASS_NAME_PREFIX + PointeeType->getName();
+        }
+        break;
+
+        case RSExportType::ExportClassVector:
+            return GetVectorTypeName(static_cast<const RSExportVectorType*>(ET));
+        break;
+
+        case RSExportType::ExportClassRecord:
+            return RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
+        break;
+
+        default:
+            assert(false && "Unknown class of type");
+        break;
+    }
+
+    return "";
+}
+
+static const char* GetBuiltinElementConstruct(const RSExportType* ET) {
+    if(ET->getClass() == RSExportType::ExportClassPrimitive) {
+        const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
+        if(EPT->getKind() == RSExportPrimitiveType::DataKindUser) {
+            static const char* PrimitiveBuiltinElementConstructMap[] = {
+                NULL,
+                NULL,
+                "USER_F32", /* RSExportPrimitiveType::DataTypeFloat32 */
+                NULL,       /* RSExportPrimitiveType::DataTypeFloat64 */
+                "USER_I8",  /* RSExportPrimitiveType::DataTypeSigned8 */
+                NULL,       /* RSExportPrimitiveType::DataTypeSigned16 */
+                "USER_I32", /* RSExportPrimitiveType::DataTypeSigned32 */
+                NULL,       /* RSExportPrimitiveType::DataTypeSigned64 */
+                "USER_U8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
+                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned16 */
+                "USER_U32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
+                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned64 */
+
+                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned565 */
+                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
+                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
+
+                "USER_ELEMENT", /* RSExportPrimitiveType::DataTypeRSElement */
+                "USER_TYPE",    /* RSExportPrimitiveType::DataTypeRSType */
+                "USER_ALLOCATION",  /* RSExportPrimitiveType::DataTypeRSAllocation */
+                "USER_SAMPLER",     /* RSExportPrimitiveType::DataTypeRSSampler */
+                "USER_SCRIPT",      /* RSExportPrimitiveType::DataTypeRSScript */
+                "USER_MESH",        /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
+                "USER_PROGRAM_FRAGMENT",    /* RSExportPrimitiveType::DataTypeRSProgramFragment */
+                "USER_PROGRAM_VERTEX",      /* RSExportPrimitiveType::DataTypeRSProgramVertex */
+                "USER_PROGRAM_RASTER",      /* RSExportPrimitiveType::DataTypeRSProgramRaster */
+                "USER_PROGRAM_STORE",       /* RSExportPrimitiveType::DataTypeRSProgramStore */
+            };
+
+            if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveBuiltinElementConstructMap) / sizeof(const char*))))
+                return PrimitiveBuiltinElementConstructMap[ EPT->getType() ];
+        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelA) {
+            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) 
+                return "A_8";
+        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGB) {
+            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned565)
+                return "RGB_565";
+            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
+                return "RGB_888";
+        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGBA) {
+            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned5551)
+                return "RGB_5551";
+            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned4444)
+                return "RGB_4444";
+            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
+                return "RGB_8888";
+        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindIndex) {
+            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned16)
+                return "INDEX_16";
+        }
+    } else if(ET->getClass() == RSExportType::ExportClassVector) {
+        const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(ET);
+        if(EVT->getKind() == RSExportPrimitiveType::DataKindPosition) {
+            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
+                if(EVT->getNumElement() == 2)
+                    return "ATTRIB_POSITION_2";
+                else if(EVT->getNumElement() == 3)
+                    return "ATTRIB_POSITION_3";
+            }
+        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindTexture) {
+            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
+                if(EVT->getNumElement() == 2)
+                    return "ATTRIB_TEXTURE_2";
+            }
+        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindNormal) {
+            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
+                if(EVT->getNumElement() == 3)
+                    return "ATTRIB_NORMAL_3";
+            }
+        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindColor) {
+            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
+                if(EVT->getNumElement() == 4)
+                    return "ATTRIB_COLOR_F32_4";
+            } else if(EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
+                if(EVT->getNumElement() == 4)
+                    return "ATTRIB_COLOR_U8_4";
+            }
+        }
+    } else if(ET->getClass() == RSExportType::ExportClassPointer) {
+        return "USER_U32";  /* tread pointer type variable as unsigned int (TODO: this is target dependent) */
+    }
+
+    return NULL;
+}
+
+static const char* GetElementDataKindName(RSExportPrimitiveType::DataKind DK) {
+    static const char* ElementDataKindNameMap[] = {
+        "Element.DataKind.USER",        /* RSExportPrimitiveType::DataKindUser */
+        "Element.DataKind.COLOR",       /* RSExportPrimitiveType::DataKindColor */
+        "Element.DataKind.POSITION",    /* RSExportPrimitiveType::DataKindPosition */
+        "Element.DataKind.TEXTURE",     /* RSExportPrimitiveType::DataKindTexture */
+        "Element.DataKind.NORMAL",      /* RSExportPrimitiveType::DataKindNormal */
+        "Element.DataKind.INDEX",       /* RSExportPrimitiveType::DataKindIndex */
+        "Element.DataKind.POINT_SIZE",  /* RSExportPrimitiveType::DataKindPointSize */
+        "Element.DataKind.PIXEL_L",     /* RSExportPrimitiveType::DataKindPixelL */
+        "Element.DataKind.PIXEL_A",     /* RSExportPrimitiveType::DataKindPixelA */
+        "Element.DataKind.PIXEL_LA",    /* RSExportPrimitiveType::DataKindPixelLA */
+        "Element.DataKind.PIXEL_RGB",   /* RSExportPrimitiveType::DataKindPixelRGB */
+        "Element.DataKind.PIXEL_RGBA",  /* RSExportPrimitiveType::DataKindPixelRGBA */
+    };
+
+    if((DK >= 0) && (DK < (sizeof(ElementDataKindNameMap) / sizeof(const char*))))
+        return ElementDataKindNameMap[ DK ];
+    else
+        return NULL;
+}
+
+static const char* GetElementDataTypeName(RSExportPrimitiveType::DataType DT) {
+    static const char* ElementDataTypeNameMap[] = {
+        NULL,
+        NULL,
+        "Element.DataType.FLOAT_32",    /* RSExportPrimitiveType::DataTypeFloat32 */
+        NULL,                           /* RSExportPrimitiveType::DataTypeFloat64 */
+        "Element.DataType.SIGNED_8",    /* RSExportPrimitiveType::DataTypeSigned8 */
+        "Element.DataType.SIGNED_16",   /* RSExportPrimitiveType::DataTypeSigned16 */
+        "Element.DataType.SIGNED_32",   /* RSExportPrimitiveType::DataTypeSigned32 */
+        NULL,                           /* RSExportPrimitiveType::DataTypeSigned64 */
+        "Element.DataType.UNSIGNED_8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
+        "Element.DataType.UNSIGNED_16", /* RSExportPrimitiveType::DataTypeUnsigned16 */
+        "Element.DataType.UNSIGNED_32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
+        NULL,                           /* RSExportPrimitiveType::DataTypeUnsigned64 */
+
+        "Element.DataType.UNSIGNED_5_6_5",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
+        "Element.DataType.UNSIGNED_5_5_5_1", /* RSExportPrimitiveType::DataTypeUnsigned5551 */
+        "Element.DataType.UNSIGNED_4_4_4_4", /* RSExportPrimitiveType::DataTypeUnsigned4444 */
+
+        "Element.DataType.RS_ELEMENT",  /* RSExportPrimitiveType::DataTypeRSElement */
+        "Element.DataType.RS_TYPE",     /* RSExportPrimitiveType::DataTypeRSType */
+        "Element.DataType.RS_ALLOCATION",   /* RSExportPrimitiveType::DataTypeRSAllocation */
+        "Element.DataType.RS_SAMPLER",      /* RSExportPrimitiveType::DataTypeRSSampler */
+        "Element.DataType.RS_SCRIPT",       /* RSExportPrimitiveType::DataTypeRSScript */
+        "Element.DataType.RS_MESH",         /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
+        "Element.DataType.RS_PROGRAM_FRAGMENT", /* RSExportPrimitiveType::DataTypeRSProgramFragment */
+        "Element.DataType.RS_PROGRAM_VERTEX",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
+        "Element.DataType.RS_PROGRAM_RASTER",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
+        "Element.DataType.RS_PROGRAM_STORE",    /* RSExportPrimitiveType::DataTypeRSProgramStore */
+    };
+
+    if((DT >= 0) && (DT < (sizeof(ElementDataTypeNameMap) / sizeof(const char*))))
+        return ElementDataTypeNameMap[ DT ];
+    else
+        return NULL;
+}
+
+/****************************** Methods to generate script class ******************************/
+bool RSReflection::genScriptClass(Context& C, const std::string& ClassName, std::string& ErrorMsg) {
+    if(!C.startClass(Context::AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME, ErrorMsg)) 
+        return false;
+
+    genScriptClassConstructor(C);
+
+    /* Reflect export variable */
+    for(RSContext::const_export_var_iterator I = mRSContext->export_vars_begin();
+        I != mRSContext->export_vars_end();
+        I++)
+        genExportVariable(C, *I);
+
+    /* Reflect export function */
+    for(RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin();
+        I != mRSContext->export_funcs_end();
+        I++)
+        genExportFunction(C, *I);
+
+    C.endClass();
+
+    return true;
+}
+
+void RSReflection::genScriptClassConstructor(Context& C) {
+    C.indent() << "// Constructor" << endl;
+    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 3, "RenderScript", "rs",
+                                                                          "Resources", "resources",
+                                                                          "boolean", "isRoot");
+    /* Call constructor of super class */
+    C.indent() << "super(rs, resources, R.raw." << C.getResourceId() << ", isRoot);" << endl;
+    C.endFunction();
+    return;
+}
+
+void RSReflection::genExportVariable(Context& C, const RSExportVar* EV) {
+    const RSExportType* ET = EV->getType();
+
+    C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << " = " << C.getNextExportVarSlot() << ";" << endl;
+
+    switch(ET->getClass()) {
+        case RSExportType::ExportClassPrimitive:
+            genPrimitiveTypeExportVariable(C, EV);
+        break;
+
+        case RSExportType::ExportClassPointer:
+            genPointerTypeExportVariable(C, EV);
+        break;
+
+        case RSExportType::ExportClassVector:
+            genVectorTypeExportVariable(C, EV);
+        break;
+
+        case RSExportType::ExportClassRecord:
+            genRecordTypeExportVariable(C, EV);
+        break;
+
+        default:
+            assert(false && "Unknown class of type");
+        break;
+    }
+
+    return;
+}
+
+void RSReflection::genExportFunction(Context& C, const RSExportFunc* EF) {
+    C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << " = " << C.getNextExportFuncSlot() << ";" << endl;
+
+    /* invoke_*() */
+    Context::ArgTy Args;
+
+    for(RSExportFunc::const_param_iterator I = EF->params_begin();
+        I != EF->params_end();
+        I++) 
+    {
+        const RSExportFunc::Parameter* P = *I;
+        Args.push_back( make_pair(GetTypeName(P->getType()), P->getName()) );
+    }
+
+    C.startFunction(Context::AM_Public, false, "void", "invoke_" + EF->getName(), Args);
+
+    if(!EF->hasParam()) {
+        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");" << endl;
+    } else {
+        const RSExportRecordType* ERT = EF->getParamPacketType();
+        std::string FieldPackerName = EF->getName() + "_fp";
+
+        if(genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
+            genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
+
+        C.indent() << "invokeData("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", " << FieldPackerName << ");" << endl;
+    }
+
+    C.endFunction();
+    return;
+}
+
+void RSReflection::genPrimitiveTypeExportVariable(Context& C, const RSExportVar* EV) {
+    assert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive) && "Variable should be type of primitive here");
+
+    const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(EV->getType());
+    const char* TypeName = GetPrimitiveTypeName(EPT);
+
+    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
+
+    /* set_*() */
+    C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
+    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
+
+    if(EPT->isRSObjectType())
+        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", v.getID());" << endl;
+    else
+        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", v);" << endl;
+
+    C.endFunction();
+
+    genGetExportVariable(C, TypeName, EV->getName());
+
+    return;
+}
+
+void RSReflection::genPointerTypeExportVariable(Context& C, const RSExportVar* EV) {
+    const RSExportType* ET = EV->getType();
+    const RSExportType* PointeeType;
+    std::string TypeName;
+
+    assert((ET->getClass() == RSExportType::ExportClassPointer) && "Variable should be type of pointer here");
+
+    PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
+    TypeName = GetTypeName(ET);
+
+    /* bind_*() */
+    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
+
+    C.startFunction(Context::AM_Public, false, "void", "bind_" + EV->getName(), 1, TypeName.c_str(), "v");
+
+    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
+    C.indent() << "if(v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
+
+    if(PointeeType->getClass() == RSExportType::ExportClassRecord)
+        C.indent() << "else bindAllocation(v.getAllocation(), "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
+    else
+        C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
+
+    C.endFunction();
+
+    genGetExportVariable(C, TypeName, EV->getName());
+
+    return;
+}
+
+void RSReflection::genVectorTypeExportVariable(Context& C, const RSExportVar* EV) {
+    assert((EV->getType()->getClass() == RSExportType::ExportClassVector) && "Variable should be type of vector here");
+
+    const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(EV->getType());
+    const char* TypeName = GetVectorTypeName(EVT);
+    const char* FieldPackerName = "fp";
+
+    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
+
+    /* set_*() */
+    C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
+    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
+
+    if(genCreateFieldPacker(C, EVT, FieldPackerName))
+        genPackVarOfType(C, EVT, "v", FieldPackerName);
+    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
+
+    C.endFunction();
+
+    genGetExportVariable(C, TypeName, EV->getName());
+    return;
+}
+
+void RSReflection::genRecordTypeExportVariable(Context& C, const RSExportVar* EV) {
+    assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && "Variable should be type of struct here");
+
+    const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(EV->getType());
+    std::string TypeName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
+    const char* FieldPackerName = "fp";
+
+    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
+
+    /* set_*() */
+    C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName.c_str(), "v");
+    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
+
+    if(genCreateFieldPacker(C, ERT, FieldPackerName))
+        genPackVarOfType(C, ERT, "v", FieldPackerName);
+    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
+
+    C.endFunction();
+
+    genGetExportVariable(C, TypeName.c_str(), EV->getName());
+    return;
+}
+
+void RSReflection::genGetExportVariable(Context& C, const std::string& TypeName, const std::string& VarName) {
+    C.startFunction(Context::AM_Public, false, TypeName.c_str(), "get_" + VarName, 0);
+
+    C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << endl;
+
+    C.endFunction();
+    return;
+}
+
+/****************************** Methods to generate script class /end ******************************/
+
+bool RSReflection::genCreateFieldPacker(Context& C, const RSExportType* ET, const char* FieldPackerName) {
+    size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
+    if(AllocSize > 0)
+        C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" << AllocSize << ");" << endl;
+    else
+        return false;
+    return true;
+}
+
+void RSReflection::genPackVarOfType(Context& C, const RSExportType* ET, const char* VarName, const char* FieldPackerName) {
+    switch(ET->getClass()) {
+        case RSExportType::ExportClassPrimitive:
+        case RSExportType::ExportClassVector:
+            C.indent() << FieldPackerName << "." << GetPackerAPIName(static_cast<const RSExportPrimitiveType*>(ET)) << "(" << VarName << ");" << endl;
+        break;
+
+        case RSExportType::ExportClassPointer:
+        {
+            /* Must reflect as type Allocation in Java */
+            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
+
+            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
+                C.indent() << FieldPackerName << ".addU32(" << VarName << ".getPtr());" << endl;
+            else
+                C.indent() << FieldPackerName << ".addU32(" << VarName << ".getAllocation().getPtr());" << endl;
+        }
+        break;
+
+        case RSExportType::ExportClassRecord:
+        {
+            const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
+            int Pos = 0;    /* relative pos from now on in field packer */
+
+            for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
+                I != ERT->fields_end();
+                I++)
+            {
+                const RSExportRecordType::Field* F = *I;
+                std::string FieldName;
+                size_t FieldOffset = F->getOffsetInParent();
+                size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
+                size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
+
+                if(VarName != NULL)
+                    FieldName = VarName + ("." + F->getName());
+                else
+                    FieldName = F->getName();
+
+                if(FieldOffset > Pos)
+                    C.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos) << ");" << endl;
+
+                genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
+
+                if(FieldAllocSize > FieldStoreSize)  /* there's padding in the field type */
+                    C.indent() << FieldPackerName << ".skip(" << (FieldAllocSize - FieldStoreSize) << ");" << endl;
+
+                Pos = FieldOffset + FieldAllocSize;
+            }
+
+            /* There maybe some padding after the struct */
+            size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
+            if(Padding > 0)
+                C.indent() << FieldPackerName << ".skip(" << Padding << ");" << endl;
+        }
+        break;
+
+        default:
+            assert(false && "Unknown class of type");
+        break;
+    }
+
+    return;
+}
+
+/****************************** Methods to generate type class  ******************************/
+bool RSReflection::genTypeClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
+    std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
+
+    if(!C.startClass(Context::AM_Public, false, ClassName, RS_TYPE_CLASS_SUPER_CLASS_NAME, ErrorMsg)) 
+        return false;
+
+    if(!genTypeItemClass(C, ERT, ErrorMsg))
+        return false;
+
+    /* Declare item buffer and item buffer packer */
+    C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[];" << endl;
+    C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";" << endl;
+
+    genTypeClassConstructor(C, ERT);
+    genTypeClassCopyToArray(C, ERT);
+    genTypeClasSet(C, ERT);
+    genTypeClasCopyAll(C, ERT);
+
+    C.endClass();
+
+    return true;
+}
+
+bool RSReflection::genTypeItemClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
+    C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
+    C.startBlock();
+
+    C.indent() << "public static final int sizeof = " << RSExportType::GetTypeAllocSize(ERT) << ";" << endl;
+
+    /* Member elements */
+    C.out() << endl;
+    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
+        FI != ERT->fields_end();
+        FI++) 
+        C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() << ";" << endl;
+
+    /* Constructor */
+    C.out() << endl;
+    C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
+    C.startBlock();
+
+    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
+        FI != ERT->fields_end();
+        FI++) 
+    {
+        const RSExportRecordType::Field* F = *FI;
+        if((F->getType()->getClass() == RSExportType::ExportClassVector) || (F->getType()->getClass() == RSExportType::ExportClassRecord))
+        C.indent() << F->getName() << " = new " << GetTypeName(F->getType()) << "();" << endl;
+    }
+
+    C.endBlock();   /* end Constructor */
+
+    C.endBlock();   /* end Item class */
+
+
+    return true;
+}
+
+void RSReflection::genTypeClassConstructor(Context& C, const RSExportRecordType* ERT) {
+    const char* RenderScriptVar = "rs";
+
+    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 2, "RenderScript", RenderScriptVar,
+                                                                          "int", "count");
+
+    C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << endl;
+    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << endl;
+
+    genBuildElement(C, ERT, "mElement", RenderScriptVar);
+    /* Call init() in super class */
+    C.indent() << "init(" << RenderScriptVar << ", count);" << endl;
+    C.endFunction();
+
+    return;
+}
+
+void RSReflection::genTypeClassCopyToArray(Context& C, const RSExportRecordType* ERT) {
+    C.startFunction(Context::AM_Private, false, "void", "copyToArray", 2, RS_TYPE_ITEM_CLASS_NAME, "i",
+                                                                          "int", "index");
+
+    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;
+    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" << endl;
+
+    genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
+
+    C.endFunction();
+    return;
+}
+
+void RSReflection::genTypeClasSet(Context& C, const RSExportRecordType* ERT) {
+    C.startFunction(Context::AM_Public, false, "void", "set", 3, RS_TYPE_ITEM_CLASS_NAME, "i",
+                                                                 "int", "index",
+                                                                 "boolean", "copyNow");
+    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "RS_TYPE_ITEM_BUFFER_NAME" = new "RS_TYPE_ITEM_CLASS_NAME"[mType.getX() /* count */];" << endl;
+    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << endl;
+
+    C.indent() << "if (copyNow) ";
+    C.startBlock();
+    
+    C.indent() << "copyToArray(i, index);" << endl;
+    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;
+
+    C.endBlock();   /* end if (copyNow) */
+
+    C.endFunction();
+    return;
+}
+
+void RSReflection::genTypeClasCopyAll(Context& C, const RSExportRecordType* ERT) {
+    C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
+
+    C.indent() << "for (int ct=0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++) copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);" << endl;
+    C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
+
+    C.endFunction();
+    return;
+}
+
+/****************************** Methods to generate type class /end ******************************/
+
+/******************** Methods to create Element in Java of given record type ********************/
+void RSReflection::genBuildElement(Context& C, const RSExportRecordType* ERT, const char* ElementName, const char* RenderScriptVar) {
+    const char* ElementBuilderName = "eb";
+
+    /* Create element builder */
+    C.startBlock(true);
+
+    C.indent() << "Element.Builder " << ElementBuilderName << " = new Element.Builder(" << RenderScriptVar << ");" << endl;
+
+    /* eb.add(...) */
+    genAddElementToElementBuilder(C, ERT, "", ElementBuilderName, RenderScriptVar);
+
+    C.indent() << ElementName << " = " << ElementBuilderName << ".create();" << endl;
+
+    C.endBlock();
+    return;
+}
+
+#define EB_ADD(x, ...)  \
+        C.indent() << ElementBuilderName << ".add(Element." << x ##__VA_ARGS__ ", \"" << VarName << "\");" << endl
+void RSReflection::genAddElementToElementBuilder(Context& C, const RSExportType* ET, const std::string& VarName, const char* ElementBuilderName, const char* RenderScriptVar) {
+        const char* ElementConstruct = GetBuiltinElementConstruct(ET);
+        if(ElementConstruct != NULL) {
+            EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
+        } else {
+            if((ET->getClass() == RSExportType::ExportClassPrimitive) || (ET->getClass() == RSExportType::ExportClassVector)) {
+                const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
+                const char* DataKindName = GetElementDataKindName(EPT->getKind());
+                const char* DataTypeName = GetElementDataTypeName(EPT->getType());
+                int Size = (ET->getClass() == RSExportType::ExportClassVector) ? static_cast<const RSExportVectorType*>(ET)->getNumElement() : 1;
+
+                switch(EPT->getKind()) {
+                    case RSExportPrimitiveType::DataKindColor:
+                    case RSExportPrimitiveType::DataKindPosition:
+                    case RSExportPrimitiveType::DataKindTexture:
+                    case RSExportPrimitiveType::DataKindNormal:
+                    case RSExportPrimitiveType::DataKindPointSize:
+                        /* Element.createAttrib() */
+                        EB_ADD("createAttrib(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ", " << Size << ")");
+                    break;
+
+                    case RSExportPrimitiveType::DataKindIndex:
+                        /* Element.createIndex() */
+                        EB_ADD("createAttrib(" << RenderScriptVar << ")");
+                    break;
+
+                    case RSExportPrimitiveType::DataKindPixelL:
+                    case RSExportPrimitiveType::DataKindPixelA:
+                    case RSExportPrimitiveType::DataKindPixelLA:
+                    case RSExportPrimitiveType::DataKindPixelRGB:
+                    case RSExportPrimitiveType::DataKindPixelRGBA:
+                        /* Element.createPixel() */
+                        EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ")");
+                    break;
+
+                    case RSExportPrimitiveType::DataKindUser:
+                    default:
+                        if(EPT->getClass() == RSExportType::ExportClassPrimitive)
+                            /* Element.createUser() */
+                            EB_ADD("createUser(" << RenderScriptVar << ", " << DataTypeName << ")");
+                        else /* (ET->getClass() == RSExportType::ExportClassVector) must hold here */
+                            /* Element.createVector() */
+                            EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << Size << ")");
+                    break;
+                }
+            } else if(ET->getClass() == RSExportType::ExportClassPointer) {
+                /* Pointer type variable should be resolved in GetBuiltinElementConstruct()  */
+                assert(false && "??");
+            } else if(ET->getClass() == RSExportType::ExportClassRecord) {
+                /* 
+                 * Simalar to genPackVarOfType.
+                 *
+                 * TODO: Generalize these two function such that there's no duplicated codes.
+                 */
+                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
+                int Pos = 0;    /* relative pos from now on */
+
+                for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
+                    I != ERT->fields_end();
+                    I++) 
+                {   
+                    const RSExportRecordType::Field* F = *I; 
+                    std::string FieldName;
+                    size_t FieldOffset = F->getOffsetInParent();
+                    size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
+                    size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
+
+                    if(!VarName.empty())
+                        FieldName = VarName + "." + F->getName();
+                    else
+                        FieldName = F->getName();
+
+                    /* alignment */
+                    genAddPaddingToElementBuiler(C, (FieldOffset - Pos), ElementBuilderName, RenderScriptVar);
+
+                    /* eb.add(...) */
+                    genAddElementToElementBuilder(C, (*I)->getType(), FieldName, ElementBuilderName, RenderScriptVar);
+
+                    /* there's padding within the field type */
+                    genAddPaddingToElementBuiler(C, (FieldAllocSize - FieldStoreSize), ElementBuilderName, RenderScriptVar);
+
+                    Pos = FieldOffset + FieldAllocSize;
+                }   
+
+                /* There maybe some padding after the struct */
+                genAddPaddingToElementBuiler(C, (RSExportType::GetTypeAllocSize(ERT) - Pos), ElementBuilderName, RenderScriptVar);
+            } else {
+                assert(false && "Unknown class of type");
+            }
+        }
+}
+
+void RSReflection::genAddPaddingToElementBuiler(Context& C, size_t PaddingSize, const char* ElementBuilderName, const char* RenderScriptVar) {
+    while(PaddingSize > 0) {
+        const std::string& VarName = C.createPaddingField();
+        if(PaddingSize >= 4) {
+            EB_ADD("USER_U32(" << RenderScriptVar << ")");
+            PaddingSize -= 4;
+        } else if(PaddingSize >= 2) {
+            EB_ADD("USER_U16(" << RenderScriptVar << ")");
+            PaddingSize -= 2;
+        } else if(PaddingSize >= 1) {
+            EB_ADD("USER_U8(" << RenderScriptVar << ")");
+            PaddingSize -= 1;
+        }
+    }
+    return;
+}
+
+#undef EB_ADD
+/******************** Methods to create Element in Java of given record type /end ********************/
+
+bool RSReflection::reflect(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
+    Context *C = NULL;
+    std::string ResourceId = "";
+
+    if(!GetFileNameWithoutExtension(OutputBCFileName, ResourceId))
+        return false;
+
+    if(ResourceId.empty())
+        ResourceId = "<Resource ID>";
+
+    if((OutputPackageName == NULL) || (*OutputPackageName == '\0') || strcmp(OutputPackageName, "-") == 0) 
+        C = new Context("<Package Name>", ResourceId, true);
+    else 
+        C = new Context(OutputPackageName, ResourceId, false);
+
+    if(C != NULL) {
+        std::string ErrorMsg, ScriptClassName;
+        /* class ScriptC_<ScriptName> */
+        if(!GetFileNameWithoutExtension(InputFileName, ScriptClassName))
+            return false;
+
+        if(ScriptClassName.empty())
+            ScriptClassName = "<Input Script Name>";
+
+        ScriptClassName.at(0) = toupper(ScriptClassName.at(0));
+        ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
+
+        if(!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
+            std::cerr << "Failed to generate class " << ScriptClassName << " (" << ErrorMsg << ")" << endl;
+            return false;
+        }
+
+        /* class ScriptField_<TypeName> */
+        for(RSContext::const_export_type_iterator TI = mRSContext->export_types_begin();
+            TI != mRSContext->export_types_end();
+            TI++) 
+        {
+            const RSExportType* ET = TI->getValue();
+
+            if(ET->getClass() == RSExportType::ExportClassRecord) {
+                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
+
+                if(!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
+                    std::cerr << "Failed to generate type class for struct '" << ERT->getName() << "' (" << ErrorMsg << ")" << endl;
+                    return false;
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+/****************************** RSReflection::Context ******************************/
+const char* const RSReflection::Context::LicenseNote = 
+    "/*\n"
+	" * Copyright (C) 2010 The Android Open Source Project\n"
+	" *\n"
+	" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+	" * you may not use this file except in compliance with the License.\n"
+	" * You may obtain a copy of the License at\n"
+	" *\n"
+	" *      http://www.apache.org/licenses/LICENSE-2.0\n"
+	" *\n"
+	" * Unless required by applicable law or agreed to in writing, software\n"
+	" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+	" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+	" * See the License for the specific language governing permissions and\n"
+	" * limitations under the License.\n"
+	" */\n";
+
+const char* const RSReflection::Context::Import[] = {
+    /* RenderScript java class */
+    "android.renderscript.*",
+    /* Import R */
+    "android.content.res.Resources",
+    /* Import for debugging */
+    "android.util.Log",
+};
+
+const char* RSReflection::Context::AccessModifierStr(AccessModifier AM) {
+    switch(AM) {
+        case AM_Public: return "public"; break;
+        case AM_Protected: return "protected"; break;
+        case AM_Private: return "private"; break;
+        default: return ""; break;
+    }
+}
+
+bool RSReflection::Context::startClass(AccessModifier AM, bool IsStatic, const std::string& ClassName, const char* SuperClassName, std::string& ErrorMsg) {
+    if(mVerbose) 
+        std::cout << "Generating " << ClassName << ".java ..." << endl;
+
+    /* Open the file */
+    if(!mUseStdout) {
+        mOF.clear();
+        mOF.open((ClassName + ".java").c_str());
+        if(!mOF.good()) {
+            ErrorMsg = "failed to open file '" + ClassName + ".java' for write";
+            return false;
+        }
+    }
+
+    /* License */
+    out() << LicenseNote << endl;
+
+    /* Package */
+    if(!mPackageName.empty())
+        out() << "package " << mPackageName << ";" << endl;
+    out() << endl;
+
+    /* Imports */
+    for(int i=0;i<(sizeof(Import)/sizeof(const char*));i++)
+        out() << "import " << Import[i] << ";" << endl;
+    out() << endl;
+
+    out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " << ClassName;
+    if(SuperClassName != NULL)
+        out() << " extends " << SuperClassName;
+
+    startBlock();
+
+    mClassName = ClassName;
+
+    return true;
+}
+
+void RSReflection::Context::endClass() {
+    endBlock();
+    if(!mUseStdout)
+        mOF.close();
+    clear();
+    return;
+}
+
+void RSReflection::Context::startBlock(bool ShouldIndent) {
+    if(ShouldIndent)
+        indent() << "{" << endl;
+    else
+        out() << " {" << endl;
+    incIndentLevel();
+    return;
+}
+
+void RSReflection::Context::endBlock() {
+    decIndentLevel();
+    indent() << "}" << endl << endl;
+    return;
+}
+
+void RSReflection::Context::startTypeClass(const std::string& ClassName) {
+    indent() << "public static class " << ClassName;
+    startBlock();
+    return;
+}
+
+void RSReflection::Context::endTypeClass() {
+    endBlock();
+    return;
+}
+
+void RSReflection::Context::startFunction(AccessModifier AM, bool IsStatic, const char* ReturnType, const std::string& FunctionName, int Argc, ...) {
+    ArgTy Args;
+    va_list vl;
+    va_start(vl, Argc);
+
+    for(int i=0;i<Argc;i++) {
+        const char* ArgType = va_arg(vl, const char*);
+        const char* ArgName = va_arg(vl, const char*);
+
+        Args.push_back( make_pair(ArgType, ArgName) );
+    }
+    va_end(vl);
+
+    startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
+
+    return;
+}
+
+void RSReflection::Context::startFunction(AccessModifier AM, 
+                                          bool IsStatic, 
+                                          const char* ReturnType, 
+                                          const std::string& FunctionName, 
+                                          const ArgTy& Args) 
+{
+    indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
+
+    bool FirstArg = true;
+    for(ArgTy::const_iterator I = Args.begin();
+        I != Args.end();
+        I++)
+    {
+        if(!FirstArg) 
+            out() << ", ";
+        else
+            FirstArg = false;
+
+        out() << I->first << " " << I->second;
+    }
+
+    out() << ")";
+    startBlock();
+
+    return;
+}
+
+void RSReflection::Context::endFunction() {
+    endBlock();
+    return;
+}
+
+}   /* namespace slang */
diff --git a/slang_rs_reflection.hpp b/slang_rs_reflection.hpp
new file mode 100644
index 0000000..7d61b28
--- /dev/null
+++ b/slang_rs_reflection.hpp
@@ -0,0 +1,179 @@
+#ifndef _SLANG_COMPILER_RS_REFLECTION_HPP
+#   define _SLANG_COMPILER_RS_REFLECTION_HPP
+
+#include <map>
+#include <vector>
+#include <string>
+#include <cassert>
+#include <fstream>
+#include <iostream>
+
+#include "slang_rs_export_type.hpp"
+
+#include "llvm/ADT/StringExtras.h"  /* for function llvm::utostr_32() and llvm::itostr() */
+
+namespace slang {
+
+class RSContext;
+class RSExportVar;
+class RSExportFunc;
+class RSExportRecordType;
+
+class RSReflection {
+private:
+    const RSContext* mRSContext;
+
+    std::string mLastError;
+    inline void setError(const std::string& Error) { mLastError = Error; }
+
+    class Context {
+    private:
+        static const char* const LicenseNote;
+        static const char* const Import[];
+
+        bool mUseStdout;
+        mutable std::ofstream mOF;
+
+        bool mVerbose;
+
+        std::string mPackageName;
+        std::string mResourceId;
+
+        std::string mClassName;
+
+        std::string mIndent;
+
+        int mPaddingFieldIndex;
+
+        int mNextExportVarSlot;
+        int mNextExportFuncSlot;
+
+        inline void clear() {
+            mClassName = "";
+            mIndent = "";
+            mPaddingFieldIndex = 1;
+            mNextExportVarSlot = 0;
+            mNextExportFuncSlot = 0;
+            return;
+        }
+
+    public:
+        typedef enum {
+            AM_Public,
+            AM_Protected,
+            AM_Private
+        } AccessModifier;
+
+        static const char* AccessModifierStr(AccessModifier AM);
+
+        Context(const std::string& PackageName, const std::string& ResourceId, bool UseStdout) : 
+            mPackageName(PackageName),
+            mResourceId(ResourceId),
+            mUseStdout(UseStdout),
+            mVerbose(true)
+        { 
+            clear();
+            return; 
+        }
+
+        inline std::ostream& out() const { if(mUseStdout) return std::cout; else return mOF; }
+        inline std::ostream& indent() const { 
+            out() << mIndent; 
+            return out();
+        }
+
+        inline void incIndentLevel() { 
+            mIndent.append(4, ' '); 
+            return; 
+        }
+
+        inline void decIndentLevel() { 
+            assert(getIndentLevel() > 0 && "No indent"); 
+            mIndent.erase(0, 4); 
+            return; 
+        }
+
+        inline int getIndentLevel() {
+            return (mIndent.length() >> 2);
+        }
+
+        inline int getNextExportVarSlot() {
+            return mNextExportVarSlot++;
+        }
+
+        inline int getNextExportFuncSlot() {
+            return mNextExportFuncSlot++;
+        }
+
+        /* Will remove later due to field name information is not necessary for C-reflect-to-Java */
+        inline std::string createPaddingField() {
+            return "#padding_" + llvm::itostr(mPaddingFieldIndex++);
+        }
+
+        bool startClass(AccessModifier AM, bool IsStatic, const std::string& ClassName, const char* SuperClassName, std::string& ErrorMsg);
+        void endClass();
+
+        void startFunction(AccessModifier AM, bool IsStatic, const char* ReturnType, const std::string& FunctionName, int Argc, ...);
+        
+        typedef std::vector<std::pair<std::string, std::string> > ArgTy;
+        void startFunction(AccessModifier AM, bool IsStatic, const char* ReturnType, const std::string& FunctionName, const ArgTy& Args);
+        void endFunction();
+
+        void startBlock(bool ShouldIndent = false);
+        void endBlock();
+
+        inline const std::string& getPackageName() const { return mPackageName; }
+        inline const std::string& getClassName() const { return mClassName; }
+        inline const std::string& getResourceId() const { return mResourceId; }
+
+        void startTypeClass(const std::string& ClassName);
+        void endTypeClass();
+    };
+
+    bool genScriptClass(Context& C, const std::string& ClassName, std::string& ErrorMsg);
+    void genScriptClassConstructor(Context& C);
+
+    void genExportVariable(Context& C, const RSExportVar* EV);
+    void genPrimitiveTypeExportVariable(Context& C, const RSExportVar* EV);
+    void genPointerTypeExportVariable(Context& C, const RSExportVar* EV);
+    void genVectorTypeExportVariable(Context& C, const RSExportVar* EV);
+    void genRecordTypeExportVariable(Context& C, const RSExportVar* EV);
+    void genGetExportVariable(Context& C, const std::string& TypeName, const std::string& VarName);
+
+    void genExportFunction(Context& C, const RSExportFunc* EF);
+
+    bool genTypeClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg);
+    bool genTypeItemClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg);
+    void genTypeClassConstructor(Context& C, const RSExportRecordType* ERT);
+    void genTypeClassCopyToArray(Context& C, const RSExportRecordType* ERT);
+    void genTypeClasSet(Context& C, const RSExportRecordType* ERT);
+    void genTypeClasCopyAll(Context& C, const RSExportRecordType* ERT);
+
+    void genBuildElement(Context& C, const RSExportRecordType* ERT, const char* ElementName, const char* RenderScriptVar);
+    void genAddElementToElementBuilder(Context& C, const RSExportType* ERT, const std::string& VarName, const char* ElementBuilderName, const char* RenderScriptVar);
+    void genAddPaddingToElementBuiler(Context& C, size_t PaddingSize, const char* ElementBuilderName, const char* RenderScriptVar);
+
+    bool genCreateFieldPacker(Context& C, const RSExportType* T, const char* FieldPackerName);
+    void genPackVarOfType(Context& C, const RSExportType* T, const char* VarName, const char* FieldPackerName);
+
+public:
+    RSReflection(const RSContext* Context) :
+        mRSContext(Context),
+        mLastError("")
+    {
+        return;
+    }
+
+    bool reflect(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName);
+
+    inline const char* getLastError() const {
+        if(mLastError.empty())
+            return NULL;
+        else
+            return mLastError.c_str();
+    }
+};  /* class RSReflection */
+
+}   /* namespace slang */
+
+#endif  /* _SLANG_COMPILER_RS_REFLECTION_HPP */
diff --git a/target.inc b/target.inc
new file mode 100644
index 0000000..a03ea02
--- /dev/null
+++ b/target.inc
@@ -0,0 +1,39 @@
+/* DEF_SUPPORT_TARGET(target, name, default_triple) */
+#ifdef DEF_SUPPORT_TARGET
+    DEF_SUPPORT_TARGET(ARM, "ARM", "armv7-none-linux-gnueabi")
+    DEF_SUPPORT_TARGET(X86, "x86", "i686-unknown-linux")
+    DEF_SUPPORT_TARGET(X64, "x64", "x86_64-unknown-linux")
+#   undef DEF_SUPPORT_TARGET
+#endif
+
+/* @id below should be an unique identifier of a feature (i.e. different features should have different @id) even across different targets */
+
+/* DEF_TARGET_FEATURE(target, id, key, description) */
+#ifdef DEF_TARGET_FEATURE
+
+#   ifndef HOOK_TARGET_FIRST_FEATURE
+#       define HOOK_TARGET_FIRST_FEATURE DEF_TARGET_FEATURE
+#   endif
+
+#   ifndef HOOK_TARGET_LAST_FEATURE
+#       define HOOK_TARGET_LAST_FEATURE DEF_TARGET_FEATURE
+#   endif
+
+    HOOK_TARGET_FIRST_FEATURE(ARM, FeatureNEON, "neon", "Enable NEON instructions")
+
+    DEF_TARGET_FEATURE(ARM, FeatureThumb2, "thumb2", "Enable Thumb2 instructions")
+    DEF_TARGET_FEATURE(ARM, ArchV4T, "v4t", "ARM v4T")
+    DEF_TARGET_FEATURE(ARM, ArchV5T, "v5t", "ARM v5T")
+    DEF_TARGET_FEATURE(ARM, ArchV5TE, "v5te", "ARM v5TE, v5TEj, v5TExp")
+    DEF_TARGET_FEATURE(ARM, ArchV6, "v6", "ARM v6")
+    DEF_TARGET_FEATURE(ARM, ArchV6T2, "v6t2", "ARM v6t2")
+    DEF_TARGET_FEATURE(ARM, ArchV7A, "v7a", "ARM v7A")
+    DEF_TARGET_FEATURE(ARM, FeatureVFP2, "vfp2", "Enable VFP2 instructions")
+
+    HOOK_TARGET_LAST_FEATURE(ARM, FeatureVFP3, "vfp3", "Enable VFP3 instructions")
+
+
+#   undef DEF_TARGET_FEATURE
+#endif
+#undef HOOK_TARGET_FIRST_FEATURE
+#undef HOOK_TARGET_LAST_FEATURE