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