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