slang_rs_reflection_cpp.cpp revision f9d5d13e26c451c192ea3b45137cfa685196a64c
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"; 147 mOut.startBlock(); 148 149 mOut.decreaseIndent(); 150 mOut.indent() << "private:\n"; 151 mOut.increaseIndent(); 152 153 genFieldsToStoreExportVariableValues(); 154 genTypeInstancesUsedInForEach(); 155 genFieldsForAllocationTypeVerification(); 156 157 mOut.decreaseIndent(); 158 mOut.indent() << "public:\n"; 159 mOut.increaseIndent(); 160 161 // Generate the constructor and destructor declarations. 162 mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n"; 163 mOut.indent() << "virtual ~" << mClassName << "();\n\n"; 164 165 genExportVariablesGetterAndSetter(); 166 genForEachDeclarations(); 167 genExportFunctionDeclarations(); 168 169 mOut.endBlock(true); 170 mOut.closeFile(); 171 return true; 172} 173 174void RSReflectionCpp::genTypeInstancesUsedInForEach() { 175 for (RSContext::const_export_foreach_iterator 176 I = mRSContext->export_foreach_begin(), 177 E = mRSContext->export_foreach_end(); 178 I != E; I++) { 179 const RSExportForEach *EF = *I; 180 const RSExportType *IET = EF->getInType(); 181 const RSExportType *OET = EF->getOutType(); 182 if (IET) { 183 genTypeInstanceFromPointer(IET); 184 } 185 if (OET) { 186 genTypeInstanceFromPointer(OET); 187 } 188 } 189} 190 191void RSReflectionCpp::genFieldsForAllocationTypeVerification() { 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 200void RSReflectionCpp::genFieldsToStoreExportVariableValues() { 201 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 202 E = mRSContext->export_vars_end(); 203 I != E; I++) { 204 const RSExportVar *ev = *I; 205 if (!ev->isConst()) { 206 mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX 207 << ev->getName() << ";\n"; 208 } 209 } 210} 211 212void RSReflectionCpp::genForEachDeclarations() { 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 219 if (ForEach->isDummyRoot()) { 220 mOut.indent() << "// No forEach_root(...)\n"; 221 continue; 222 } 223 224 std::string FunctionStart = "void forEach_" + ForEach->getName() + "("; 225 mOut.indent() << FunctionStart; 226 227 ArgumentList Arguments; 228 if (ForEach->hasIn()) { 229 Arguments.push_back(std::make_pair( 230 "android::RSC::sp<const android::RSC::Allocation>", "ain")); 231 } 232 233 if (ForEach->hasOut() || ForEach->hasReturn()) { 234 Arguments.push_back(std::make_pair( 235 "android::RSC::sp<const android::RSC::Allocation>", "aout")); 236 } 237 238 const RSExportRecordType *ERT = ForEach->getParamPacketType(); 239 if (ERT) { 240 for (RSExportForEach::const_param_iterator i = ForEach->params_begin(), 241 e = ForEach->params_end(); 242 i != e; i++) { 243 RSReflectionTypeData rtd; 244 (*i)->getType()->convertToRTD(&rtd); 245 Arguments.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); 246 } 247 } 248 genArguments(Arguments, FunctionStart.length()); 249 mOut << ");\n"; 250 } 251} 252 253void RSReflectionCpp::genExportFunctionDeclarations() { 254 for (RSContext::const_export_func_iterator 255 I = mRSContext->export_funcs_begin(), 256 E = mRSContext->export_funcs_end(); 257 I != E; I++) { 258 const RSExportFunc *ef = *I; 259 260 makeFunctionSignature(false, ef); 261 } 262} 263 264bool RSReflectionCpp::genEncodedBitCode() { 265 FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb"); 266 if (pfin == NULL) { 267 fprintf(stderr, "Error: could not read file %s\n", 268 mBitCodeFilePath.c_str()); 269 return false; 270 } 271 272 unsigned char buf[16]; 273 int read_length; 274 mOut.indent() << "static const unsigned char __txt[] ="; 275 mOut.startBlock(); 276 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) { 277 mOut.indent(); 278 for (int i = 0; i < read_length; i++) { 279 char buf2[16]; 280 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]); 281 mOut << buf2; 282 } 283 mOut << "\n"; 284 } 285 mOut.endBlock(true); 286 mOut << "\n"; 287 return true; 288} 289 290bool RSReflectionCpp::writeImplementationFile() { 291 if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath, 292 mRSContext->getLicenseNote(), false)) { 293 return false; 294 } 295 296 mOut.indent() << "#include \"" << mClassName << ".h\"\n\n"; 297 298 genEncodedBitCode(); 299 mOut.indent() << "\n\n"; 300 301 const std::string &packageName = mRSContext->getReflectJavaPackageName(); 302 mOut.indent() << mClassName << "::" << mClassName 303 << "(android::RSC::sp<android::RSC::RS> rs):\n" 304 " ScriptC(rs, __txt, sizeof(__txt), \"" 305 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length() 306 << ", \"/data/data/" << packageName << "/app\", sizeof(\"" 307 << packageName << "\"))"; 308 mOut.startBlock(); 309 for (std::set<std::string>::iterator I = mTypesToCheck.begin(), 310 E = mTypesToCheck.end(); 311 I != E; I++) { 312 mOut.indent() << RS_ELEM_PREFIX << *I << " = android::RSC::Element::" << *I 313 << "(mRS);\n"; 314 } 315 316 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 317 E = mRSContext->export_vars_end(); 318 I != E; I++) { 319 const RSExportVar *EV = *I; 320 if (!EV->getInit().isUninit()) { 321 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit()); 322 } else { 323 genZeroInitExportVariable(EV->getName()); 324 } 325 } 326 mOut.endBlock(); 327 328 mOut.indent() << mClassName << "::~" << mClassName << "()"; 329 mOut.startBlock(); 330 mOut.endBlock(); 331 332 // Reflect export for each functions 333 uint32_t slot = 0; 334 for (RSContext::const_export_foreach_iterator 335 I = mRSContext->export_foreach_begin(), 336 E = mRSContext->export_foreach_end(); 337 I != E; I++, slot++) { 338 const RSExportForEach *ef = *I; 339 if (ef->isDummyRoot()) { 340 mOut.indent() << "// No forEach_root(...)\n"; 341 continue; 342 } 343 344 ArgumentList Arguments; 345 std::string FunctionStart = 346 "void " + mClassName + "::forEach_" + ef->getName() + "("; 347 mOut.indent() << FunctionStart; 348 349 if (ef->hasIn()) { 350 Arguments.push_back(std::make_pair( 351 "android::RSC::sp<const android::RSC::Allocation>", "ain")); 352 } 353 354 if (ef->hasOut() || ef->hasReturn()) { 355 Arguments.push_back(std::make_pair( 356 "android::RSC::sp<const android::RSC::Allocation>", "aout")); 357 } 358 359 const RSExportRecordType *ERT = ef->getParamPacketType(); 360 if (ERT) { 361 for (RSExportForEach::const_param_iterator i = ef->params_begin(), 362 e = ef->params_end(); 363 i != e; i++) { 364 RSReflectionTypeData rtd; 365 (*i)->getType()->convertToRTD(&rtd); 366 Arguments.push_back(std::make_pair(rtd.type->c_name, (*i)->getName())); 367 } 368 } 369 genArguments(Arguments, FunctionStart.length()); 370 mOut << ")"; 371 mOut.startBlock(); 372 373 const RSExportType *IET = ef->getInType(); 374 const RSExportType *OET = ef->getOutType(); 375 if (IET) { 376 genTypeCheck(IET, "ain"); 377 } 378 if (OET) { 379 genTypeCheck(OET, "aout"); 380 } 381 382 // TODO Add the appropriate dimension checking code, as seen in 383 // slang_rs_reflection.cpp. 384 385 std::string FieldPackerName = ef->getName() + "_fp"; 386 if (ERT) { 387 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) { 388 genPackVarOfType(ERT, NULL, FieldPackerName.c_str()); 389 } 390 } 391 mOut.indent() << "forEach(" << slot << ", "; 392 393 if (ef->hasIn()) { 394 mOut << "ain, "; 395 } else { 396 mOut << "NULL, "; 397 } 398 399 if (ef->hasOut() || ef->hasReturn()) { 400 mOut << "aout, "; 401 } else { 402 mOut << "NULL, "; 403 } 404 405 // FIXME (no support for usrData with C++ kernels) 406 mOut << "NULL, 0);\n"; 407 mOut.endBlock(); 408 } 409 410 slot = 0; 411 // Reflect export function 412 for (RSContext::const_export_func_iterator 413 I = mRSContext->export_funcs_begin(), 414 E = mRSContext->export_funcs_end(); 415 I != E; I++) { 416 const RSExportFunc *ef = *I; 417 418 makeFunctionSignature(true, ef); 419 mOut.startBlock(); 420 const RSExportRecordType *params = ef->getParamPacketType(); 421 size_t param_len = 0; 422 if (params) { 423 param_len = params->getAllocSize(); 424 if (genCreateFieldPacker(params, "__fp")) { 425 genPackVarOfType(params, NULL, "__fp"); 426 } 427 } 428 429 mOut.indent() << "invoke(" << slot; 430 if (params) { 431 mOut << ", __fp.getData(), " << param_len << ");\n"; 432 } else { 433 mOut << ", NULL, 0);\n"; 434 } 435 mOut.endBlock(); 436 437 slot++; 438 } 439 440 mOut.closeFile(); 441 return true; 442} 443 444void RSReflectionCpp::genExportVariablesGetterAndSetter() { 445 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 446 E = mRSContext->export_vars_end(); 447 I != E; I++) { 448 const RSExportVar *EV = *I; 449 const RSExportType *ET = EV->getType(); 450 451 switch (ET->getClass()) { 452 case RSExportType::ExportClassPrimitive: { 453 genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV); 454 break; 455 } 456 case RSExportType::ExportClassPointer: { 457 // TODO Deprecate this. 458 genPointerTypeExportVariable(EV); 459 break; 460 } 461 case RSExportType::ExportClassVector: { 462 genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV); 463 break; 464 } 465 case RSExportType::ExportClassMatrix: { 466 genMatrixTypeExportVariable(EV); 467 break; 468 } 469 case RSExportType::ExportClassConstantArray: { 470 genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET), 471 EV); 472 break; 473 } 474 case RSExportType::ExportClassRecord: { 475 genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV); 476 break; 477 } 478 default: { slangAssert(false && "Unknown class of type"); } 479 } 480 } 481} 482 483void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT, 484 const RSExportVar *EV) { 485 RSReflectionTypeData rtd; 486 EPT->convertToRTD(&rtd); 487 std::string TypeName = GetTypeName(EPT, false); 488 489 if (!EV->isConst()) { 490 mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)"; 491 mOut.startBlock(); 492 mOut.indent() << "setVar(" << getNextExportVarSlot() << ", "; 493 if (EPT->isRSObjectType()) { 494 mOut << "v"; 495 } else { 496 mOut << "&v, sizeof(v)"; 497 } 498 mOut << ");\n"; 499 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n"; 500 mOut.endBlock(); 501 } 502 mOut.indent() << TypeName << " get_" << EV->getName() << "() const"; 503 mOut.startBlock(); 504 if (EV->isConst()) { 505 const clang::APValue &val = EV->getInit(); 506 bool isBool = !strcmp(TypeName.c_str(), "bool"); 507 mOut.indent() << "return "; 508 genInitValue(val, isBool); 509 mOut << ";\n"; 510 } else { 511 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName() 512 << ";\n"; 513 } 514 mOut.endBlock(); 515} 516 517void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) { 518 const RSExportType *ET = EV->getType(); 519 520 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && 521 "Variable should be type of pointer here"); 522 523 std::string TypeName = GetTypeName(ET); 524 std::string VarName = EV->getName(); 525 526 RSReflectionTypeData rtd; 527 EV->getType()->convertToRTD(&rtd); 528 uint32_t slot = getNextExportVarSlot(); 529 530 if (!EV->isConst()) { 531 mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)"; 532 mOut.startBlock(); 533 mOut.indent() << "bindAllocation(v, " << slot << ");\n"; 534 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 535 mOut.endBlock(); 536 } 537 mOut.indent() << TypeName << " get_" << VarName << "() const"; 538 mOut.startBlock(); 539 if (EV->isConst()) { 540 const clang::APValue &val = EV->getInit(); 541 bool isBool = !strcmp(TypeName.c_str(), "bool"); 542 mOut.indent() << "return "; 543 genInitValue(val, isBool); 544 mOut << ";\n"; 545 } else { 546 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n"; 547 } 548 mOut.endBlock(); 549} 550 551void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT, 552 const RSExportVar *EV) { 553 slangAssert(EVT != NULL); 554 555 RSReflectionTypeData rtd; 556 EVT->convertToRTD(&rtd); 557 558 if (!EV->isConst()) { 559 mOut.indent() << "void set_" << EV->getName() << "(" 560 << rtd.type->rs_c_vector_prefix << EVT->getNumElement() 561 << " v)"; 562 mOut.startBlock(); 563 mOut.indent() << "setVar(" << getNextExportVarSlot() 564 << ", &v, sizeof(v));\n"; 565 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n"; 566 mOut.endBlock(); 567 } 568 mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement() 569 << " get_" << EV->getName() << "() const"; 570 mOut.startBlock(); 571 if (EV->isConst()) { 572 const clang::APValue &val = EV->getInit(); 573 mOut.indent() << "return "; 574 genInitValue(val, false); 575 mOut << ";\n"; 576 } else { 577 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName() 578 << ";\n"; 579 } 580 mOut.endBlock(); 581} 582 583void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) { 584 slangAssert(false); 585} 586 587void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT, 588 const RSExportVar *EV) { 589 slangAssert(false); 590} 591 592void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT, 593 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