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