Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2012, The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <sys/stat.h> |
| 18 | #include <stdio.h> |
| 19 | #include <stdlib.h> |
| 20 | |
| 21 | #include <cstdarg> |
| 22 | #include <cctype> |
| 23 | |
| 24 | #include <algorithm> |
| 25 | #include <sstream> |
| 26 | #include <string> |
| 27 | #include <utility> |
| 28 | |
| 29 | #include "os_sep.h" |
| 30 | #include "slang_rs_context.h" |
| 31 | #include "slang_rs_export_var.h" |
| 32 | #include "slang_rs_export_foreach.h" |
| 33 | #include "slang_rs_export_func.h" |
| 34 | #include "slang_rs_reflect_utils.h" |
| 35 | #include "slang_version.h" |
| 36 | #include "slang_utils.h" |
| 37 | |
| 38 | #include "slang_rs_reflection_cpp.h" |
| 39 | |
| 40 | using namespace std; |
| 41 | |
| 42 | namespace slang { |
| 43 | |
| 44 | RSReflectionCpp::RSReflectionCpp(const RSContext *con) : |
| 45 | RSReflectionBase(con) { |
| 46 | |
| 47 | } |
| 48 | |
| 49 | RSReflectionCpp::~RSReflectionCpp() { |
| 50 | |
| 51 | } |
| 52 | |
| 53 | bool RSReflectionCpp::reflect(const string &OutputPathBase, |
| 54 | const string &InputFileName, |
| 55 | const string &OutputBCFileName) { |
| 56 | mInputFileName = InputFileName; |
| 57 | mOutputPath = OutputPathBase; |
| 58 | mOutputBCFileName = OutputBCFileName; |
| 59 | mClassName = string("ScriptC_") + stripRS(InputFileName); |
| 60 | |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 61 | makeHeader("android::renderscriptCpp::ScriptC"); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 62 | std::vector< std::string > header(mText); |
| 63 | mText.clear(); |
| 64 | |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 65 | makeImpl("android::renderscriptCpp::ScriptC"); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 66 | std::vector< std::string > cpp(mText); |
| 67 | mText.clear(); |
| 68 | |
| 69 | |
| 70 | RSReflectionBase::writeFile(mClassName + ".h", header); |
| 71 | RSReflectionBase::writeFile(mClassName + ".cpp", cpp); |
| 72 | |
| 73 | |
| 74 | return false; |
| 75 | } |
| 76 | |
| 77 | typedef std::vector<std::pair<std::string, std::string> > ArgTy; |
| 78 | |
| 79 | |
| 80 | #define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_" |
| 81 | |
| 82 | |
| 83 | |
| 84 | bool RSReflectionCpp::makeHeader(const std::string &baseClass) { |
| 85 | startFile(mClassName + ".h"); |
| 86 | |
| 87 | write(""); |
| 88 | write("#include \"ScriptC.h\""); |
| 89 | write(""); |
| 90 | |
| 91 | // Imports |
| 92 | //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) |
| 93 | //out() << "import " << Import[i] << ";" << std::endl; |
| 94 | //out() << std::endl; |
| 95 | |
| 96 | if(!baseClass.empty()) { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 97 | write("class " + mClassName + " : public " + baseClass + " {"); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 98 | } else { |
| 99 | write("class " + mClassName + " {"); |
| 100 | } |
| 101 | |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 102 | write("private:"); |
| 103 | uint32_t slot = 0; |
| 104 | incIndent(); |
| 105 | for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), |
| 106 | E = mRSContext->export_vars_end(); I != E; I++, slot++) { |
| 107 | |
| 108 | const RSExportVar *ev = *I; |
| 109 | RSReflectionTypeData rtd; |
| 110 | ev->getType()->convertToRTD(&rtd); |
| 111 | if(!ev->isConst()) { |
| 112 | write(string(rtd.type->c_name) + " __" + ev->getName() + ";"); |
| 113 | } |
| 114 | } |
| 115 | decIndent(); |
| 116 | |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 117 | write("public:"); |
| 118 | incIndent(); |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 119 | write(mClassName + "(android::renderscriptCpp::RenderScript *rs," + |
| 120 | " const char *cacheDir, size_t cacheDirLength);"); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 121 | write("virtual ~" + mClassName + "();"); |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 122 | write(""); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 123 | |
| 124 | |
| 125 | // Reflect export variable |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 126 | slot = 0; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 127 | for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 128 | E = mRSContext->export_vars_end(); I != E; I++, slot++) { |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 129 | |
| 130 | const RSExportVar *ev = *I; |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 131 | RSReflectionTypeData rtd; |
| 132 | ev->getType()->convertToRTD(&rtd); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 133 | |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 134 | if(!ev->isConst()) { |
| 135 | write(string("void set_") + ev->getName() + "(" + rtd.type->c_name + " v) {"); |
| 136 | stringstream tmp; |
| 137 | tmp << slot; |
| 138 | write(string(" setVar(") + tmp.str() + ", v);"); |
| 139 | write(string(" __") + ev->getName() + " = v;"); |
| 140 | write("}"); |
| 141 | } |
| 142 | write(string(rtd.type->c_name) + " get_" + ev->getName() + "() const {"); |
| 143 | if(ev->isConst()) { |
| 144 | const clang::APValue &val = ev->getInit(); |
| 145 | bool isBool = !strcmp(rtd.type->c_name, "bool"); |
| 146 | write(string(" return ") + genInitValue(val, isBool) + ";"); |
| 147 | } else { |
| 148 | write(string(" return __") + ev->getName() + ";"); |
| 149 | } |
| 150 | write("}"); |
| 151 | write(""); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | // Reflect export for each functions |
| 155 | for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(), |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 156 | E = mRSContext->export_foreach_end(); I != E; I++) { |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 157 | |
| 158 | const RSExportForEach *ef = *I; |
| 159 | if (ef->isDummyRoot()) { |
| 160 | write("// No forEach_root(...)"); |
| 161 | continue; |
| 162 | } |
| 163 | |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 164 | stringstream tmp; |
| 165 | tmp << "void forEach_" << ef->getName() << "("; |
| 166 | if(ef->hasIn() && ef->hasOut()) { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 167 | tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; |
| 168 | tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout"; |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 169 | } else if(ef->hasIn()) { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 170 | tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 171 | } else { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 172 | tmp << "android::sp<const android::renderscriptCpp::Allocation> aout"; |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 173 | } |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 174 | |
| 175 | if(ef->getParamPacketType()) { |
| 176 | for(RSExportForEach::const_param_iterator i = ef->params_begin(), |
| 177 | e = ef->params_end(); i != e; i++) { |
| 178 | |
| 179 | RSReflectionTypeData rtd; |
| 180 | (*i)->getType()->convertToRTD(&rtd); |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 181 | tmp << rtd.type->c_name << " " << (*i)->getName(); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 182 | } |
| 183 | } |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 184 | tmp << ") const;"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 185 | write(tmp); |
| 186 | } |
| 187 | |
| 188 | |
| 189 | // Reflect export function |
| 190 | for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(), |
| 191 | E = mRSContext->export_funcs_end(); I != E; I++) { |
| 192 | |
| 193 | //genExportFunction(C, *I); |
| 194 | } |
| 195 | |
| 196 | decIndent(); |
| 197 | write("};"); |
| 198 | return true; |
| 199 | } |
| 200 | |
| 201 | bool RSReflectionCpp::writeBC() { |
| 202 | FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb"); |
| 203 | if (pfin == NULL) { |
| 204 | fprintf(stderr, "Error: could not read file %s\n", mOutputBCFileName.c_str()); |
| 205 | return false; |
| 206 | } |
| 207 | |
| 208 | unsigned char buf[16]; |
| 209 | int read_length; |
| 210 | write("static const unsigned char __txt[] = {"); |
| 211 | incIndent(); |
| 212 | while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) { |
| 213 | string s; |
| 214 | for(int i = 0; i < read_length; i++) { |
| 215 | char buf2[16]; |
| 216 | sprintf(buf2, "0x%02x,", buf[i]); |
| 217 | s += buf2; |
| 218 | } |
| 219 | write(s); |
| 220 | } |
| 221 | decIndent(); |
| 222 | write("};"); |
| 223 | write(""); |
| 224 | return true; |
| 225 | } |
| 226 | |
| 227 | bool RSReflectionCpp::makeImpl(const std::string &baseClass) { |
| 228 | startFile(mClassName + ".h"); |
| 229 | |
| 230 | write(""); |
| 231 | write("#include \"" + mClassName + ".h\""); |
| 232 | write(""); |
| 233 | |
| 234 | writeBC(); |
| 235 | |
| 236 | // Imports |
| 237 | //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) |
| 238 | //out() << "import " << Import[i] << ";" << std::endl; |
| 239 | //out() << std::endl; |
| 240 | |
| 241 | write(mClassName + "::" + mClassName + |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 242 | "(android::renderscriptCpp::RenderScript *rs, const char *cacheDir, size_t cacheDirLength) :"); |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 243 | write(" ScriptC(rs, __txt, sizeof(__txt), \"" + mInputFileName + |
| 244 | "\", 4, cacheDir, cacheDirLength) {"); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 245 | incIndent(); |
| 246 | //... |
| 247 | decIndent(); |
| 248 | write("}"); |
| 249 | write(""); |
| 250 | |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 251 | write(mClassName + "::~" + mClassName + "() {"); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 252 | write("}"); |
| 253 | write(""); |
| 254 | |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 255 | // Reflect export for each functions |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 256 | uint32_t slot = 0; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 257 | for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(), |
| 258 | E = mRSContext->export_foreach_end(); I != E; I++, slot++) { |
| 259 | |
| 260 | const RSExportForEach *ef = *I; |
| 261 | if (ef->isDummyRoot()) { |
| 262 | write("// No forEach_root(...)"); |
| 263 | continue; |
| 264 | } |
| 265 | |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 266 | stringstream tmp; |
| 267 | tmp << "void " << mClassName << "::forEach_" << ef->getName() << "("; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 268 | if(ef->hasIn() && ef->hasOut()) { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 269 | tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; |
| 270 | tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 271 | } else if(ef->hasIn()) { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 272 | tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 273 | } else { |
Jason Sams | 6c51b5d | 2012-04-03 13:29:22 -0700 | [diff] [blame] | 274 | tmp << "android::sp<const android::renderscriptCpp::Allocation> aout"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 275 | } |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 276 | tmp << ") const {"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 277 | write(tmp); |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 278 | tmp.str(""); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 279 | |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 280 | tmp << " forEach(" << slot << ", "; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 281 | if(ef->hasIn() && ef->hasOut()) { |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 282 | tmp << "ain, aout, NULL, 0);"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 283 | } else if(ef->hasIn()) { |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 284 | tmp << "ain, NULL, 0);"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 285 | } else { |
Jason Sams | 192392f | 2012-03-13 16:22:12 -0700 | [diff] [blame] | 286 | tmp << "aout, NULL, 0);"; |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 287 | } |
| 288 | write(tmp); |
Jason Sams | 1b6a088 | 2012-03-12 15:07:58 -0700 | [diff] [blame] | 289 | |
| 290 | write("}"); |
| 291 | write(""); |
| 292 | } |
| 293 | |
| 294 | |
| 295 | // Reflect export function |
| 296 | slot = 0; |
| 297 | for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(), |
| 298 | E = mRSContext->export_funcs_end(); I != E; I++) { |
| 299 | |
| 300 | //genExportFunction(C, *I); |
| 301 | } |
| 302 | |
| 303 | decIndent(); |
| 304 | return true; |
| 305 | } |
| 306 | |
| 307 | |
| 308 | |
| 309 | } |