slang_rs_reflection_cpp.cpp revision 476d4f5a0249a3318cb86460e6a1adb2b40ecd6f
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] << ";" << std::endl; 177 //out() << std::endl; 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] << ";" << std::endl; 329 //out() << std::endl; 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 = RSExportType::GetTypeAllocSize(params); 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 = RSExportType::GetTypeAllocSize(ET); 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 size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); 763 size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType()); 764 765 if (VarName != NULL) 766 FieldName = VarName + ("." + F->getName()); 767 else 768 FieldName = F->getName(); 769 770 if (FieldOffset > Pos) { 771 ss.str(""); 772 ss << " " << FieldPackerName << ".skip(" 773 << (FieldOffset - Pos) << ");"; 774 write(ss); 775 } 776 777 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName); 778 779 // There is padding in the field type 780 if (FieldAllocSize > FieldStoreSize) { 781 ss.str(""); 782 ss << " " << FieldPackerName << ".skip(" 783 << (FieldAllocSize - FieldStoreSize) << ");"; 784 write(ss); 785 } 786 787 Pos = FieldOffset + FieldAllocSize; 788 } 789 790 // There maybe some padding after the struct 791 if (RSExportType::GetTypeAllocSize(ERT) > Pos) { 792 ss.str(""); 793 ss << " " << FieldPackerName << ".skip(" 794 << RSExportType::GetTypeAllocSize(ERT) - Pos << ");"; 795 write(ss); 796 } 797 break; 798 } 799 default: { 800 slangAssert(false && "Unknown class of type"); 801 } 802 } 803} 804 805 806void RSReflectionCpp::genTypeCheck(const RSExportType *ET, 807 const char *VarName) { 808 stringstream tmp; 809 tmp << "// Type check for " << VarName; 810 write(tmp); 811 tmp.str(""); 812 813 if (ET->getClass() == RSExportType::ExportClassPointer) { 814 const RSExportPointerType *EPT = 815 static_cast<const RSExportPointerType*>(ET); 816 ET = EPT->getPointeeType(); 817 } 818 819 std::string TypeName; 820 switch (ET->getClass()) { 821 case RSExportType::ExportClassPrimitive: 822 case RSExportType::ExportClassVector: 823 case RSExportType::ExportClassRecord: { 824 TypeName = ET->getElementName(); 825 break; 826 } 827 828 default: 829 break; 830 } 831 832 if (!TypeName.empty()) { 833 //tmp << "// TypeName: " << TypeName; 834 tmp << "if (!" << VarName 835 << "->getType()->getElement()->isCompatible(" 836 << RS_ELEM_PREFIX 837 << TypeName << ")) {"; 838 write(tmp); 839 840 incIndent(); 841 write("mRS->throwError(RS_ERROR_RUNTIME_ERROR, " 842 "\"Incompatible type\");"); 843 write("return;"); 844 decIndent(); 845 846 write("}"); 847 } 848} 849 850void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) { 851 if (ET->getClass() == RSExportType::ExportClassPointer) { 852 // For pointer parameters to original forEach kernels. 853 const RSExportPointerType *EPT = 854 static_cast<const RSExportPointerType*>(ET); 855 genTypeInstance(EPT->getPointeeType()); 856 } else { 857 // For handling pass-by-value kernel parameters. 858 genTypeInstance(ET); 859 } 860} 861 862void RSReflectionCpp::genTypeInstance(const RSExportType *ET) { 863 switch (ET->getClass()) { 864 case RSExportType::ExportClassPrimitive: 865 case RSExportType::ExportClassVector: 866 case RSExportType::ExportClassConstantArray: 867 case RSExportType::ExportClassRecord: { 868 std::string TypeName = ET->getElementName(); 869 addTypeNameForElement(TypeName); 870 break; 871 } 872 873 default: 874 break; 875 } 876} 877 878void RSReflectionCpp::genInitExportVariable(const RSExportType *ET, 879 const std::string &VarName, 880 const clang::APValue &Val) { 881 slangAssert(!Val.isUninit() && "Not a valid initializer"); 882 883 switch (ET->getClass()) { 884 case RSExportType::ExportClassPrimitive: { 885 const RSExportPrimitiveType *EPT = 886 static_cast<const RSExportPrimitiveType*>(ET); 887 if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) { 888 genInitBoolExportVariable(VarName, Val); 889 } else { 890 genInitPrimitiveExportVariable(VarName, Val); 891 } 892 break; 893 } 894 case RSExportType::ExportClassPointer: { 895 if (!Val.isInt() || Val.getInt().getSExtValue() != 0) 896 std::cerr << "Initializer which is non-NULL to pointer type variable " 897 "will be ignored" << std::endl; 898 break; 899 } 900 case RSExportType::ExportClassVector: { 901 const RSExportVectorType *EVT = 902 static_cast<const RSExportVectorType*>(ET); 903 switch (Val.getKind()) { 904 case clang::APValue::Int: 905 case clang::APValue::Float: { 906 for (unsigned i = 0; i < EVT->getNumElement(); i++) { 907 std::string Name = VarName + "." + getVectorAccessor(i); 908 genInitPrimitiveExportVariable(Name, Val); 909 } 910 break; 911 } 912 case clang::APValue::Vector: { 913 unsigned NumElements = 914 std::min(static_cast<unsigned>(EVT->getNumElement()), 915 Val.getVectorLength()); 916 for (unsigned i = 0; i < NumElements; i++) { 917 const clang::APValue &ElementVal = Val.getVectorElt(i); 918 std::string Name = VarName + "." + getVectorAccessor(i); 919 genInitPrimitiveExportVariable(Name, ElementVal); 920 } 921 break; 922 } 923 case clang::APValue::MemberPointer: 924 case clang::APValue::Uninitialized: 925 case clang::APValue::ComplexInt: 926 case clang::APValue::ComplexFloat: 927 case clang::APValue::LValue: 928 case clang::APValue::Array: 929 case clang::APValue::Struct: 930 case clang::APValue::Union: 931 case clang::APValue::AddrLabelDiff: { 932 slangAssert(false && "Unexpected type of value of initializer."); 933 } 934 } 935 break; 936 } 937 case RSExportType::ExportClassMatrix: 938 case RSExportType::ExportClassConstantArray: 939 case RSExportType::ExportClassRecord: { 940 slangAssert(false && "Unsupported initializer for record/matrix/constant " 941 "array type variable currently"); 942 break; 943 } 944 default: { 945 slangAssert(false && "Unknown class of type"); 946 } 947 } 948 return; 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