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