start cpp reflection

BUG=5972398

Change-Id: Iede58fde457d16293345e741f80109f89e653ad5
diff --git a/Android.mk b/Android.mk
index 05df356..2347d3d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -229,7 +229,9 @@
 	slang_rs_export_foreach.cpp \
 	slang_rs_object_ref_count.cpp	\
 	slang_rs_reflection.cpp \
-	slang_rs_reflect_utils.cpp  \
+	slang_rs_reflection_base.cpp \
+	slang_rs_reflection_cpp.cpp \
+	slang_rs_reflect_utils.cpp
 
 LOCAL_STATIC_LIBRARIES :=	\
 	libclangDriver libslang \
diff --git a/slang_rs.cpp b/slang_rs.cpp
index 13413c0..0eea6f9 100644
--- a/slang_rs.cpp
+++ b/slang_rs.cpp
@@ -36,6 +36,8 @@
 #include "slang_rs_context.h"
 #include "slang_rs_export_type.h"
 
+#include "slang_rs_reflection_cpp.h"
+
 namespace slang {
 
 #define RS_HEADER_SUFFIX  "rsh"
@@ -321,7 +323,11 @@
     if (OutputType != Slang::OT_Dependency) {
 
       if (BitcodeStorage == BCST_CPP_CODE) {
-        // TODO: Call C++ reflection routines + appendGeneratedFileName().
+          RSReflectionCpp R(mRSContext);
+          bool ret = R.reflect(JavaReflectionPathBase, getInputFileName(), getOutputFileName());
+          if (!ret) {
+            return false;
+          }
       } else {
 
         if (!reflectToJava(JavaReflectionPathBase,
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
index dc2b356..843ef56 100644
--- a/slang_rs_export_type.cpp
+++ b/slang_rs_export_type.cpp
@@ -1439,4 +1439,52 @@
   return true;
 }
 
+void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
+    memset(rtd, 0, sizeof(*rtd));
+    rtd->vecSize = 1;
+
+    switch(getClass()) {
+    case RSExportType::ExportClassPrimitive: {
+            const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
+            rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
+            return;
+        }
+    case RSExportType::ExportClassPointer: {
+            const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
+            const RSExportType *PointeeType = EPT->getPointeeType();
+            PointeeType->convertToRTD(rtd);
+            rtd->isPointer = true;
+            return;
+        }
+    case RSExportType::ExportClassVector: {
+            const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
+            rtd->type = EVT->getRSReflectionType(EVT);
+            rtd->vecSize = EVT->getNumElement();
+            return;
+        }
+    case RSExportType::ExportClassMatrix: {
+            const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
+            unsigned Dim = EMT->getDim();
+            slangAssert((Dim >= 2) && (Dim <= 4));
+            rtd->type = &gReflectionTypes[15 + Dim-2];
+            return;
+        }
+    case RSExportType::ExportClassConstantArray: {
+            const RSExportConstantArrayType* CAT =
+              static_cast<const RSExportConstantArrayType*>(this);
+            CAT->getElementType()->convertToRTD(rtd);
+            rtd->arraySize = CAT->getSize();
+            return;
+        }
+    case RSExportType::ExportClassRecord: {
+            slangAssert(!"RSExportType::ExportClassRecord not implemented");
+            return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
+        }
+    default: {
+            slangAssert(false && "Unknown class of type");
+        }
+    }
+}
+
+
 }  // namespace slang
diff --git a/slang_rs_export_type.h b/slang_rs_export_type.h
index e88f42f..e3d8f78 100644
--- a/slang_rs_export_type.h
+++ b/slang_rs_export_type.h
@@ -71,6 +71,20 @@
     bool java_promotion;
 } RSReflectionType;
 
+
+typedef struct RSReflectionTypeData_rec {
+    const RSReflectionType *type;
+    uint32_t vecSize;
+    bool isPointer;
+    uint32_t arraySize;
+
+    // Subelements
+    //std::vector<const struct RSReflectionTypeData_rec *> fields;
+    //std::vector< std::string > fieldNames;
+    //std::vector< uint32_t> fieldOffsetBytes;
+} RSReflectionTypeData;
+
+
 class RSExportType : public RSExportable {
   friend class RSExportElement;
  public:
@@ -83,6 +97,8 @@
     ExportClassRecord
   } ExportClass;
 
+  void convertToRTD(RSReflectionTypeData *rtd) const;
+
  private:
   ExportClass mClass;
   std::string mName;
diff --git a/slang_rs_reflection_base.cpp b/slang_rs_reflection_base.cpp
new file mode 100644
index 0000000..9f0650d
--- /dev/null
+++ b/slang_rs_reflection_base.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>
+
+#include <cstdarg>
+#include <cctype>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "os_sep.h"
+#include "slang_rs_context.h"
+#include "slang_rs_export_var.h"
+#include "slang_rs_export_foreach.h"
+#include "slang_rs_export_func.h"
+#include "slang_rs_reflect_utils.h"
+#include "slang_version.h"
+#include "slang_utils.h"
+
+#include "slang_rs_reflection_base.h"
+
+
+
+using namespace std;
+
+namespace slang {
+
+static const char *const gApacheLicenseNote =
+"/*\n"
+" * Copyright (C) 2012 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"
+"\n";
+
+
+RSReflectionBase::RSReflectionBase(const RSContext *con) {
+    mRSContext = con;
+    mLicenseNote = gApacheLicenseNote;
+
+
+}
+
+RSReflectionBase::~RSReflectionBase() {
+
+}
+
+/*
+bool RSReflectionBase::openFile(const string &name, string &errorMsg) {
+    if(!mUseStdout) {
+        mOF.clear();
+        if(!SlangUtils::CreateDirectoryWithParents(mOutputPath, &errorMsg)) {
+            return false;
+        }
+
+        string cf(mOutputPath + OS_PATH_SEPARATOR_STR + name);
+        mOF.open(cf.c_str());
+        if(!mOF.good()) {
+            errorMsg = "failed to open file '" + cf + "' for write";
+            return false;
+        }
+    }
+    return true;
+}
+*/
+
+void RSReflectionBase::startFile(const string &filename) {
+    if(mVerbose) {
+        printf("Generating %s\n", filename.c_str());
+    }
+
+    // License
+    write(mLicenseNote);
+
+    // Notice of generated file
+    write("/*");
+    write(" * This file is auto-generated. DO NOT MODIFY!");
+    write(" * The source Renderscript file: " + mInputFileName);
+    write(" */");
+    write("");
+}
+
+string RSReflectionBase::stripRS(const string &s) const {
+    size_t pos = s.rfind(".rs");
+    if(pos != string::npos) {
+        string tmp(s);
+        tmp.erase(pos);
+        return tmp;
+    }
+    return s;
+}
+
+void RSReflectionBase::write(const std::string &t) {
+    printf("%s%s\n", mIndent.c_str(), t.c_str());
+    mText.push_back(mIndent + t);
+}
+
+
+void RSReflectionBase::incIndent() {
+  mIndent.append("    ");
+}
+
+void RSReflectionBase::decIndent() {
+  mIndent.erase(0, 4);
+}
+
+bool RSReflectionBase::writeFile(const string &filename, const vector< string > &txt) {
+    FILE *pfin = fopen(filename.c_str(), "wt");
+    if (pfin == NULL) {
+        fprintf(stderr, "Error: could not write file %s\n", filename.c_str());
+        return false;
+    }
+
+    for(size_t ct=0; ct < txt.size(); ct++) {
+        fprintf(pfin, "%s\n", txt[ct].c_str());
+    }
+    fclose(pfin);
+    return true;
+}
+
+
+}
diff --git a/slang_rs_reflection_base.h b/slang_rs_reflection_base.h
new file mode 100644
index 0000000..b328646
--- /dev/null
+++ b/slang_rs_reflection_base.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_BASE_H_  // NOLINT
+#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_BASE_H_
+
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "llvm/ADT/StringExtras.h"
+
+#include "slang_assert.h"
+#include "slang_rs_export_type.h"
+
+namespace slang {
+    class RSContext;
+    class RSExportVar;
+    class RSExportFunc;
+    class RSExportForEach;
+
+class RSReflectionBase {
+protected:
+    const RSContext *mRSContext;
+
+
+
+    RSReflectionBase(const RSContext *);
+
+
+    bool mVerbose;
+
+    std::string mLicenseNote;
+    std::string mInputFileName;
+
+    std::string mClassName;
+    std::string mOutputPath;
+    std::string mOutputBCFileName;
+
+    std::vector< std::string > mText;
+    std::string mIndent;
+
+    bool openFile(const std::string &name, std::string &errorMsg);
+    void startFile(const std::string &filename);
+    void incIndent();
+    void decIndent();
+    void write(const std::string &t);
+
+    std::string stripRS(const std::string &s) const;
+
+    static bool writeFile(const std::string &filename, const std::vector< std::string > &txt);
+
+
+private:
+
+public:
+    virtual ~RSReflectionBase();
+
+
+};  // class RSReflection
+
+}   // namespace slang
+
+#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_BASE_H_  NOLINT
diff --git a/slang_rs_reflection_cpp.cpp b/slang_rs_reflection_cpp.cpp
new file mode 100644
index 0000000..68c7c0a
--- /dev/null
+++ b/slang_rs_reflection_cpp.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <cstdarg>
+#include <cctype>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "os_sep.h"
+#include "slang_rs_context.h"
+#include "slang_rs_export_var.h"
+#include "slang_rs_export_foreach.h"
+#include "slang_rs_export_func.h"
+#include "slang_rs_reflect_utils.h"
+#include "slang_version.h"
+#include "slang_utils.h"
+
+#include "slang_rs_reflection_cpp.h"
+
+using namespace std;
+
+namespace slang {
+
+RSReflectionCpp::RSReflectionCpp(const RSContext *con) :
+    RSReflectionBase(con) {
+
+}
+
+RSReflectionCpp::~RSReflectionCpp() {
+
+}
+
+bool RSReflectionCpp::reflect(const string &OutputPathBase,
+                              const string &InputFileName,
+                              const string &OutputBCFileName) {
+    mInputFileName = InputFileName;
+    mOutputPath = OutputPathBase;
+    mOutputBCFileName = OutputBCFileName;
+    mClassName = string("ScriptC_") + stripRS(InputFileName);
+
+    makeHeader("ScriptC");
+    std::vector< std::string > header(mText);
+    mText.clear();
+
+    makeImpl("ScriptC");
+    std::vector< std::string > cpp(mText);
+    mText.clear();
+
+
+    RSReflectionBase::writeFile(mClassName + ".h", header);
+    RSReflectionBase::writeFile(mClassName + ".cpp", cpp);
+
+
+    return false;
+}
+
+typedef std::vector<std::pair<std::string, std::string> > ArgTy;
+
+
+#define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
+
+
+
+bool RSReflectionCpp::makeHeader(const std::string &baseClass) {
+    startFile(mClassName + ".h");
+
+    write("");
+    write("#include \"ScriptC.h\"");
+    write("");
+
+    // Imports
+    //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
+        //out() << "import " << Import[i] << ";" << std::endl;
+    //out() << std::endl;
+
+    if(!baseClass.empty()) {
+        write("class " + mClassName + " : public " + baseClass + " {");
+    } else {
+        write("class " + mClassName + " {");
+    }
+
+    write("public:");
+    incIndent();
+    write(mClassName + "(RenderScript *rs, const char *cacheDir, size_t cacheDirLength);");
+    write("virtual ~" + mClassName + "();");
+
+
+    // Reflect export variable
+    uint32_t slot = 0;
+    for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
+           E = mRSContext->export_vars_end(); I != E; I++) {
+
+        const RSExportVar *ev = *I;
+        //const RSExportType *et = ev->getType();
+
+        char buf[256];
+        sprintf(buf, " = %i;", slot++);
+        write("const static int mExportVarIdx_" + ev->getName() + buf);
+
+        //switch (ET->getClass()) {
+
+        //genExportVariable(C, *I);
+    }
+
+    // Reflect export for each functions
+    for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
+             E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
+
+        const RSExportForEach *ef = *I;
+        if (ef->isDummyRoot()) {
+            write("// No forEach_root(...)");
+            continue;
+        }
+
+        char buf[256];
+        sprintf(buf, " = %i;", slot);
+        write("const static int mExportForEachIdx_" + ef->getName() + buf);
+
+        string tmp("void forEach_" + ef->getName() + "(");
+        if(ef->hasIn())
+            tmp += "Allocation ain";
+        if(ef->hasOut())
+            tmp += "Allocation aout";
+
+        if(ef->getParamPacketType()) {
+            for(RSExportForEach::const_param_iterator i = ef->params_begin(),
+                     e = ef->params_end(); i != e; i++) {
+
+                RSReflectionTypeData rtd;
+                (*i)->getType()->convertToRTD(&rtd);
+                tmp += rtd.type->c_name;
+                tmp += " ";
+                tmp +=(*i)->getName();
+            }
+        }
+        tmp += ") const;";
+        write(tmp);
+    }
+
+
+    // Reflect export function
+    for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
+           E = mRSContext->export_funcs_end(); I != E; I++) {
+
+        //genExportFunction(C, *I);
+    }
+
+    decIndent();
+    write("};");
+    return true;
+}
+
+bool RSReflectionCpp::writeBC() {
+    FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
+    if (pfin == NULL) {
+        fprintf(stderr, "Error: could not read file %s\n", mOutputBCFileName.c_str());
+        return false;
+    }
+
+    unsigned char buf[16];
+    int read_length;
+    write("static const unsigned char __txt[] = {");
+    incIndent();
+    while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
+        string s;
+        for(int i = 0; i < read_length; i++) {
+            char buf2[16];
+            sprintf(buf2, "0x%02x,", buf[i]);
+            s += buf2;
+        }
+        write(s);
+    }
+    decIndent();
+    write("};");
+    write("");
+    return true;
+}
+
+bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
+    startFile(mClassName + ".h");
+
+    write("");
+    write("#include \"" + mClassName + ".h\"");
+    write("");
+
+    writeBC();
+
+    // Imports
+    //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
+        //out() << "import " << Import[i] << ";" << std::endl;
+    //out() << std::endl;
+
+    write(mClassName + "::" + mClassName +
+          "(RenderScript *rs, const char *cacheDir, size_t cacheDirLength) :");
+    write("        ScriptC(rs, __txt, sizeof(__txt), " + mInputFileName +
+          ", 4, cacheDir, cacheDirLength) {");
+    incIndent();
+    //...
+    decIndent();
+    write("}");
+    write("");
+
+    write("virtual ~" + mClassName + "::" + mClassName + "() {");
+    write("}");
+    write("");
+
+
+    // Reflect export variable
+    uint32_t slot = 0;
+    for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
+           E = mRSContext->export_vars_end(); I != E; I++) {
+
+        const RSExportVar *ev = *I;
+        //const RSExportType *et = ev->getType();
+
+        char buf[256];
+        sprintf(buf, " = %i;", slot++);
+        write("const static int mExportVarIdx_" + ev->getName() + buf);
+
+        //switch (ET->getClass()) {
+
+        //genExportVariable(C, *I);
+    }
+
+    // Reflect export for each functions
+    slot = 0;
+    for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
+             E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
+
+        const RSExportForEach *ef = *I;
+        if (ef->isDummyRoot()) {
+            write("// No forEach_root(...)");
+            continue;
+        }
+
+        char buf[256];
+        string tmp("void forEach_" + ef->getName() + "(");
+        if(ef->hasIn() && ef->hasOut()) {
+            tmp += "Allocation ain, Allocation aout";
+        } else if(ef->hasIn()) {
+            tmp += "Allocation ain";
+        } else {
+            tmp += "Allocation aout";
+        }
+        tmp += ") const {";
+        write(tmp);
+
+        incIndent();
+        sprintf(buf, "forEach(%i, ", slot);
+        tmp = buf;
+        if(ef->hasIn() && ef->hasOut()) {
+            tmp += "ain, aout, NULL, 0);";
+        } else if(ef->hasIn()) {
+            tmp += "ain, NULL, 0);";
+        } else {
+            tmp += "aout, NULL, 0);";
+        }
+        write(tmp);
+        decIndent();
+
+        write("}");
+        write("");
+    }
+
+
+    // Reflect export function
+    slot = 0;
+    for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
+           E = mRSContext->export_funcs_end(); I != E; I++) {
+
+        //genExportFunction(C, *I);
+    }
+
+    decIndent();
+    return true;
+}
+
+
+
+}
diff --git a/slang_rs_reflection_cpp.h b/slang_rs_reflection_cpp.h
new file mode 100644
index 0000000..1537286
--- /dev/null
+++ b/slang_rs_reflection_cpp.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_CPP_H_  // NOLINT
+#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_CPP_H_
+
+#include "slang_rs_reflection_base.h"
+
+namespace slang {
+
+class RSReflectionCpp : public RSReflectionBase {
+protected:
+
+
+public:
+    RSReflectionCpp(const RSContext *);
+    virtual ~RSReflectionCpp();
+
+    bool reflect(const std::string &OutputPathBase,
+                 const std::string &InputFileName,
+                 const std::string &OutputBCFileName);
+
+
+private:
+    bool makeHeader(const std::string &baseClass);
+    bool makeImpl(const std::string &baseClass);
+    bool writeBC();
+
+    bool startScriptHeader();
+
+};  // class RSReflection
+
+}   // namespace slang
+
+#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_CPP_H_  NOLINT