slang_rs_reflection_cpp.cpp revision ee9d7b0e0cb74a592cef718d72b589b64997bd21
1/* 2 * Copyright 2013, 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 44#define RS_TYPE_ITEM_CLASS_NAME "Item" 45 46static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) { 47 static const char *MatrixTypeCNameMap[] = { 48 "rs_matrix2x2", 49 "rs_matrix3x3", 50 "rs_matrix4x4", 51 }; 52 unsigned Dim = EMT->getDim(); 53 54 if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char*))) 55 return MatrixTypeCNameMap[ EMT->getDim() - 2 ]; 56 57 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension"); 58 return NULL; 59} 60 61 62static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) { 63 switch (ET->getClass()) { 64 case RSExportType::ExportClassPrimitive: { 65 return RSExportPrimitiveType::getRSReflectionType( 66 static_cast<const RSExportPrimitiveType*>(ET))->c_name; 67 } 68 case RSExportType::ExportClassPointer: { 69 const RSExportType *PointeeType = 70 static_cast<const RSExportPointerType*>(ET)->getPointeeType(); 71 72 if (PointeeType->getClass() != RSExportType::ExportClassRecord) 73 return "android::RSC::sp<android::RSC::Allocation>"; 74 else 75 return PointeeType->getElementName(); 76 } 77 case RSExportType::ExportClassVector: { 78 const RSExportVectorType *EVT = 79 static_cast<const RSExportVectorType*>(ET); 80 std::stringstream VecName; 81 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix 82 << EVT->getNumElement(); 83 return VecName.str(); 84 } 85 case RSExportType::ExportClassMatrix: { 86 return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET)); 87 } 88 case RSExportType::ExportClassConstantArray: { 89 // TODO: Fix this for C arrays! 90 const RSExportConstantArrayType* CAT = 91 static_cast<const RSExportConstantArrayType*>(ET); 92 std::string ElementTypeName = GetTypeName(CAT->getElementType()); 93 if (Brackets) { 94 ElementTypeName.append("[]"); 95 } 96 return ElementTypeName; 97 } 98 case RSExportType::ExportClassRecord: { 99 // TODO: Fix for C structs! 100 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME; 101 } 102 default: { 103 slangAssert(false && "Unknown class of type"); 104 } 105 } 106 107 return ""; 108} 109 110 111RSReflectionCpp::RSReflectionCpp(const RSContext *con) 112 : RSReflectionBase(con) { 113 clear(); 114} 115 116RSReflectionCpp::~RSReflectionCpp() { 117} 118 119bool RSReflectionCpp::reflect(const string &OutputPathBase, 120 const string &InputFileName, 121 const string &OutputBCFileName) { 122 mInputFileName = InputFileName; 123 mOutputPath = OutputPathBase; 124 mOutputBCFileName = OutputBCFileName; 125 mClassName = string("ScriptC_") + stripRS(InputFileName); 126 127 makeHeader("android::RSC::ScriptC"); 128 std::vector< std::string > header(mText); 129 mText.clear(); 130 131 makeImpl("android::RSC::ScriptC"); 132 std::vector< std::string > cpp(mText); 133 mText.clear(); 134 135 136 writeFile(mClassName + ".h", header); 137 writeFile(mClassName + ".cpp", cpp); 138 139 140 return true; 141} 142 143 144#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_" 145 146 147 148bool RSReflectionCpp::makeHeader(const std::string &baseClass) { 149 startFile(mClassName + ".h"); 150 151 write(""); 152 write("#include \"RenderScript.h\""); 153 write("using namespace android::RSC;"); 154 write(""); 155 156 // Imports 157 //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 158 //out() << "import " << Import[i] << ";" << std::endl; 159 //out() << std::endl; 160 161 if (!baseClass.empty()) { 162 write("class " + mClassName + " : public " + baseClass + " {"); 163 } else { 164 write("class " + mClassName + " {"); 165 } 166 167 write("private:"); 168 uint32_t slot = 0; 169 incIndent(); 170 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 171 E = mRSContext->export_vars_end(); I != E; I++, slot++) { 172 const RSExportVar *ev = *I; 173 RSReflectionTypeData rtd; 174 ev->getType()->convertToRTD(&rtd); 175 if (!ev->isConst()) { 176 write(GetTypeName(ev->getType()) + " __" + ev->getName() + ";"); 177 } 178 } 179 decIndent(); 180 181 write("public:"); 182 incIndent(); 183 write(mClassName + "(android::RSC::sp<android::RSC::RS> rs);"); 184 write("virtual ~" + mClassName + "();"); 185 write(""); 186 187 188 // Reflect export variable 189 slot = 0; 190 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 191 E = mRSContext->export_vars_end(); I != E; I++, slot++) { 192 genExportVariable(*I); 193 } 194 195 // Reflect export for each functions 196 for (RSContext::const_export_foreach_iterator 197 I = mRSContext->export_foreach_begin(), 198 E = mRSContext->export_foreach_end(); I != E; I++) { 199 const RSExportForEach *ef = *I; 200 if (ef->isDummyRoot()) { 201 write("// No forEach_root(...)"); 202 continue; 203 } 204 205 ArgTy Args; 206 stringstream ss; 207 ss << "void forEach_" << ef->getName() << "("; 208 209 if (ef->hasIn()) { 210 Args.push_back(std::make_pair( 211 "android::RSC::sp<const android::RSC::Allocation>", "ain")); 212 } 213 214 if (ef->hasOut() || ef->hasReturn()) { 215 Args.push_back(std::make_pair( 216 "android::RSC::sp<const android::RSC::Allocation>", "aout")); 217 } 218 219 const RSExportRecordType *ERT = ef->getParamPacketType(); 220 if (ERT) { 221 for (RSExportForEach::const_param_iterator i = ef->params_begin(), 222 e = ef->params_end(); i != e; i++) { 223 RSReflectionTypeData rtd; 224 (*i)->getType()->convertToRTD(&rtd); 225 Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); 226 } 227 } 228 makeArgs(ss, Args); 229 ss << ");"; 230 write(ss); 231 } 232 233 234 // Reflect export function 235 for (RSContext::const_export_func_iterator 236 I = mRSContext->export_funcs_begin(), 237 E = mRSContext->export_funcs_end(); I != E; I++) { 238 const RSExportFunc *ef = *I; 239 240 stringstream ss; 241 makeFunctionSignature(ss, false, ef); 242 write(ss); 243 } 244 245 decIndent(); 246 write("};"); 247 return true; 248} 249 250bool RSReflectionCpp::writeBC() { 251 FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb"); 252 if (pfin == NULL) { 253 fprintf(stderr, "Error: could not read file %s\n", 254 mOutputBCFileName.c_str()); 255 return false; 256 } 257 258 unsigned char buf[16]; 259 int read_length; 260 write("static const unsigned char __txt[] = {"); 261 incIndent(); 262 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) { 263 string s; 264 for (int i = 0; i < read_length; i++) { 265 char buf2[16]; 266 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]); 267 s += buf2; 268 } 269 write(s); 270 } 271 decIndent(); 272 write("};"); 273 write(""); 274 return true; 275} 276 277bool RSReflectionCpp::makeImpl(const std::string &baseClass) { 278 startFile(mClassName + ".cpp"); 279 280 write(""); 281 write("#include \"" + mClassName + ".h\""); 282 write(""); 283 284 writeBC(); 285 286 // Imports 287 //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 288 //out() << "import " << Import[i] << ";" << std::endl; 289 //out() << std::endl; 290 291 write("\n"); 292 stringstream ss; 293 const std::string &packageName = mRSContext->getReflectJavaPackageName(); 294 ss << mClassName << "::" << mClassName 295 << "(android::RSC::sp<android::RSC::RS> rs):\n" 296 " ScriptC(rs, __txt, sizeof(__txt), \"" 297 << stripRS(mInputFileName) << "\", " << stripRS(mInputFileName).length() 298 << ", \"/data/data/" << packageName << "/app\", sizeof(\"" << packageName << "\")) {"; 299 write(ss); 300 incIndent(); 301 //... 302 decIndent(); 303 write("}"); 304 write(""); 305 306 write(mClassName + "::~" + mClassName + "() {"); 307 write("}"); 308 write(""); 309 310 // Reflect export for each functions 311 uint32_t slot = 0; 312 for (RSContext::const_export_foreach_iterator 313 I = mRSContext->export_foreach_begin(), 314 E = mRSContext->export_foreach_end(); I != E; I++, slot++) { 315 const RSExportForEach *ef = *I; 316 if (ef->isDummyRoot()) { 317 write("// No forEach_root(...)"); 318 continue; 319 } 320 321 stringstream tmp; 322 ArgTy Args; 323 tmp << "void " << mClassName << "::forEach_" << ef->getName() << "("; 324 325 if (ef->hasIn()) { 326 Args.push_back(std::make_pair( 327 "android::RSC::sp<const android::RSC::Allocation>", "ain")); 328 } 329 330 if (ef->hasOut() || ef->hasReturn()) { 331 Args.push_back(std::make_pair( 332 "android::RSC::sp<const android::RSC::Allocation>", "aout")); 333 } 334 335 const RSExportRecordType *ERT = ef->getParamPacketType(); 336 if (ERT) { 337 for (RSExportForEach::const_param_iterator i = ef->params_begin(), 338 e = ef->params_end(); i != e; i++) { 339 RSReflectionTypeData rtd; 340 (*i)->getType()->convertToRTD(&rtd); 341 Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); 342 } 343 } 344 makeArgs(tmp, Args); 345 346 tmp << ") {"; 347 write(tmp); 348 tmp.str(""); 349 350 std::string FieldPackerName = ef->getName() + "_fp"; 351 if (ERT) { 352 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) { 353 genPackVarOfType(ERT, NULL, FieldPackerName.c_str()); 354 } 355 } 356 tmp << " forEach(" << slot << ", "; 357 358 if (ef->hasIn()) { 359 tmp << "ain, "; 360 } else { 361 tmp << "NULL, "; 362 } 363 364 if (ef->hasOut() || ef->hasReturn()) { 365 tmp << "aout, "; 366 } else { 367 tmp << "NULL, "; 368 } 369 370 tmp << "NULL, 0);"; 371 write(tmp); 372 373 write("}"); 374 write(""); 375 } 376 377 slot = 0; 378 // Reflect export function 379 for (RSContext::const_export_func_iterator 380 I = mRSContext->export_funcs_begin(), 381 E = mRSContext->export_funcs_end(); I != E; I++) { 382 const RSExportFunc *ef = *I; 383 384 stringstream ss; 385 makeFunctionSignature(ss, true, ef); 386 write(ss); 387 ss.str(""); 388 const RSExportRecordType *params = ef->getParamPacketType(); 389 size_t param_len = 0; 390 if (params) { 391 param_len = RSExportType::GetTypeAllocSize(params); 392 if (genCreateFieldPacker(params, "__fp")) { 393 genPackVarOfType(params, NULL, "__fp"); 394 } 395 } 396 397 ss.str(""); 398 ss << " invoke(" << slot; 399 if (params) { 400 ss << ", __fp.getData(), " << param_len << ");"; 401 } else { 402 ss << ", NULL, 0);"; 403 } 404 write(ss); 405 406 write("}"); 407 write(""); 408 409 slot++; 410 } 411 412 decIndent(); 413 return true; 414} 415 416void RSReflectionCpp::genExportVariable(const RSExportVar *EV) { 417 const RSExportType *ET = EV->getType(); 418 419 switch (ET->getClass()) { 420 case RSExportType::ExportClassPrimitive: { 421 genPrimitiveTypeExportVariable(EV); 422 break; 423 } 424 case RSExportType::ExportClassPointer: { 425 genPointerTypeExportVariable(EV); 426 break; 427 } 428 case RSExportType::ExportClassVector: { 429 genVectorTypeExportVariable(EV); 430 break; 431 } 432 case RSExportType::ExportClassMatrix: { 433 genMatrixTypeExportVariable(EV); 434 break; 435 } 436 case RSExportType::ExportClassConstantArray: { 437 genConstantArrayTypeExportVariable(EV); 438 break; 439 } 440 case RSExportType::ExportClassRecord: { 441 genRecordTypeExportVariable(EV); 442 break; 443 } 444 default: { 445 slangAssert(false && "Unknown class of type"); 446 } 447 } 448} 449 450 451void RSReflectionCpp::genPrimitiveTypeExportVariable(const RSExportVar *EV) { 452 RSReflectionTypeData rtd; 453 EV->getType()->convertToRTD(&rtd); 454 455 if (!EV->isConst()) { 456 write(string("void set_") + EV->getName() + "(" + rtd.type->c_name + 457 " v) {"); 458 stringstream tmp; 459 tmp << getNextExportVarSlot(); 460 write(string(" setVar(") + tmp.str() + ", &v, sizeof(v));"); 461 write(string(" __") + EV->getName() + " = v;"); 462 write("}"); 463 } 464 write(string(rtd.type->c_name) + " get_" + EV->getName() + "() const {"); 465 if (EV->isConst()) { 466 const clang::APValue &val = EV->getInit(); 467 bool isBool = !strcmp(rtd.type->c_name, "bool"); 468 write(string(" return ") + genInitValue(val, isBool) + ";"); 469 } else { 470 write(string(" return __") + EV->getName() + ";"); 471 } 472 write("}"); 473 write(""); 474} 475 476void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) { 477 const RSExportType *ET = EV->getType(); 478 479 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && 480 "Variable should be type of pointer here"); 481 482 std::string TypeName = GetTypeName(ET); 483 std::string VarName = EV->getName(); 484 485 RSReflectionTypeData rtd; 486 EV->getType()->convertToRTD(&rtd); 487 uint32_t slot = getNextExportVarSlot(); 488 489 if (!EV->isConst()) { 490 write(string("void bind_") + VarName + "(" + TypeName + 491 " v) {"); 492 stringstream tmp; 493 tmp << slot; 494 write(string(" bindAllocation(v, ") + tmp.str() + ");"); 495 write(string(" __") + VarName + " = v;"); 496 write("}"); 497 } 498 write(TypeName + " get_" + VarName + "() const {"); 499 if (EV->isConst()) { 500 const clang::APValue &val = EV->getInit(); 501 bool isBool = !strcmp(TypeName.c_str(), "bool"); 502 write(string(" return ") + genInitValue(val, isBool) + ";"); 503 } else { 504 write(string(" return __") + VarName + ";"); 505 } 506 write("}"); 507 write(""); 508 509} 510 511void RSReflectionCpp::genVectorTypeExportVariable(const RSExportVar *EV) { 512 slangAssert(false); 513} 514 515void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) { 516 slangAssert(false); 517} 518 519void RSReflectionCpp::genConstantArrayTypeExportVariable( 520 const RSExportVar *EV) { 521 slangAssert(false); 522} 523 524void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) { 525 slangAssert(false); 526} 527 528 529void RSReflectionCpp::makeFunctionSignature( 530 std::stringstream &ss, 531 bool isDefinition, 532 const RSExportFunc *ef) { 533 ss << "void "; 534 if (isDefinition) { 535 ss << mClassName << "::"; 536 } 537 ss << "invoke_" << ef->getName() << "("; 538 539 if (ef->getParamPacketType()) { 540 bool FirstArg = true; 541 for (RSExportFunc::const_param_iterator i = ef->params_begin(), 542 e = ef->params_end(); i != e; i++) { 543 RSReflectionTypeData rtd; 544 (*i)->getType()->convertToRTD(&rtd); 545 if (!FirstArg) { 546 ss << ", "; 547 } else { 548 FirstArg = false; 549 } 550 ss << rtd.type->c_name << " " << (*i)->getName(); 551 } 552 } 553 554 if (isDefinition) { 555 ss << ") {"; 556 } else { 557 ss << ");"; 558 } 559} 560 561void RSReflectionCpp::makeArgs(std::stringstream &ss, const ArgTy& Args) { 562 bool FirstArg = true; 563 564 for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) { 565 if (!FirstArg) { 566 ss << ", "; 567 } else { 568 FirstArg = false; 569 } 570 571 ss << I->first << " " << I->second; 572 } 573} 574 575bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET, 576 const char *FieldPackerName) { 577 size_t AllocSize = RSExportType::GetTypeAllocSize(ET); 578 579 if (AllocSize > 0) { 580 std::stringstream ss; 581 ss << " FieldPacker " << FieldPackerName << "(" 582 << AllocSize << ");"; 583 write(ss); 584 return true; 585 } 586 587 return false; 588} 589 590void RSReflectionCpp::genPackVarOfType(const RSExportType *ET, 591 const char *VarName, 592 const char *FieldPackerName) { 593 std::stringstream ss; 594 switch (ET->getClass()) { 595 case RSExportType::ExportClassPrimitive: 596 case RSExportType::ExportClassVector: 597 case RSExportType::ExportClassPointer: 598 case RSExportType::ExportClassMatrix: { 599 RSReflectionTypeData rtd; 600 ET->convertToRTD(&rtd); 601 ss << " " << FieldPackerName << ".add(" << VarName << ");"; 602 write(ss); 603 break; 604 } 605 case RSExportType::ExportClassConstantArray: { 606 /*const RSExportConstantArrayType *ECAT = 607 static_cast<const RSExportConstantArrayType *>(ET); 608 609 // TODO(zonr): more elegant way. Currently, we obtain the unique index 610 // variable (this method involves recursive call which means 611 // we may have more than one level loop, therefore we can't 612 // always use the same index variable name here) name given 613 // in the for-loop from counting the '.' in @VarName. 614 unsigned Level = 0; 615 size_t LastDotPos = 0; 616 std::string ElementVarName(VarName); 617 618 while (LastDotPos != std::string::npos) { 619 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1); 620 Level++; 621 } 622 std::string IndexVarName("ct"); 623 IndexVarName.append(llvm::utostr_32(Level)); 624 625 C.indent() << "for (int " << IndexVarName << " = 0; " << 626 IndexVarName << " < " << ECAT->getSize() << "; " << 627 IndexVarName << "++)"; 628 C.startBlock(); 629 630 ElementVarName.append("[" + IndexVarName + "]"); 631 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(), 632 FieldPackerName); 633 634 C.endBlock();*/ 635 break; 636 } 637 case RSExportType::ExportClassRecord: { 638 const RSExportRecordType *ERT = 639 static_cast<const RSExportRecordType*>(ET); 640 // Relative pos from now on in field packer 641 unsigned Pos = 0; 642 643 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 644 E = ERT->fields_end(); 645 I != E; 646 I++) { 647 const RSExportRecordType::Field *F = *I; 648 std::string FieldName; 649 size_t FieldOffset = F->getOffsetInParent(); 650 size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); 651 size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType()); 652 653 if (VarName != NULL) 654 FieldName = VarName + ("." + F->getName()); 655 else 656 FieldName = F->getName(); 657 658 if (FieldOffset > Pos) { 659 ss.str(""); 660 ss << " " << FieldPackerName << ".skip(" 661 << (FieldOffset - Pos) << ");"; 662 write(ss); 663 } 664 665 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName); 666 667 // There is padding in the field type 668 if (FieldAllocSize > FieldStoreSize) { 669 ss.str(""); 670 ss << " " << FieldPackerName << ".skip(" 671 << (FieldAllocSize - FieldStoreSize) << ");"; 672 write(ss); 673 } 674 675 Pos = FieldOffset + FieldAllocSize; 676 } 677 678 // There maybe some padding after the struct 679 if (RSExportType::GetTypeAllocSize(ERT) > Pos) { 680 ss.str(""); 681 ss << " " << FieldPackerName << ".skip(" 682 << RSExportType::GetTypeAllocSize(ERT) - Pos << ");"; 683 write(ss); 684 } 685 break; 686 } 687 default: { 688 slangAssert(false && "Unknown class of type"); 689 } 690 } 691} 692 693} // namespace slang 694