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