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