slang_rs_reflection_cpp.cpp revision 713377ec412f448273158c954f6816f07f8bcd20
1526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen/* 2526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright 2012, The Android Open Source Project 3526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 4526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Licensed under the Apache License, Version 2.0 (the "License"); 5526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * you may not use this file except in compliance with the License. 6526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * You may obtain a copy of the License at 7526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 8526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * http://www.apache.org/licenses/LICENSE-2.0 9526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * 10526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Unless required by applicable law or agreed to in writing, software 11526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * distributed under the License is distributed on an "AS IS" BASIS, 12526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * See the License for the specific language governing permissions and 14526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * limitations under the License. 15526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */ 16526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 17526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <sys/stat.h> 18526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <stdio.h> 19526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <stdlib.h> 20526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 21526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <cstdarg> 22526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <cctype> 23526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 24526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <algorithm> 25526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <sstream> 26526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <string> 27526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <utility> 28526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 29526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "os_sep.h" 30526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_context.h" 31526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_export_var.h" 32526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_export_foreach.h" 33526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_export_func.h" 34526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_reflect_utils.h" 35526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_version.h" 36526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_utils.h" 37526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 38526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_reflection_cpp.h" 39526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 40526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenusing namespace std; 41526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 42526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wennamespace slang { 43526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 44526ecd1799a2fc467cfce114eae3578b42ccb786Ye WenRSReflectionCpp::RSReflectionCpp(const RSContext *con) 45526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen : RSReflectionBase(con) { 46526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen} 47526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 48526ecd1799a2fc467cfce114eae3578b42ccb786Ye WenRSReflectionCpp::~RSReflectionCpp() { 49526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen} 50526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 51526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenbool RSReflectionCpp::reflect(const string &OutputPathBase, 52526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen const string &InputFileName, 53526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen const string &OutputBCFileName) { 54526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen mInputFileName = InputFileName; 55526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen mOutputPath = OutputPathBase; 56526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen mOutputBCFileName = OutputBCFileName; 57526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen mClassName = string("ScriptC_") + stripRS(InputFileName); 58526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 59526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen makeHeader("android::renderscriptCpp::ScriptC"); 60526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen std::vector< std::string > header(mText); 61526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen mText.clear(); 62526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 63526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen makeImpl("android::renderscriptCpp::ScriptC"); 64526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen std::vector< std::string > cpp(mText); 65526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen mText.clear(); 66526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 67526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 68526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen writeFile(mClassName + ".h", header); 69526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen writeFile(mClassName + ".cpp", cpp); 70526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 71526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 72526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen return true; 73526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen} 74526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 75526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wentypedef std::vector<std::pair<std::string, std::string> > ArgTy; 76526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 77526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 78526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_" 79526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 80526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 81526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 82526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenbool RSReflectionCpp::makeHeader(const std::string &baseClass) { 83526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen startFile(mClassName + ".h"); 84526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 85526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write(""); 86526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write("#include \"RenderScript.h\""); 87526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write("using namespace android::renderscriptCpp;"); 88526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write(""); 89526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 90526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen // Imports 91526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 92526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen //out() << "import " << Import[i] << ";" << std::endl; 93526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen //out() << std::endl; 94526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 95526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (!baseClass.empty()) { 96526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write("class " + mClassName + " : public " + baseClass + " {"); 97526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } else { 98526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write("class " + mClassName + " {"); 99526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 100526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen 101526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write("private:"); 102526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen uint32_t slot = 0; 103526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen incIndent(); 104526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 105526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen E = mRSContext->export_vars_end(); I != E; I++, slot++) { 106526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen const RSExportVar *ev = *I; 107526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen RSReflectionTypeData rtd; 108526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen ev->getType()->convertToRTD(&rtd); 109526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen if (!ev->isConst()) { 110526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen write(string(rtd.type->c_name) + " __" + ev->getName() + ";"); 111526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 112526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen } 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 << ");"; 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 << ") {"; 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 const RSExportRecordType *params = ef->getParamPacketType(); 313 size_t param_len = 0; 314 if (params) { 315 param_len = RSExportType::GetTypeAllocSize(params); 316 ss << " FieldPacker __fp(" << param_len << ");"; 317 write(ss); 318 for (RSExportFunc::const_param_iterator i = ef->params_begin(), 319 e = ef->params_end(); i != e; i++) { 320 RSReflectionTypeData rtd; 321 (*i)->getType()->convertToRTD(&rtd); 322 ss.str(""); 323 ss << " __fp.add(" << (*i)->getName() << ");"; 324 write(ss); 325 } 326 327 } 328 329 ss.str(""); 330 ss << " invoke(" << slot; 331 if (params) { 332 ss << ", __fp.getData(), " << param_len << ");"; 333 } else { 334 ss << ", NULL, 0);"; 335 } 336 write(ss); 337 338 write("}"); 339 write(""); 340 341 slot++; 342 } 343 344 decIndent(); 345 return true; 346} 347 348 349void RSReflectionCpp::makeFunctionSignature( 350 std::stringstream &ss, 351 bool isDefinition, 352 const RSExportFunc *ef) { 353 ss << "void "; 354 if (isDefinition) { 355 ss << mClassName << "::"; 356 } 357 ss << "invoke_" << ef->getName() << "("; 358 359 if (ef->getParamPacketType()) { 360 bool FirstArg = true; 361 for (RSExportFunc::const_param_iterator i = ef->params_begin(), 362 e = ef->params_end(); i != e; i++) { 363 RSReflectionTypeData rtd; 364 (*i)->getType()->convertToRTD(&rtd); 365 if (!FirstArg) { 366 ss << ", "; 367 } else { 368 FirstArg = false; 369 } 370 ss << rtd.type->c_name << " " << (*i)->getName(); 371 } 372 } 373 374 if (isDefinition) { 375 ss << ") {"; 376 } else { 377 ss << ");"; 378 } 379} 380 381} // namespace slang 382