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