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 40 using namespace std; 41 42 namespace slang { 43 44 #define RS_TYPE_ITEM_CLASS_NAME "Item" 45 46 #define RS_ELEM_PREFIX "__rs_elem_" 47 48 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) { 49 static const char *MatrixTypeCNameMap[] = { 50 "rs_matrix2x2", 51 "rs_matrix3x3", 52 "rs_matrix4x4", 53 }; 54 unsigned Dim = EMT->getDim(); 55 56 if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char*))) 57 return MatrixTypeCNameMap[ EMT->getDim() - 2 ]; 58 59 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension"); 60 return NULL; 61 } 62 63 64 static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) { 65 switch (ET->getClass()) { 66 case RSExportType::ExportClassPrimitive: { 67 return RSExportPrimitiveType::getRSReflectionType( 68 static_cast<const RSExportPrimitiveType*>(ET))->c_name; 69 } 70 case RSExportType::ExportClassPointer: { 71 const RSExportType *PointeeType = 72 static_cast<const RSExportPointerType*>(ET)->getPointeeType(); 73 74 if (PointeeType->getClass() != RSExportType::ExportClassRecord) 75 return "android::RSC::sp<android::RSC::Allocation>"; 76 else 77 return PointeeType->getElementName(); 78 } 79 case RSExportType::ExportClassVector: { 80 const RSExportVectorType *EVT = 81 static_cast<const RSExportVectorType*>(ET); 82 std::stringstream VecName; 83 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix 84 << EVT->getNumElement(); 85 return VecName.str(); 86 } 87 case RSExportType::ExportClassMatrix: { 88 return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET)); 89 } 90 case RSExportType::ExportClassConstantArray: { 91 // TODO: Fix this for C arrays! 92 const RSExportConstantArrayType* CAT = 93 static_cast<const RSExportConstantArrayType*>(ET); 94 std::string ElementTypeName = GetTypeName(CAT->getElementType()); 95 if (Brackets) { 96 ElementTypeName.append("[]"); 97 } 98 return ElementTypeName; 99 } 100 case RSExportType::ExportClassRecord: { 101 // TODO: Fix for C structs! 102 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME; 103 } 104 default: { 105 slangAssert(false && "Unknown class of type"); 106 } 107 } 108 109 return ""; 110 } 111 112 113 RSReflectionCpp::RSReflectionCpp(const RSContext *con) 114 : RSReflectionBase(con) { 115 clear(); 116 } 117 118 RSReflectionCpp::~RSReflectionCpp() { 119 } 120 121 bool RSReflectionCpp::reflect(const string &OutputPathBase, 122 const string &InputFileName, 123 const string &OutputBCFileName) { 124 mInputFileName = InputFileName; 125 mOutputPath = OutputPathBase; 126 mOutputBCFileName = OutputBCFileName; 127 mClassName = string("ScriptC_") + stripRS(InputFileName); 128 129 makeHeader("android::RSC::ScriptC"); 130 std::vector< std::string > header(mText); 131 mText.clear(); 132 133 makeImpl("android::RSC::ScriptC"); 134 std::vector< std::string > cpp(mText); 135 mText.clear(); 136 137 138 writeFile(mClassName + ".h", header); 139 writeFile(mClassName + ".cpp", cpp); 140 141 142 return true; 143 } 144 145 146 #define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_" 147 148 149 150 bool RSReflectionCpp::makeHeader(const std::string &baseClass) { 151 startFile(mClassName + ".h"); 152 153 write(""); 154 write("#include \"RenderScript.h\""); 155 write("using namespace android::RSC;"); 156 write(""); 157 158 // Imports 159 //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 160 //out() << "import " << Import[i] << ";" << std::endl; 161 //out() << std::endl; 162 163 if (!baseClass.empty()) { 164 write("class " + mClassName + " : public " + baseClass + " {"); 165 } else { 166 write("class " + mClassName + " {"); 167 } 168 169 write("private:"); 170 uint32_t slot = 0; 171 incIndent(); 172 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 173 E = mRSContext->export_vars_end(); I != E; I++, slot++) { 174 const RSExportVar *ev = *I; 175 if (!ev->isConst()) { 176 write(GetTypeName(ev->getType()) + " " RS_EXPORT_VAR_PREFIX 177 + ev->getName() + ";"); 178 } 179 } 180 181 for (RSContext::const_export_foreach_iterator 182 I = mRSContext->export_foreach_begin(), 183 E = mRSContext->export_foreach_end(); I != E; I++) { 184 const RSExportForEach *EF = *I; 185 const RSExportType *IET = EF->getInType(); 186 const RSExportType *OET = EF->getOutType(); 187 if (IET) { 188 genTypeInstanceFromPointer(IET); 189 } 190 if (OET) { 191 genTypeInstanceFromPointer(OET); 192 } 193 } 194 195 for (std::set<std::string>::iterator I = mTypesToCheck.begin(), 196 E = mTypesToCheck.end(); 197 I != E; 198 I++) { 199 write("android::RSC::sp<const android::RSC::Element> " RS_ELEM_PREFIX 200 + *I + ";"); 201 } 202 203 decIndent(); 204 205 write("public:"); 206 incIndent(); 207 write(mClassName + "(android::RSC::sp<android::RSC::RS> rs);"); 208 write("virtual ~" + mClassName + "();"); 209 write(""); 210 211 212 // Reflect export variable 213 slot = 0; 214 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 215 E = mRSContext->export_vars_end(); I != E; I++, slot++) { 216 genExportVariable(*I); 217 } 218 219 // Reflect export for each functions 220 for (RSContext::const_export_foreach_iterator 221 I = mRSContext->export_foreach_begin(), 222 E = mRSContext->export_foreach_end(); I != E; I++) { 223 const RSExportForEach *ef = *I; 224 if (ef->isDummyRoot()) { 225 write("// No forEach_root(...)"); 226 continue; 227 } 228 229 ArgTy Args; 230 stringstream ss; 231 ss << "void forEach_" << ef->getName() << "("; 232 233 if (ef->hasIn()) { 234 Args.push_back(std::make_pair( 235 "android::RSC::sp<const android::RSC::Allocation>", "ain")); 236 } 237 238 if (ef->hasOut() || ef->hasReturn()) { 239 Args.push_back(std::make_pair( 240 "android::RSC::sp<const android::RSC::Allocation>", "aout")); 241 } 242 243 const RSExportRecordType *ERT = ef->getParamPacketType(); 244 if (ERT) { 245 for (RSExportForEach::const_param_iterator i = ef->params_begin(), 246 e = ef->params_end(); i != e; i++) { 247 RSReflectionTypeData rtd; 248 (*i)->getType()->convertToRTD(&rtd); 249 Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); 250 } 251 } 252 makeArgs(ss, Args); 253 ss << ");"; 254 write(ss); 255 } 256 257 258 // Reflect export function 259 for (RSContext::const_export_func_iterator 260 I = mRSContext->export_funcs_begin(), 261 E = mRSContext->export_funcs_end(); I != E; I++) { 262 const RSExportFunc *ef = *I; 263 264 stringstream ss; 265 makeFunctionSignature(ss, false, ef); 266 write(ss); 267 } 268 269 decIndent(); 270 write("};"); 271 return true; 272 } 273 274 bool RSReflectionCpp::writeBC() { 275 FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb"); 276 if (pfin == NULL) { 277 fprintf(stderr, "Error: could not read file %s\n", 278 mOutputBCFileName.c_str()); 279 return false; 280 } 281 282 unsigned char buf[16]; 283 int read_length; 284 write("static const unsigned char __txt[] = {"); 285 incIndent(); 286 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) { 287 string s; 288 for (int i = 0; i < read_length; i++) { 289 char buf2[16]; 290 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]); 291 s += buf2; 292 } 293 write(s); 294 } 295 decIndent(); 296 write("};"); 297 write(""); 298 return true; 299 } 300 301 bool RSReflectionCpp::makeImpl(const std::string &baseClass) { 302 startFile(mClassName + ".cpp"); 303 304 write(""); 305 write("#include \"" + mClassName + ".h\""); 306 write(""); 307 308 writeBC(); 309 310 // Imports 311 //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 312 //out() << "import " << Import[i] << ";" << std::endl; 313 //out() << std::endl; 314 315 write("\n"); 316 stringstream ss; 317 const std::string &packageName = mRSContext->getReflectJavaPackageName(); 318 ss << mClassName << "::" << mClassName 319 << "(android::RSC::sp<android::RSC::RS> rs):\n" 320 " ScriptC(rs, __txt, sizeof(__txt), \"" 321 << stripRS(mInputFileName) << "\", " << stripRS(mInputFileName).length() 322 << ", \"/data/data/" << packageName << "/app\", sizeof(\"" << packageName << "\")) {"; 323 write(ss); 324 ss.str(""); 325 incIndent(); 326 for (std::set<std::string>::iterator I = mTypesToCheck.begin(), 327 E = mTypesToCheck.end(); 328 I != E; 329 I++) { 330 write(RS_ELEM_PREFIX + *I + " = android::RSC::Element::" + *I + "(mRS);"); 331 } 332 333 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 334 E = mRSContext->export_vars_end(); 335 I != E; 336 I++) { 337 const RSExportVar *EV = *I; 338 if (!EV->getInit().isUninit()) { 339 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit()); 340 } else { 341 genZeroInitExportVariable(EV->getName()); 342 } 343 } 344 decIndent(); 345 write("}"); 346 write(""); 347 348 write(mClassName + "::~" + mClassName + "() {"); 349 write("}"); 350 write(""); 351 352 // Reflect export for each functions 353 uint32_t slot = 0; 354 for (RSContext::const_export_foreach_iterator 355 I = mRSContext->export_foreach_begin(), 356 E = mRSContext->export_foreach_end(); I != E; I++, slot++) { 357 const RSExportForEach *ef = *I; 358 if (ef->isDummyRoot()) { 359 write("// No forEach_root(...)"); 360 continue; 361 } 362 363 stringstream tmp; 364 ArgTy Args; 365 tmp << "void " << mClassName << "::forEach_" << ef->getName() << "("; 366 367 if (ef->hasIn()) { 368 Args.push_back(std::make_pair( 369 "android::RSC::sp<const android::RSC::Allocation>", "ain")); 370 } 371 372 if (ef->hasOut() || ef->hasReturn()) { 373 Args.push_back(std::make_pair( 374 "android::RSC::sp<const android::RSC::Allocation>", "aout")); 375 } 376 377 const RSExportRecordType *ERT = ef->getParamPacketType(); 378 if (ERT) { 379 for (RSExportForEach::const_param_iterator i = ef->params_begin(), 380 e = ef->params_end(); i != e; i++) { 381 RSReflectionTypeData rtd; 382 (*i)->getType()->convertToRTD(&rtd); 383 Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); 384 } 385 } 386 makeArgs(tmp, Args); 387 388 tmp << ") {"; 389 write(tmp); 390 tmp.str(""); 391 392 const RSExportType *IET = ef->getInType(); 393 const RSExportType *OET = ef->getOutType(); 394 395 incIndent(); 396 if (IET) { 397 genTypeCheck(IET, "ain"); 398 } 399 400 if (OET) { 401 genTypeCheck(OET, "aout"); 402 } 403 decIndent(); 404 405 std::string FieldPackerName = ef->getName() + "_fp"; 406 if (ERT) { 407 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) { 408 genPackVarOfType(ERT, NULL, FieldPackerName.c_str()); 409 } 410 } 411 tmp << " forEach(" << slot << ", "; 412 413 if (ef->hasIn()) { 414 tmp << "ain, "; 415 } else { 416 tmp << "NULL, "; 417 } 418 419 if (ef->hasOut() || ef->hasReturn()) { 420 tmp << "aout, "; 421 } else { 422 tmp << "NULL, "; 423 } 424 425 // FIXME (no support for usrData with C++ kernels) 426 tmp << "NULL, 0);"; 427 write(tmp); 428 429 write("}"); 430 write(""); 431 } 432 433 slot = 0; 434 // Reflect export function 435 for (RSContext::const_export_func_iterator 436 I = mRSContext->export_funcs_begin(), 437 E = mRSContext->export_funcs_end(); I != E; I++) { 438 const RSExportFunc *ef = *I; 439 440 stringstream ss; 441 makeFunctionSignature(ss, true, ef); 442 write(ss); 443 ss.str(""); 444 const RSExportRecordType *params = ef->getParamPacketType(); 445 size_t param_len = 0; 446 if (params) { 447 param_len = RSExportType::GetTypeAllocSize(params); 448 if (genCreateFieldPacker(params, "__fp")) { 449 genPackVarOfType(params, NULL, "__fp"); 450 } 451 } 452 453 ss.str(""); 454 ss << " invoke(" << slot; 455 if (params) { 456 ss << ", __fp.getData(), " << param_len << ");"; 457 } else { 458 ss << ", NULL, 0);"; 459 } 460 write(ss); 461 462 write("}"); 463 write(""); 464 465 slot++; 466 } 467 468 decIndent(); 469 return true; 470 } 471 472 void RSReflectionCpp::genExportVariable(const RSExportVar *EV) { 473 const RSExportType *ET = EV->getType(); 474 475 switch (ET->getClass()) { 476 case RSExportType::ExportClassPrimitive: { 477 genPrimitiveTypeExportVariable(EV); 478 break; 479 } 480 case RSExportType::ExportClassPointer: { 481 genPointerTypeExportVariable(EV); 482 break; 483 } 484 case RSExportType::ExportClassVector: { 485 genVectorTypeExportVariable(EV); 486 break; 487 } 488 case RSExportType::ExportClassMatrix: { 489 genMatrixTypeExportVariable(EV); 490 break; 491 } 492 case RSExportType::ExportClassConstantArray: { 493 genConstantArrayTypeExportVariable(EV); 494 break; 495 } 496 case RSExportType::ExportClassRecord: { 497 genRecordTypeExportVariable(EV); 498 break; 499 } 500 default: { 501 slangAssert(false && "Unknown class of type"); 502 } 503 } 504 } 505 506 507 void RSReflectionCpp::genPrimitiveTypeExportVariable(const RSExportVar *EV) { 508 RSReflectionTypeData rtd; 509 EV->getType()->convertToRTD(&rtd); 510 511 if (!EV->isConst()) { 512 write(string("void set_") + EV->getName() + "(" + rtd.type->c_name + 513 " v) {"); 514 stringstream tmp; 515 tmp << getNextExportVarSlot(); 516 write(string(" setVar(") + tmp.str() + ", &v, sizeof(v));"); 517 write(string(" " RS_EXPORT_VAR_PREFIX) + EV->getName() + " = v;"); 518 write("}"); 519 } 520 write(string(rtd.type->c_name) + " get_" + EV->getName() + "() const {"); 521 if (EV->isConst()) { 522 const clang::APValue &val = EV->getInit(); 523 bool isBool = !strcmp(rtd.type->c_name, "bool"); 524 write(string(" return ") + genInitValue(val, isBool) + ";"); 525 } else { 526 write(string(" return " RS_EXPORT_VAR_PREFIX) + EV->getName() + ";"); 527 } 528 write("}"); 529 write(""); 530 } 531 532 void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) { 533 const RSExportType *ET = EV->getType(); 534 535 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && 536 "Variable should be type of pointer here"); 537 538 std::string TypeName = GetTypeName(ET); 539 std::string VarName = EV->getName(); 540 541 RSReflectionTypeData rtd; 542 EV->getType()->convertToRTD(&rtd); 543 uint32_t slot = getNextExportVarSlot(); 544 545 if (!EV->isConst()) { 546 write(string("void bind_") + VarName + "(" + TypeName + 547 " v) {"); 548 stringstream tmp; 549 tmp << slot; 550 write(string(" bindAllocation(v, ") + tmp.str() + ");"); 551 write(string(" " RS_EXPORT_VAR_PREFIX) + VarName + " = v;"); 552 write("}"); 553 } 554 write(TypeName + " get_" + VarName + "() const {"); 555 if (EV->isConst()) { 556 const clang::APValue &val = EV->getInit(); 557 bool isBool = !strcmp(TypeName.c_str(), "bool"); 558 write(string(" return ") + genInitValue(val, isBool) + ";"); 559 } else { 560 write(string(" return " RS_EXPORT_VAR_PREFIX) + VarName + ";"); 561 } 562 write("}"); 563 write(""); 564 565 } 566 567 void RSReflectionCpp::genVectorTypeExportVariable(const RSExportVar *EV) { 568 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) && 569 "Variable should be type of vector here"); 570 571 const RSExportVectorType *EVT = 572 static_cast<const RSExportVectorType*>(EV->getType()); 573 slangAssert(EVT != NULL); 574 575 RSReflectionTypeData rtd; 576 EVT->convertToRTD(&rtd); 577 578 std::stringstream ss; 579 580 if (!EV->isConst()) { 581 ss << "void set_" << EV->getName() << "(" << rtd.type->rs_c_vector_prefix 582 << EVT->getNumElement() << " v) {"; 583 write(ss); 584 ss.str(""); 585 ss << getNextExportVarSlot(); 586 write(string(" setVar(") + ss.str() + ", &v, sizeof(v));"); 587 ss.str(""); 588 write(string(" " RS_EXPORT_VAR_PREFIX) + EV->getName() + " = v;"); 589 write("}"); 590 } 591 ss << rtd.type->rs_c_vector_prefix << EVT->getNumElement() << " get_" 592 << EV->getName() << "() const {"; 593 write(ss); 594 ss.str(""); 595 if (EV->isConst()) { 596 const clang::APValue &val = EV->getInit(); 597 write(string(" return ") + genInitValue(val, false) + ";"); 598 } else { 599 write(string(" return " RS_EXPORT_VAR_PREFIX) + EV->getName() + ";"); 600 } 601 write("}"); 602 write(""); 603 } 604 605 void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) { 606 slangAssert(false); 607 } 608 609 void RSReflectionCpp::genConstantArrayTypeExportVariable( 610 const RSExportVar *EV) { 611 slangAssert(false); 612 } 613 614 void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) { 615 slangAssert(false); 616 } 617 618 619 void RSReflectionCpp::makeFunctionSignature( 620 std::stringstream &ss, 621 bool isDefinition, 622 const RSExportFunc *ef) { 623 ss << "void "; 624 if (isDefinition) { 625 ss << mClassName << "::"; 626 } 627 ss << "invoke_" << ef->getName() << "("; 628 629 if (ef->getParamPacketType()) { 630 bool FirstArg = true; 631 for (RSExportFunc::const_param_iterator i = ef->params_begin(), 632 e = ef->params_end(); i != e; i++) { 633 RSReflectionTypeData rtd; 634 (*i)->getType()->convertToRTD(&rtd); 635 if (!FirstArg) { 636 ss << ", "; 637 } else { 638 FirstArg = false; 639 } 640 ss << rtd.type->c_name << " " << (*i)->getName(); 641 } 642 } 643 644 if (isDefinition) { 645 ss << ") {"; 646 } else { 647 ss << ");"; 648 } 649 } 650 651 void RSReflectionCpp::makeArgs(std::stringstream &ss, const ArgTy& Args) { 652 bool FirstArg = true; 653 654 for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) { 655 if (!FirstArg) { 656 ss << ", "; 657 } else { 658 FirstArg = false; 659 } 660 661 ss << I->first << " " << I->second; 662 } 663 } 664 665 bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET, 666 const char *FieldPackerName) { 667 size_t AllocSize = RSExportType::GetTypeAllocSize(ET); 668 669 if (AllocSize > 0) { 670 std::stringstream ss; 671 ss << " FieldPacker " << FieldPackerName << "(" 672 << AllocSize << ");"; 673 write(ss); 674 return true; 675 } 676 677 return false; 678 } 679 680 void RSReflectionCpp::genPackVarOfType(const RSExportType *ET, 681 const char *VarName, 682 const char *FieldPackerName) { 683 std::stringstream ss; 684 switch (ET->getClass()) { 685 case RSExportType::ExportClassPrimitive: 686 case RSExportType::ExportClassVector: 687 case RSExportType::ExportClassPointer: 688 case RSExportType::ExportClassMatrix: { 689 ss << " " << FieldPackerName << ".add(" << VarName << ");"; 690 write(ss); 691 break; 692 } 693 case RSExportType::ExportClassConstantArray: { 694 /*const RSExportConstantArrayType *ECAT = 695 static_cast<const RSExportConstantArrayType *>(ET); 696 697 // TODO(zonr): more elegant way. Currently, we obtain the unique index 698 // variable (this method involves recursive call which means 699 // we may have more than one level loop, therefore we can't 700 // always use the same index variable name here) name given 701 // in the for-loop from counting the '.' in @VarName. 702 unsigned Level = 0; 703 size_t LastDotPos = 0; 704 std::string ElementVarName(VarName); 705 706 while (LastDotPos != std::string::npos) { 707 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1); 708 Level++; 709 } 710 std::string IndexVarName("ct"); 711 IndexVarName.append(llvm::utostr_32(Level)); 712 713 C.indent() << "for (int " << IndexVarName << " = 0; " << 714 IndexVarName << " < " << ECAT->getSize() << "; " << 715 IndexVarName << "++)"; 716 C.startBlock(); 717 718 ElementVarName.append("[" + IndexVarName + "]"); 719 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(), 720 FieldPackerName); 721 722 C.endBlock();*/ 723 break; 724 } 725 case RSExportType::ExportClassRecord: { 726 const RSExportRecordType *ERT = 727 static_cast<const RSExportRecordType*>(ET); 728 // Relative pos from now on in field packer 729 unsigned Pos = 0; 730 731 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 732 E = ERT->fields_end(); 733 I != E; 734 I++) { 735 const RSExportRecordType::Field *F = *I; 736 std::string FieldName; 737 size_t FieldOffset = F->getOffsetInParent(); 738 size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); 739 size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType()); 740 741 if (VarName != NULL) 742 FieldName = VarName + ("." + F->getName()); 743 else 744 FieldName = F->getName(); 745 746 if (FieldOffset > Pos) { 747 ss.str(""); 748 ss << " " << FieldPackerName << ".skip(" 749 << (FieldOffset - Pos) << ");"; 750 write(ss); 751 } 752 753 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName); 754 755 // There is padding in the field type 756 if (FieldAllocSize > FieldStoreSize) { 757 ss.str(""); 758 ss << " " << FieldPackerName << ".skip(" 759 << (FieldAllocSize - FieldStoreSize) << ");"; 760 write(ss); 761 } 762 763 Pos = FieldOffset + FieldAllocSize; 764 } 765 766 // There maybe some padding after the struct 767 if (RSExportType::GetTypeAllocSize(ERT) > Pos) { 768 ss.str(""); 769 ss << " " << FieldPackerName << ".skip(" 770 << RSExportType::GetTypeAllocSize(ERT) - Pos << ");"; 771 write(ss); 772 } 773 break; 774 } 775 default: { 776 slangAssert(false && "Unknown class of type"); 777 } 778 } 779 } 780 781 782 void RSReflectionCpp::genTypeCheck(const RSExportType *ET, 783 const char *VarName) { 784 stringstream tmp; 785 tmp << "// Type check for " << VarName; 786 write(tmp); 787 tmp.str(""); 788 789 if (ET->getClass() == RSExportType::ExportClassPointer) { 790 const RSExportPointerType *EPT = 791 static_cast<const RSExportPointerType*>(ET); 792 ET = EPT->getPointeeType(); 793 } 794 795 std::string TypeName; 796 switch (ET->getClass()) { 797 case RSExportType::ExportClassPrimitive: 798 case RSExportType::ExportClassVector: 799 case RSExportType::ExportClassRecord: { 800 TypeName = ET->getElementName(); 801 break; 802 } 803 804 default: 805 break; 806 } 807 808 if (!TypeName.empty()) { 809 //tmp << "// TypeName: " << TypeName; 810 tmp << "if (!" << VarName 811 << "->getType()->getElement()->isCompatible(" 812 << RS_ELEM_PREFIX 813 << TypeName << ")) {"; 814 write(tmp); 815 816 incIndent(); 817 write("mRS->throwError(RS_ERROR_RUNTIME_ERROR, " 818 "\"Incompatible type\");"); 819 write("return;"); 820 decIndent(); 821 822 write("}"); 823 } 824 } 825 826 void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) { 827 if (ET->getClass() == RSExportType::ExportClassPointer) { 828 // For pointer parameters to original forEach kernels. 829 const RSExportPointerType *EPT = 830 static_cast<const RSExportPointerType*>(ET); 831 genTypeInstance(EPT->getPointeeType()); 832 } else { 833 // For handling pass-by-value kernel parameters. 834 genTypeInstance(ET); 835 } 836 } 837 838 void RSReflectionCpp::genTypeInstance(const RSExportType *ET) { 839 switch (ET->getClass()) { 840 case RSExportType::ExportClassPrimitive: 841 case RSExportType::ExportClassVector: 842 case RSExportType::ExportClassConstantArray: 843 case RSExportType::ExportClassRecord: { 844 std::string TypeName = ET->getElementName(); 845 addTypeNameForElement(TypeName); 846 break; 847 } 848 849 default: 850 break; 851 } 852 } 853 854 void RSReflectionCpp::genInitExportVariable(const RSExportType *ET, 855 const std::string &VarName, 856 const clang::APValue &Val) { 857 slangAssert(!Val.isUninit() && "Not a valid initializer"); 858 859 switch (ET->getClass()) { 860 case RSExportType::ExportClassPrimitive: { 861 const RSExportPrimitiveType *EPT = 862 static_cast<const RSExportPrimitiveType*>(ET); 863 if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) { 864 genInitBoolExportVariable(VarName, Val); 865 } else { 866 genInitPrimitiveExportVariable(VarName, Val); 867 } 868 break; 869 } 870 case RSExportType::ExportClassPointer: { 871 if (!Val.isInt() || Val.getInt().getSExtValue() != 0) 872 std::cerr << "Initializer which is non-NULL to pointer type variable " 873 "will be ignored" << std::endl; 874 break; 875 } 876 case RSExportType::ExportClassVector: { 877 const RSExportVectorType *EVT = 878 static_cast<const RSExportVectorType*>(ET); 879 switch (Val.getKind()) { 880 case clang::APValue::Int: 881 case clang::APValue::Float: { 882 for (unsigned i = 0; i < EVT->getNumElement(); i++) { 883 std::string Name = VarName + "." + getVectorAccessor(i); 884 genInitPrimitiveExportVariable(Name, Val); 885 } 886 break; 887 } 888 case clang::APValue::Vector: { 889 unsigned NumElements = 890 std::min(static_cast<unsigned>(EVT->getNumElement()), 891 Val.getVectorLength()); 892 for (unsigned i = 0; i < NumElements; i++) { 893 const clang::APValue &ElementVal = Val.getVectorElt(i); 894 std::string Name = VarName + "." + getVectorAccessor(i); 895 genInitPrimitiveExportVariable(Name, ElementVal); 896 } 897 break; 898 } 899 case clang::APValue::MemberPointer: 900 case clang::APValue::Uninitialized: 901 case clang::APValue::ComplexInt: 902 case clang::APValue::ComplexFloat: 903 case clang::APValue::LValue: 904 case clang::APValue::Array: 905 case clang::APValue::Struct: 906 case clang::APValue::Union: 907 case clang::APValue::AddrLabelDiff: { 908 slangAssert(false && "Unexpected type of value of initializer."); 909 } 910 } 911 break; 912 } 913 case RSExportType::ExportClassMatrix: 914 case RSExportType::ExportClassConstantArray: 915 case RSExportType::ExportClassRecord: { 916 slangAssert(false && "Unsupported initializer for record/matrix/constant " 917 "array type variable currently"); 918 break; 919 } 920 default: { 921 slangAssert(false && "Unknown class of type"); 922 } 923 } 924 return; 925 } 926 927 void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) { 928 std::stringstream ss; 929 ss << "memset(&" RS_EXPORT_VAR_PREFIX << VarName << ", 0, sizeof(" 930 << RS_EXPORT_VAR_PREFIX << VarName << "));"; 931 write(ss); 932 } 933 934 void RSReflectionCpp::genInitPrimitiveExportVariable( 935 const std::string &VarName, 936 const clang::APValue &Val) { 937 slangAssert(!Val.isUninit() && "Not a valid initializer"); 938 939 std::stringstream ss; 940 ss << RS_EXPORT_VAR_PREFIX << VarName << " = " 941 << RSReflectionBase::genInitValue(Val) << ";"; 942 write(ss); 943 } 944 945 void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName, 946 const clang::APValue &Val) { 947 slangAssert(!Val.isUninit() && "Not a valid initializer"); 948 slangAssert((Val.getKind() == clang::APValue::Int) && 949 "Bool type has wrong initial APValue"); 950 951 std::stringstream ss; 952 ss << RS_EXPORT_VAR_PREFIX << VarName << " = " 953 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true") << ";"; 954 write(ss); 955 } 956 957 } // namespace slang 958