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