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