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