slang_rs_reflection_cpp.cpp revision 02a9826b586f765a95e3c75bd6080c4ee8e2e911
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 40using namespace std; 41 42namespace slang { 43 44RSReflectionCpp::RSReflectionCpp(const RSContext *con) 45 : RSReflectionBase(con) { 46} 47 48RSReflectionCpp::~RSReflectionCpp() { 49} 50 51bool RSReflectionCpp::reflect(const string &OutputPathBase, 52 const string &InputFileName, 53 const string &OutputBCFileName) { 54 mInputFileName = InputFileName; 55 mOutputPath = OutputPathBase; 56 mOutputBCFileName = OutputBCFileName; 57 mClassName = string("ScriptC_") + stripRS(InputFileName); 58 59 makeHeader("android::renderscriptCpp::ScriptC"); 60 std::vector< std::string > header(mText); 61 mText.clear(); 62 63 makeImpl("android::renderscriptCpp::ScriptC"); 64 std::vector< std::string > cpp(mText); 65 mText.clear(); 66 67 68 writeFile(mClassName + ".h", header); 69 writeFile(mClassName + ".cpp", cpp); 70 71 72 return true; 73} 74 75typedef std::vector<std::pair<std::string, std::string> > ArgTy; 76 77 78#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_" 79 80 81 82bool RSReflectionCpp::makeHeader(const std::string &baseClass) { 83 startFile(mClassName + ".h"); 84 85 write(""); 86 write("#include \"RenderScript.h\""); 87 write("using namespace android::renderscriptCpp;"); 88 write(""); 89 90 // Imports 91 //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 92 //out() << "import " << Import[i] << ";" << std::endl; 93 //out() << std::endl; 94 95 if (!baseClass.empty()) { 96 write("class " + mClassName + " : public " + baseClass + " {"); 97 } else { 98 write("class " + mClassName + " {"); 99 } 100 101 write("private:"); 102 uint32_t slot = 0; 103 incIndent(); 104 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 105 E = mRSContext->export_vars_end(); I != E; I++, slot++) { 106 const RSExportVar *ev = *I; 107 RSReflectionTypeData rtd; 108 ev->getType()->convertToRTD(&rtd); 109 if (!ev->isConst()) { 110 write(string(rtd.type->c_name) + " __" + ev->getName() + ";"); 111 } 112 } 113 decIndent(); 114 115 write("public:"); 116 incIndent(); 117 write(mClassName + "(android::sp<android::renderscriptCpp::RS> rs," + 118 " const char *cacheDir, size_t cacheDirLength);"); 119 write("virtual ~" + mClassName + "();"); 120 write(""); 121 122 123 // Reflect export variable 124 slot = 0; 125 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 126 E = mRSContext->export_vars_end(); I != E; I++, slot++) { 127 const RSExportVar *ev = *I; 128 RSReflectionTypeData rtd; 129 ev->getType()->convertToRTD(&rtd); 130 131 if (!ev->isConst()) { 132 write(string("void set_") + ev->getName() + "(" + rtd.type->c_name + 133 " v) {"); 134 stringstream tmp; 135 tmp << slot; 136 write(string(" setVar(") + tmp.str() + ", &v, sizeof(v));"); 137 write(string(" __") + ev->getName() + " = v;"); 138 write("}"); 139 } 140 write(string(rtd.type->c_name) + " get_" + ev->getName() + "() const {"); 141 if (ev->isConst()) { 142 const clang::APValue &val = ev->getInit(); 143 bool isBool = !strcmp(rtd.type->c_name, "bool"); 144 write(string(" return ") + genInitValue(val, isBool) + ";"); 145 } else { 146 write(string(" return __") + ev->getName() + ";"); 147 } 148 write("}"); 149 write(""); 150 } 151 152 // Reflect export for each functions 153 for (RSContext::const_export_foreach_iterator 154 I = mRSContext->export_foreach_begin(), 155 E = mRSContext->export_foreach_end(); I != E; I++) { 156 const RSExportForEach *ef = *I; 157 if (ef->isDummyRoot()) { 158 write("// No forEach_root(...)"); 159 continue; 160 } 161 162 stringstream tmp; 163 tmp << "void forEach_" << ef->getName() << "("; 164 if (ef->hasIn() && (ef->hasOut() || ef->hasReturn())) { 165 tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; 166 tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout"; 167 } else if (ef->hasIn()) { 168 tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; 169 } else { 170 tmp << "android::sp<const android::renderscriptCpp::Allocation> aout"; 171 } 172 173 if (ef->getParamPacketType()) { 174 for (RSExportForEach::const_param_iterator i = ef->params_begin(), 175 e = ef->params_end(); i != e; i++) { 176 RSReflectionTypeData rtd; 177 (*i)->getType()->convertToRTD(&rtd); 178 tmp << rtd.type->c_name << " " << (*i)->getName(); 179 } 180 } 181 tmp << ") const;"; 182 write(tmp); 183 } 184 185 186 // Reflect export function 187 for (RSContext::const_export_func_iterator 188 I = mRSContext->export_funcs_begin(), 189 E = mRSContext->export_funcs_end(); I != E; I++) { 190 const RSExportFunc *ef = *I; 191 192 stringstream ss; 193 makeFunctionSignature(ss, false, ef); 194 write(ss); 195 } 196 197 decIndent(); 198 write("};"); 199 return true; 200} 201 202bool RSReflectionCpp::writeBC() { 203 FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb"); 204 if (pfin == NULL) { 205 fprintf(stderr, "Error: could not read file %s\n", 206 mOutputBCFileName.c_str()); 207 return false; 208 } 209 210 unsigned char buf[16]; 211 int read_length; 212 write("static const unsigned char __txt[] = {"); 213 incIndent(); 214 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) { 215 string s; 216 for (int i = 0; i < read_length; i++) { 217 char buf2[16]; 218 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]); 219 s += buf2; 220 } 221 write(s); 222 } 223 decIndent(); 224 write("};"); 225 write(""); 226 return true; 227} 228 229bool RSReflectionCpp::makeImpl(const std::string &baseClass) { 230 startFile(mClassName + ".h"); 231 232 write(""); 233 write("#include \"" + mClassName + ".h\""); 234 write(""); 235 236 writeBC(); 237 238 // Imports 239 //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 240 //out() << "import " << Import[i] << ";" << std::endl; 241 //out() << std::endl; 242 243 write("\n"); 244 stringstream ss; 245 ss << mClassName << "::" << mClassName 246 << "(android::sp<android::renderscriptCpp::RS> rs, " 247 "const char *cacheDir, size_t cacheDirLength) :\n" 248 << " ScriptC(rs, __txt, sizeof(__txt), \"" 249 << mClassName << "\", " << mClassName.length() 250 << ", cacheDir, cacheDirLength) {"; 251 write(ss); 252 incIndent(); 253 //... 254 decIndent(); 255 write("}"); 256 write(""); 257 258 write(mClassName + "::~" + mClassName + "() {"); 259 write("}"); 260 write(""); 261 262 // Reflect export for each functions 263 uint32_t slot = 0; 264 for (RSContext::const_export_foreach_iterator 265 I = mRSContext->export_foreach_begin(), 266 E = mRSContext->export_foreach_end(); I != E; I++, slot++) { 267 const RSExportForEach *ef = *I; 268 if (ef->isDummyRoot()) { 269 write("// No forEach_root(...)"); 270 continue; 271 } 272 273 stringstream tmp; 274 tmp << "void " << mClassName << "::forEach_" << ef->getName() << "("; 275 if (ef->hasIn() && (ef->hasOut() || ef->hasReturn())) { 276 tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; 277 tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout"; 278 } else if (ef->hasIn()) { 279 tmp << "android::sp<const android::renderscriptCpp::Allocation> ain"; 280 } else { 281 tmp << "android::sp<const android::renderscriptCpp::Allocation> aout"; 282 } 283 tmp << ") const {"; 284 write(tmp); 285 tmp.str(""); 286 287 tmp << " forEach(" << slot << ", "; 288 if (ef->hasIn() && (ef->hasOut() || ef->hasReturn())) { 289 tmp << "ain, aout, NULL, 0);"; 290 } else if (ef->hasIn()) { 291 tmp << "ain, NULL, 0);"; 292 } else { 293 tmp << "aout, NULL, 0);"; 294 } 295 write(tmp); 296 297 write("}"); 298 write(""); 299 } 300 301 slot = 0; 302 // Reflect export function 303 for (RSContext::const_export_func_iterator 304 I = mRSContext->export_funcs_begin(), 305 E = mRSContext->export_funcs_end(); I != E; I++) { 306 const RSExportFunc *ef = *I; 307 308 stringstream ss; 309 makeFunctionSignature(ss, true, ef); 310 write(ss); 311 ss.str(""); 312 313 ss << " invoke(" << slot << ", NULL, 0);"; 314 write(ss); 315 316 write("}"); 317 write(""); 318 319 slot++; 320 } 321 322 decIndent(); 323 return true; 324} 325 326 327void RSReflectionCpp::makeFunctionSignature( 328 std::stringstream &ss, 329 bool isDefinition, 330 const RSExportFunc *ef) { 331 ss << "void "; 332 if (isDefinition) { 333 ss << mClassName << "::"; 334 } 335 ss << "invoke_" << ef->getName() << "("; 336 337 if (ef->getParamPacketType()) { 338 bool FirstArg = true; 339 for (RSExportFunc::const_param_iterator i = ef->params_begin(), 340 e = ef->params_end(); i != e; i++) { 341 RSReflectionTypeData rtd; 342 (*i)->getType()->convertToRTD(&rtd); 343 if (!FirstArg) { 344 ss << ", "; 345 } else { 346 FirstArg = false; 347 } 348 ss << rtd.type->c_name << " " << (*i)->getName(); 349 } 350 } 351 352 if (isDefinition) { 353 ss << ") {"; 354 } else { 355 ss << ");"; 356 } 357} 358 359} // namespace slang 360