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