diff options
-rw-r--r-- | Android.mk | 4 | ||||
-rw-r--r-- | slang_rs.cpp | 8 | ||||
-rw-r--r-- | slang_rs_export_type.cpp | 48 | ||||
-rw-r--r-- | slang_rs_export_type.h | 16 | ||||
-rw-r--r-- | slang_rs_reflection_base.cpp | 148 | ||||
-rw-r--r-- | slang_rs_reflection_base.h | 80 | ||||
-rw-r--r-- | slang_rs_reflection_cpp.cpp | 300 | ||||
-rw-r--r-- | slang_rs_reflection_cpp.h | 48 |
8 files changed, 650 insertions, 2 deletions
@@ -229,7 +229,9 @@ LOCAL_SRC_FILES := \ 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 @@ bool SlangRS::compile( 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 @@ bool RSExportRecordType::equals(const RSExportable *E) const { 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 @@ typedef struct { 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 @@ class RSExportType : public RSExportable { 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 |