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