1 2 /* 3 * Copyright 2010-2014, The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include "slang_rs_reflection.h" 19 20 #include <sys/stat.h> 21 22 #include <cstdarg> 23 #include <cctype> 24 25 #include <algorithm> 26 #include <sstream> 27 #include <string> 28 #include <utility> 29 30 #include "llvm/ADT/APFloat.h" 31 #include "llvm/ADT/StringExtras.h" 32 33 #include "os_sep.h" 34 #include "slang_rs_context.h" 35 #include "slang_rs_export_var.h" 36 #include "slang_rs_export_foreach.h" 37 #include "slang_rs_export_func.h" 38 #include "slang_rs_reflect_utils.h" 39 #include "slang_version.h" 40 41 #define RS_SCRIPT_CLASS_NAME_PREFIX "ScriptC_" 42 #define RS_SCRIPT_CLASS_SUPER_CLASS_NAME "ScriptC" 43 44 #define RS_TYPE_CLASS_SUPER_CLASS_NAME ".Script.FieldBase" 45 46 #define RS_TYPE_ITEM_CLASS_NAME "Item" 47 48 #define RS_TYPE_ITEM_SIZEOF_LEGACY "Item.sizeof" 49 #define RS_TYPE_ITEM_SIZEOF_CURRENT "mElement.getBytesSize()" 50 51 #define RS_TYPE_ITEM_BUFFER_NAME "mItemArray" 52 #define RS_TYPE_ITEM_BUFFER_PACKER_NAME "mIOBuffer" 53 #define RS_TYPE_ELEMENT_REF_NAME "mElementCache" 54 55 #define RS_EXPORT_VAR_INDEX_PREFIX "mExportVarIdx_" 56 #define RS_EXPORT_VAR_PREFIX "mExportVar_" 57 #define RS_EXPORT_VAR_ELEM_PREFIX "mExportVarElem_" 58 #define RS_EXPORT_VAR_DIM_PREFIX "mExportVarDim_" 59 #define RS_EXPORT_VAR_CONST_PREFIX "const_" 60 61 #define RS_ELEM_PREFIX "__" 62 63 #define RS_FP_PREFIX "__rs_fp_" 64 65 #define RS_RESOURCE_NAME "__rs_resource_name" 66 67 #define RS_EXPORT_FUNC_INDEX_PREFIX "mExportFuncIdx_" 68 #define RS_EXPORT_FOREACH_INDEX_PREFIX "mExportForEachIdx_" 69 70 #define RS_EXPORT_VAR_ALLOCATION_PREFIX "mAlloction_" 71 #define RS_EXPORT_VAR_DATA_STORAGE_PREFIX "mData_" 72 73 namespace slang { 74 75 class RSReflectionJavaElementBuilder { 76 public: 77 RSReflectionJavaElementBuilder(const char *ElementBuilderName, 78 const RSExportRecordType *ERT, 79 const char *RenderScriptVar, 80 GeneratedFile *Out, const RSContext *RSContext, 81 RSReflectionJava *Reflection); 82 void generate(); 83 84 private: 85 void genAddElement(const RSExportType *ET, const std::string &VarName, 86 unsigned ArraySize); 87 void genAddStatementStart(); 88 void genAddStatementEnd(const std::string &VarName, unsigned ArraySize); 89 void genAddPadding(int PaddingSize); 90 // TODO Will remove later due to field name information is not necessary for 91 // C-reflect-to-Java 92 std::string createPaddingField() { 93 return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++); 94 } 95 96 const char *mElementBuilderName; 97 const RSExportRecordType *mERT; 98 const char *mRenderScriptVar; 99 GeneratedFile *mOut; 100 std::string mPaddingPrefix; 101 int mPaddingFieldIndex; 102 const RSContext *mRSContext; 103 RSReflectionJava *mReflection; 104 }; 105 106 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) { 107 static const char *MatrixTypeJavaNameMap[] = {/* 2x2 */ "Matrix2f", 108 /* 3x3 */ "Matrix3f", 109 /* 4x4 */ "Matrix4f", 110 }; 111 unsigned Dim = EMT->getDim(); 112 113 if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char *))) 114 return MatrixTypeJavaNameMap[EMT->getDim() - 2]; 115 116 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension"); 117 return nullptr; 118 } 119 120 static const char *GetVectorAccessor(unsigned Index) { 121 static const char *VectorAccessorMap[] = {/* 0 */ "x", 122 /* 1 */ "y", 123 /* 2 */ "z", 124 /* 3 */ "w", 125 }; 126 127 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) && 128 "Out-of-bound index to access vector member"); 129 130 return VectorAccessorMap[Index]; 131 } 132 133 static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) { 134 static const char *PrimitiveTypePackerAPINameMap[] = { 135 "addF16", // DataTypeFloat16 136 "addF32", // DataTypeFloat32 137 "addF64", // DataTypeFloat64 138 "addI8", // DataTypeSigned8 139 "addI16", // DataTypeSigned16 140 "addI32", // DataTypeSigned32 141 "addI64", // DataTypeSigned64 142 "addU8", // DataTypeUnsigned8 143 "addU16", // DataTypeUnsigned16 144 "addU32", // DataTypeUnsigned32 145 "addU64", // DataTypeUnsigned64 146 "addBoolean", // DataTypeBoolean 147 "addU16", // DataTypeUnsigned565 148 "addU16", // DataTypeUnsigned5551 149 "addU16", // DataTypeUnsigned4444 150 "addMatrix", // DataTypeRSMatrix2x2 151 "addMatrix", // DataTypeRSMatrix3x3 152 "addMatrix", // DataTypeRSMatrix4x4 153 "addObj", // DataTypeRSElement 154 "addObj", // DataTypeRSType 155 "addObj", // DataTypeRSAllocation 156 "addObj", // DataTypeRSSampler 157 "addObj", // DataTypeRSScript 158 "addObj", // DataTypeRSMesh 159 "addObj", // DataTypeRSPath 160 "addObj", // DataTypeRSProgramFragment 161 "addObj", // DataTypeRSProgramVertex 162 "addObj", // DataTypeRSProgramRaster 163 "addObj", // DataTypeRSProgramStore 164 "addObj", // DataTypeRSFont 165 }; 166 unsigned TypeId = EPT->getType(); 167 168 if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char *))) 169 return PrimitiveTypePackerAPINameMap[EPT->getType()]; 170 171 slangAssert(false && "GetPackerAPIName : Unknown primitive data type"); 172 return nullptr; 173 } 174 175 static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) { 176 switch (ET->getClass()) { 177 case RSExportType::ExportClassPrimitive: { 178 return RSExportPrimitiveType::getRSReflectionType( 179 static_cast<const RSExportPrimitiveType *>(ET))->java_name; 180 } 181 case RSExportType::ExportClassPointer: { 182 const RSExportType *PointeeType = 183 static_cast<const RSExportPointerType *>(ET)->getPointeeType(); 184 185 if (PointeeType->getClass() != RSExportType::ExportClassRecord) 186 return "Allocation"; 187 else 188 return PointeeType->getElementName(); 189 } 190 case RSExportType::ExportClassVector: { 191 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET); 192 std::stringstream VecName; 193 VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix 194 << EVT->getNumElement(); 195 return VecName.str(); 196 } 197 case RSExportType::ExportClassMatrix: { 198 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET)); 199 } 200 case RSExportType::ExportClassConstantArray: { 201 const RSExportConstantArrayType *CAT = 202 static_cast<const RSExportConstantArrayType *>(ET); 203 std::string ElementTypeName = GetTypeName(CAT->getElementType()); 204 if (Brackets) { 205 ElementTypeName.append("[]"); 206 } 207 return ElementTypeName; 208 } 209 case RSExportType::ExportClassRecord: { 210 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME; 211 } 212 default: { slangAssert(false && "Unknown class of type"); } 213 } 214 215 return ""; 216 } 217 218 static const char *GetTypeNullValue(const RSExportType *ET) { 219 switch (ET->getClass()) { 220 case RSExportType::ExportClassPrimitive: { 221 const RSExportPrimitiveType *EPT = 222 static_cast<const RSExportPrimitiveType *>(ET); 223 if (EPT->isRSObjectType()) 224 return "null"; 225 else if (EPT->getType() == DataTypeBoolean) 226 return "false"; 227 else 228 return "0"; 229 break; 230 } 231 case RSExportType::ExportClassPointer: 232 case RSExportType::ExportClassVector: 233 case RSExportType::ExportClassMatrix: 234 case RSExportType::ExportClassConstantArray: 235 case RSExportType::ExportClassRecord: { 236 return "null"; 237 break; 238 } 239 default: { slangAssert(false && "Unknown class of type"); } 240 } 241 return ""; 242 } 243 244 static std::string GetBuiltinElementConstruct(const RSExportType *ET) { 245 if (ET->getClass() == RSExportType::ExportClassPrimitive) { 246 return std::string("Element.") + ET->getElementName(); 247 } else if (ET->getClass() == RSExportType::ExportClassVector) { 248 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET); 249 if (EVT->getType() == DataTypeFloat32) { 250 if (EVT->getNumElement() == 2) { 251 return "Element.F32_2"; 252 } else if (EVT->getNumElement() == 3) { 253 return "Element.F32_3"; 254 } else if (EVT->getNumElement() == 4) { 255 return "Element.F32_4"; 256 } else { 257 slangAssert(false && "Vectors should be size 2, 3, 4"); 258 } 259 } else if (EVT->getType() == DataTypeUnsigned8) { 260 if (EVT->getNumElement() == 4) 261 return "Element.U8_4"; 262 } 263 } else if (ET->getClass() == RSExportType::ExportClassMatrix) { 264 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType *>(ET); 265 switch (EMT->getDim()) { 266 case 2: 267 return "Element.MATRIX_2X2"; 268 case 3: 269 return "Element.MATRIX_3X3"; 270 case 4: 271 return "Element.MATRIX_4X4"; 272 default: 273 slangAssert(false && "Unsupported dimension of matrix"); 274 } 275 } 276 // RSExportType::ExportClassPointer can't be generated in a struct. 277 278 return ""; 279 } 280 281 /********************** Methods to generate script class **********************/ 282 RSReflectionJava::RSReflectionJava(const RSContext *Context, 283 std::vector<std::string> *GeneratedFileNames, 284 const std::string &OutputBaseDirectory, 285 const std::string &RSSourceFileName, 286 const std::string &BitCodeFileName, 287 bool EmbedBitcodeInJava) 288 : mRSContext(Context), mPackageName(Context->getReflectJavaPackageName()), 289 mRSPackageName(Context->getRSPackageName()), 290 mOutputBaseDirectory(OutputBaseDirectory), 291 mRSSourceFileName(RSSourceFileName), mBitCodeFileName(BitCodeFileName), 292 mResourceId(RSSlangReflectUtils::JavaClassNameFromRSFileName( 293 mBitCodeFileName.c_str())), 294 mScriptClassName(RS_SCRIPT_CLASS_NAME_PREFIX + 295 RSSlangReflectUtils::JavaClassNameFromRSFileName( 296 mRSSourceFileName.c_str())), 297 mEmbedBitcodeInJava(EmbedBitcodeInJava), mNextExportVarSlot(0), 298 mNextExportFuncSlot(0), mNextExportForEachSlot(0), mLastError(""), 299 mGeneratedFileNames(GeneratedFileNames), mFieldIndex(0) { 300 slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames"); 301 slangAssert(!mPackageName.empty() && mPackageName != "-"); 302 303 mOutputDirectory = RSSlangReflectUtils::ComputePackagedPath( 304 OutputBaseDirectory.c_str(), mPackageName.c_str()) + 305 OS_PATH_SEPARATOR_STR; 306 307 // mElement.getBytesSize only exists on JB+ 308 if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) { 309 mItemSizeof = RS_TYPE_ITEM_SIZEOF_CURRENT; 310 } else { 311 mItemSizeof = RS_TYPE_ITEM_SIZEOF_LEGACY; 312 } 313 } 314 315 bool RSReflectionJava::genScriptClass(const std::string &ClassName, 316 std::string &ErrorMsg) { 317 if (!startClass(AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME, 318 ErrorMsg)) 319 return false; 320 321 genScriptClassConstructor(); 322 323 // Reflect export variable 324 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 325 E = mRSContext->export_vars_end(); 326 I != E; I++) 327 genExportVariable(*I); 328 329 // Reflect export for each functions (only available on ICS+) 330 if (mRSContext->getTargetAPI() >= SLANG_ICS_TARGET_API) { 331 for (RSContext::const_export_foreach_iterator 332 I = mRSContext->export_foreach_begin(), 333 E = mRSContext->export_foreach_end(); 334 I != E; I++) 335 genExportForEach(*I); 336 } 337 338 // Reflect export function 339 for (RSContext::const_export_func_iterator 340 I = mRSContext->export_funcs_begin(), 341 E = mRSContext->export_funcs_end(); 342 I != E; I++) 343 genExportFunction(*I); 344 345 endClass(); 346 347 return true; 348 } 349 350 void RSReflectionJava::genScriptClassConstructor() { 351 std::string className(RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName( 352 mRSSourceFileName.c_str())); 353 // Provide a simple way to reference this object. 354 mOut.indent() << "private static final String " RS_RESOURCE_NAME " = \"" 355 << getResourceId() << "\";\n"; 356 357 // Generate a simple constructor with only a single parameter (the rest 358 // can be inferred from information we already have). 359 mOut.indent() << "// Constructor\n"; 360 startFunction(AM_Public, false, nullptr, getClassName(), 1, "RenderScript", 361 "rs"); 362 363 if (getEmbedBitcodeInJava()) { 364 // Call new single argument Java-only constructor 365 mOut.indent() << "super(rs,\n"; 366 mOut.indent() << " " << RS_RESOURCE_NAME ",\n"; 367 mOut.indent() << " " << className << ".getBitCode32(),\n"; 368 mOut.indent() << " " << className << ".getBitCode64());\n"; 369 } else { 370 // Call alternate constructor with required parameters. 371 // Look up the proper raw bitcode resource id via the context. 372 mOut.indent() << "this(rs,\n"; 373 mOut.indent() << " rs.getApplicationContext().getResources(),\n"; 374 mOut.indent() << " rs.getApplicationContext().getResources()." 375 "getIdentifier(\n"; 376 mOut.indent() << " " RS_RESOURCE_NAME ", \"raw\",\n"; 377 mOut.indent() 378 << " rs.getApplicationContext().getPackageName()));\n"; 379 endFunction(); 380 381 // Alternate constructor (legacy) with 3 original parameters. 382 startFunction(AM_Public, false, nullptr, getClassName(), 3, "RenderScript", 383 "rs", "Resources", "resources", "int", "id"); 384 // Call constructor of super class 385 mOut.indent() << "super(rs, resources, id);\n"; 386 } 387 388 // If an exported variable has initial value, reflect it 389 390 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(), 391 E = mRSContext->export_vars_end(); 392 I != E; I++) { 393 const RSExportVar *EV = *I; 394 if (!EV->getInit().isUninit()) { 395 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit()); 396 } else if (EV->getArraySize()) { 397 // Always create an initial zero-init array object. 398 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = new " 399 << GetTypeName(EV->getType(), false) << "[" 400 << EV->getArraySize() << "];\n"; 401 size_t NumInits = EV->getNumInits(); 402 const RSExportConstantArrayType *ECAT = 403 static_cast<const RSExportConstantArrayType *>(EV->getType()); 404 const RSExportType *ET = ECAT->getElementType(); 405 for (size_t i = 0; i < NumInits; i++) { 406 std::stringstream Name; 407 Name << EV->getName() << "[" << i << "]"; 408 genInitExportVariable(ET, Name.str(), EV->getInitArray(i)); 409 } 410 } 411 if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) { 412 genTypeInstance(EV->getType()); 413 } 414 genFieldPackerInstance(EV->getType()); 415 } 416 417 for (RSContext::const_export_foreach_iterator 418 I = mRSContext->export_foreach_begin(), 419 E = mRSContext->export_foreach_end(); 420 I != E; I++) { 421 const RSExportForEach *EF = *I; 422 423 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes(); 424 for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end(); 425 BI != EI; BI++) { 426 427 if (*BI != nullptr) { 428 genTypeInstanceFromPointer(*BI); 429 } 430 } 431 432 const RSExportType *OET = EF->getOutType(); 433 if (OET) { 434 genTypeInstanceFromPointer(OET); 435 } 436 } 437 438 endFunction(); 439 440 for (std::set<std::string>::iterator I = mTypesToCheck.begin(), 441 E = mTypesToCheck.end(); 442 I != E; I++) { 443 mOut.indent() << "private Element " RS_ELEM_PREFIX << *I << ";\n"; 444 } 445 446 for (std::set<std::string>::iterator I = mFieldPackerTypes.begin(), 447 E = mFieldPackerTypes.end(); 448 I != E; I++) { 449 mOut.indent() << "private FieldPacker " RS_FP_PREFIX << *I << ";\n"; 450 } 451 } 452 453 void RSReflectionJava::genInitBoolExportVariable(const std::string &VarName, 454 const clang::APValue &Val) { 455 slangAssert(!Val.isUninit() && "Not a valid initializer"); 456 slangAssert((Val.getKind() == clang::APValue::Int) && 457 "Bool type has wrong initial APValue"); 458 459 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "; 460 461 mOut << ((Val.getInt().getSExtValue() == 0) ? "false" : "true") << ";\n"; 462 } 463 464 void 465 RSReflectionJava::genInitPrimitiveExportVariable(const std::string &VarName, 466 const clang::APValue &Val) { 467 slangAssert(!Val.isUninit() && "Not a valid initializer"); 468 469 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "; 470 genInitValue(Val, false); 471 mOut << ";\n"; 472 } 473 474 void RSReflectionJava::genInitExportVariable(const RSExportType *ET, 475 const std::string &VarName, 476 const clang::APValue &Val) { 477 slangAssert(!Val.isUninit() && "Not a valid initializer"); 478 479 switch (ET->getClass()) { 480 case RSExportType::ExportClassPrimitive: { 481 const RSExportPrimitiveType *EPT = 482 static_cast<const RSExportPrimitiveType *>(ET); 483 if (EPT->getType() == DataTypeBoolean) { 484 genInitBoolExportVariable(VarName, Val); 485 } else { 486 genInitPrimitiveExportVariable(VarName, Val); 487 } 488 break; 489 } 490 case RSExportType::ExportClassPointer: { 491 if (!Val.isInt() || Val.getInt().getSExtValue() != 0) 492 std::cout << "Initializer which is non-NULL to pointer type variable " 493 "will be ignored\n"; 494 break; 495 } 496 case RSExportType::ExportClassVector: { 497 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET); 498 switch (Val.getKind()) { 499 case clang::APValue::Int: 500 case clang::APValue::Float: { 501 for (unsigned i = 0; i < EVT->getNumElement(); i++) { 502 std::string Name = VarName + "." + GetVectorAccessor(i); 503 genInitPrimitiveExportVariable(Name, Val); 504 } 505 break; 506 } 507 case clang::APValue::Vector: { 508 std::stringstream VecName; 509 VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix 510 << EVT->getNumElement(); 511 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new " 512 << VecName.str() << "();\n"; 513 514 unsigned NumElements = std::min( 515 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength()); 516 for (unsigned i = 0; i < NumElements; i++) { 517 const clang::APValue &ElementVal = Val.getVectorElt(i); 518 std::string Name = VarName + "." + GetVectorAccessor(i); 519 genInitPrimitiveExportVariable(Name, ElementVal); 520 } 521 break; 522 } 523 case clang::APValue::MemberPointer: 524 case clang::APValue::Uninitialized: 525 case clang::APValue::ComplexInt: 526 case clang::APValue::ComplexFloat: 527 case clang::APValue::LValue: 528 case clang::APValue::Array: 529 case clang::APValue::Struct: 530 case clang::APValue::Union: 531 case clang::APValue::AddrLabelDiff: { 532 slangAssert(false && "Unexpected type of value of initializer."); 533 } 534 } 535 break; 536 } 537 // TODO(zonr): Resolving initializer of a record (and matrix) type variable 538 // is complex. It cannot obtain by just simply evaluating the initializer 539 // expression. 540 case RSExportType::ExportClassMatrix: 541 case RSExportType::ExportClassConstantArray: 542 case RSExportType::ExportClassRecord: { 543 #if 0 544 unsigned InitIndex = 0; 545 const RSExportRecordType *ERT = 546 static_cast<const RSExportRecordType*>(ET); 547 548 slangAssert((Val.getKind() == clang::APValue::Vector) && 549 "Unexpected type of initializer for record type variable"); 550 551 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName 552 << " = new " << ERT->getElementName() 553 << "." RS_TYPE_ITEM_CLASS_NAME"();\n"; 554 555 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 556 E = ERT->fields_end(); 557 I != E; 558 I++) { 559 const RSExportRecordType::Field *F = *I; 560 std::string FieldName = VarName + "." + F->getName(); 561 562 if (InitIndex > Val.getVectorLength()) 563 break; 564 565 genInitPrimitiveExportVariable(FieldName, 566 Val.getVectorElt(InitIndex++)); 567 } 568 #endif 569 slangAssert(false && "Unsupported initializer for record/matrix/constant " 570 "array type variable currently"); 571 break; 572 } 573 default: { slangAssert(false && "Unknown class of type"); } 574 } 575 } 576 577 void RSReflectionJava::genExportVariable(const RSExportVar *EV) { 578 const RSExportType *ET = EV->getType(); 579 580 mOut.indent() << "private final static int " << RS_EXPORT_VAR_INDEX_PREFIX 581 << EV->getName() << " = " << getNextExportVarSlot() << ";\n"; 582 583 switch (ET->getClass()) { 584 case RSExportType::ExportClassPrimitive: { 585 genPrimitiveTypeExportVariable(EV); 586 break; 587 } 588 case RSExportType::ExportClassPointer: { 589 genPointerTypeExportVariable(EV); 590 break; 591 } 592 case RSExportType::ExportClassVector: { 593 genVectorTypeExportVariable(EV); 594 break; 595 } 596 case RSExportType::ExportClassMatrix: { 597 genMatrixTypeExportVariable(EV); 598 break; 599 } 600 case RSExportType::ExportClassConstantArray: { 601 genConstantArrayTypeExportVariable(EV); 602 break; 603 } 604 case RSExportType::ExportClassRecord: { 605 genRecordTypeExportVariable(EV); 606 break; 607 } 608 default: { slangAssert(false && "Unknown class of type"); } 609 } 610 } 611 612 void RSReflectionJava::genExportFunction(const RSExportFunc *EF) { 613 mOut.indent() << "private final static int " << RS_EXPORT_FUNC_INDEX_PREFIX 614 << EF->getName() << " = " << getNextExportFuncSlot() << ";\n"; 615 616 // invoke_*() 617 ArgTy Args; 618 619 if (EF->hasParam()) { 620 for (RSExportFunc::const_param_iterator I = EF->params_begin(), 621 E = EF->params_end(); 622 I != E; I++) { 623 Args.push_back( 624 std::make_pair(GetTypeName((*I)->getType()), (*I)->getName())); 625 } 626 } 627 628 if (mRSContext->getTargetAPI() >= SLANG_M_TARGET_API) { 629 startFunction(AM_Public, false, "Script.InvokeID", 630 "getInvokeID_" + EF->getName(), 0); 631 632 mOut.indent() << "return createInvokeID(" << RS_EXPORT_FUNC_INDEX_PREFIX 633 << EF->getName() << ");\n"; 634 635 endFunction(); 636 } 637 638 startFunction(AM_Public, false, "void", 639 "invoke_" + EF->getName(/*Mangle=*/false), 640 // We are using un-mangled name since Java 641 // supports method overloading. 642 Args); 643 644 if (!EF->hasParam()) { 645 mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() 646 << ");\n"; 647 } else { 648 const RSExportRecordType *ERT = EF->getParamPacketType(); 649 std::string FieldPackerName = EF->getName() + "_fp"; 650 651 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) 652 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str()); 653 654 mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() 655 << ", " << FieldPackerName << ");\n"; 656 } 657 658 endFunction(); 659 } 660 661 void RSReflectionJava::genPairwiseDimCheck(std::string name0, 662 std::string name1) { 663 664 mOut.indent() << "// Verify dimensions\n"; 665 mOut.indent() << "t0 = " << name0 << ".getType();\n"; 666 mOut.indent() << "t1 = " << name1 << ".getType();\n"; 667 mOut.indent() << "if ((t0.getCount() != t1.getCount()) ||\n"; 668 mOut.indent() << " (t0.getX() != t1.getX()) ||\n"; 669 mOut.indent() << " (t0.getY() != t1.getY()) ||\n"; 670 mOut.indent() << " (t0.getZ() != t1.getZ()) ||\n"; 671 mOut.indent() << " (t0.hasFaces() != t1.hasFaces()) ||\n"; 672 mOut.indent() << " (t0.hasMipmaps() != t1.hasMipmaps())) {\n"; 673 mOut.indent() << " throw new RSRuntimeException(\"Dimension mismatch " 674 << "between parameters " << name0 << " and " << name1 675 << "!\");\n"; 676 mOut.indent() << "}\n\n"; 677 } 678 679 void RSReflectionJava::genExportForEach(const RSExportForEach *EF) { 680 if (EF->isDummyRoot()) { 681 // Skip reflection for dummy root() kernels. Note that we have to 682 // advance the next slot number for ForEach, however. 683 mOut.indent() << "//private final static int " 684 << RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName() << " = " 685 << getNextExportForEachSlot() << ";\n"; 686 return; 687 } 688 689 mOut.indent() << "private final static int " << RS_EXPORT_FOREACH_INDEX_PREFIX 690 << EF->getName() << " = " << getNextExportForEachSlot() 691 << ";\n"; 692 693 // forEach_*() 694 ArgTy Args; 695 bool HasAllocation = false; // at least one in/out allocation? 696 697 const RSExportForEach::InVec &Ins = EF->getIns(); 698 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes(); 699 const RSExportType *OET = EF->getOutType(); 700 701 if (Ins.size() == 1) { 702 HasAllocation = true; 703 Args.push_back(std::make_pair("Allocation", "ain")); 704 705 } else if (Ins.size() > 1) { 706 HasAllocation = true; 707 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI; 708 BI++) { 709 710 Args.push_back(std::make_pair("Allocation", 711 "ain_" + (*BI)->getName().str())); 712 } 713 } 714 715 if (EF->hasOut() || EF->hasReturn()) { 716 HasAllocation = true; 717 Args.push_back(std::make_pair("Allocation", "aout")); 718 } 719 720 const RSExportRecordType *ERT = EF->getParamPacketType(); 721 if (ERT) { 722 for (RSExportForEach::const_param_iterator I = EF->params_begin(), 723 E = EF->params_end(); 724 I != E; I++) { 725 Args.push_back( 726 std::make_pair(GetTypeName((*I)->getType()), (*I)->getName())); 727 } 728 } 729 730 if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) { 731 startFunction(AM_Public, false, "Script.KernelID", 732 "getKernelID_" + EF->getName(), 0); 733 734 // TODO: add element checking 735 mOut.indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX 736 << EF->getName() << ", " << EF->getSignatureMetadata() 737 << ", null, null);\n"; 738 739 endFunction(); 740 } 741 742 if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) { 743 if (HasAllocation) { 744 startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args); 745 746 mOut.indent() << "forEach_" << EF->getName(); 747 mOut << "("; 748 749 if (Ins.size() == 1) { 750 mOut << "ain, "; 751 752 } else if (Ins.size() > 1) { 753 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI; 754 BI++) { 755 756 mOut << "ain_" << (*BI)->getName().str() << ", "; 757 } 758 } 759 760 if (EF->hasOut() || EF->hasReturn()) { 761 mOut << "aout, "; 762 } 763 764 if (EF->hasUsrData()) { 765 mOut << Args.back().second << ", "; 766 } 767 768 // No clipped bounds to pass in. 769 mOut << "null);\n"; 770 771 endFunction(); 772 } 773 774 // Add the clipped kernel parameters to the Args list. 775 Args.push_back(std::make_pair("Script.LaunchOptions", "sc")); 776 } 777 778 startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args); 779 780 if (InTypes.size() == 1) { 781 if (InTypes.front() != nullptr) { 782 genTypeCheck(InTypes.front(), "ain"); 783 } 784 785 } else if (InTypes.size() > 1) { 786 size_t Index = 0; 787 for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end(); 788 BI != EI; BI++, ++Index) { 789 790 if (*BI != nullptr) { 791 genTypeCheck(*BI, ("ain_" + Ins[Index]->getName()).str().c_str()); 792 } 793 } 794 } 795 796 if (OET) { 797 genTypeCheck(OET, "aout"); 798 } 799 800 if (Ins.size() == 1 && (EF->hasOut() || EF->hasReturn())) { 801 mOut.indent() << "Type t0, t1;"; 802 genPairwiseDimCheck("ain", "aout"); 803 804 } else if (Ins.size() > 1) { 805 mOut.indent() << "Type t0, t1;"; 806 807 std::string In0Name = "ain_" + Ins[0]->getName().str(); 808 809 for (size_t index = 1; index < Ins.size(); ++index) { 810 genPairwiseDimCheck(In0Name, "ain_" + Ins[index]->getName().str()); 811 } 812 813 if (EF->hasOut() || EF->hasReturn()) { 814 genPairwiseDimCheck(In0Name, "aout"); 815 } 816 } 817 818 std::string FieldPackerName = EF->getName() + "_fp"; 819 if (ERT) { 820 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) { 821 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str()); 822 } 823 } 824 mOut.indent() << "forEach(" << RS_EXPORT_FOREACH_INDEX_PREFIX 825 << EF->getName(); 826 827 if (Ins.size() == 1) { 828 mOut << ", ain"; 829 } else if (Ins.size() > 1) { 830 mOut << ", new Allocation[]{ain_" << Ins[0]->getName().str(); 831 832 for (size_t index = 1; index < Ins.size(); ++index) { 833 mOut << ", ain_" << Ins[index]->getName().str(); 834 } 835 836 mOut << "}"; 837 838 } else { 839 mOut << ", (Allocation) null"; 840 } 841 842 if (EF->hasOut() || EF->hasReturn()) 843 mOut << ", aout"; 844 else 845 mOut << ", null"; 846 847 if (EF->hasUsrData()) 848 mOut << ", " << FieldPackerName; 849 else 850 mOut << ", null"; 851 852 if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) { 853 mOut << ", sc);\n"; 854 } else { 855 mOut << ");\n"; 856 } 857 858 endFunction(); 859 } 860 861 void RSReflectionJava::genTypeInstanceFromPointer(const RSExportType *ET) { 862 if (ET->getClass() == RSExportType::ExportClassPointer) { 863 // For pointer parameters to original forEach kernels. 864 const RSExportPointerType *EPT = 865 static_cast<const RSExportPointerType *>(ET); 866 genTypeInstance(EPT->getPointeeType()); 867 } else { 868 // For handling pass-by-value kernel parameters. 869 genTypeInstance(ET); 870 } 871 } 872 873 void RSReflectionJava::genTypeInstance(const RSExportType *ET) { 874 switch (ET->getClass()) { 875 case RSExportType::ExportClassPrimitive: 876 case RSExportType::ExportClassVector: 877 case RSExportType::ExportClassConstantArray: { 878 std::string TypeName = ET->getElementName(); 879 if (addTypeNameForElement(TypeName)) { 880 mOut.indent() << RS_ELEM_PREFIX << TypeName << " = Element." << TypeName 881 << "(rs);\n"; 882 } 883 break; 884 } 885 886 case RSExportType::ExportClassRecord: { 887 std::string ClassName = ET->getElementName(); 888 if (addTypeNameForElement(ClassName)) { 889 mOut.indent() << RS_ELEM_PREFIX << ClassName << " = " << ClassName 890 << ".createElement(rs);\n"; 891 } 892 break; 893 } 894 895 default: 896 break; 897 } 898 } 899 900 void RSReflectionJava::genFieldPackerInstance(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 addTypeNameForFieldPacker(TypeName); 908 break; 909 } 910 911 default: 912 break; 913 } 914 } 915 916 void RSReflectionJava::genTypeCheck(const RSExportType *ET, 917 const char *VarName) { 918 mOut.indent() << "// check " << VarName << "\n"; 919 920 if (ET->getClass() == RSExportType::ExportClassPointer) { 921 const RSExportPointerType *EPT = 922 static_cast<const RSExportPointerType *>(ET); 923 ET = EPT->getPointeeType(); 924 } 925 926 std::string TypeName; 927 928 switch (ET->getClass()) { 929 case RSExportType::ExportClassPrimitive: 930 case RSExportType::ExportClassVector: 931 case RSExportType::ExportClassRecord: { 932 TypeName = ET->getElementName(); 933 break; 934 } 935 936 default: 937 break; 938 } 939 940 if (!TypeName.empty()) { 941 mOut.indent() << "if (!" << VarName 942 << ".getType().getElement().isCompatible(" RS_ELEM_PREFIX 943 << TypeName << ")) {\n"; 944 mOut.indent() << " throw new RSRuntimeException(\"Type mismatch with " 945 << TypeName << "!\");\n"; 946 mOut.indent() << "}\n"; 947 } 948 } 949 950 void RSReflectionJava::genPrimitiveTypeExportVariable(const RSExportVar *EV) { 951 slangAssert( 952 (EV->getType()->getClass() == RSExportType::ExportClassPrimitive) && 953 "Variable should be type of primitive here"); 954 955 const RSExportPrimitiveType *EPT = 956 static_cast<const RSExportPrimitiveType *>(EV->getType()); 957 std::string TypeName = GetTypeName(EPT); 958 std::string VarName = EV->getName(); 959 960 genPrivateExportVariable(TypeName, EV->getName()); 961 962 if (EV->isConst()) { 963 mOut.indent() << "public final static " << TypeName 964 << " " RS_EXPORT_VAR_CONST_PREFIX << VarName << " = "; 965 const clang::APValue &Val = EV->getInit(); 966 genInitValue(Val, EPT->getType() == DataTypeBoolean); 967 mOut << ";\n"; 968 } else { 969 // set_*() 970 // This must remain synchronized, since multiple Dalvik threads may 971 // be calling setters. 972 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1, 973 TypeName.c_str(), "v"); 974 if ((EPT->getSize() < 4) || EV->isUnsigned()) { 975 // We create/cache a per-type FieldPacker. This allows us to reuse the 976 // validation logic (for catching negative inputs from Dalvik, as well 977 // as inputs that are too large to be represented in the unsigned type). 978 // Sub-integer types are also handled specially here, so that we don't 979 // overwrite bytes accidentally. 980 std::string ElemName = EPT->getElementName(); 981 std::string FPName; 982 FPName = RS_FP_PREFIX + ElemName; 983 mOut.indent() << "if (" << FPName << "!= null) {\n"; 984 mOut.increaseIndent(); 985 mOut.indent() << FPName << ".reset();\n"; 986 mOut.decreaseIndent(); 987 mOut.indent() << "} else {\n"; 988 mOut.increaseIndent(); 989 mOut.indent() << FPName << " = new FieldPacker(" << EPT->getSize() 990 << ");\n"; 991 mOut.decreaseIndent(); 992 mOut.indent() << "}\n"; 993 994 genPackVarOfType(EPT, "v", FPName.c_str()); 995 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName 996 << ", " << FPName << ");\n"; 997 } else { 998 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName 999 << ", v);\n"; 1000 } 1001 1002 // Dalvik update comes last, since the input may be invalid (and hence 1003 // throw an exception). 1004 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 1005 1006 endFunction(); 1007 } 1008 1009 genGetExportVariable(TypeName, VarName); 1010 genGetFieldID(VarName); 1011 } 1012 1013 void RSReflectionJava::genInitValue(const clang::APValue &Val, bool asBool) { 1014 switch (Val.getKind()) { 1015 case clang::APValue::Int: { 1016 llvm::APInt api = Val.getInt(); 1017 if (asBool) { 1018 mOut << ((api.getSExtValue() == 0) ? "false" : "true"); 1019 } else { 1020 // TODO: Handle unsigned correctly 1021 mOut << api.getSExtValue(); 1022 if (api.getBitWidth() > 32) { 1023 mOut << "L"; 1024 } 1025 } 1026 break; 1027 } 1028 1029 case clang::APValue::Float: { 1030 llvm::APFloat apf = Val.getFloat(); 1031 llvm::SmallString<30> s; 1032 apf.toString(s); 1033 mOut << s.c_str(); 1034 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) { 1035 if (s.count('.') == 0) { 1036 mOut << ".f"; 1037 } else { 1038 mOut << "f"; 1039 } 1040 } 1041 break; 1042 } 1043 1044 case clang::APValue::ComplexInt: 1045 case clang::APValue::ComplexFloat: 1046 case clang::APValue::LValue: 1047 case clang::APValue::Vector: { 1048 slangAssert(false && "Primitive type cannot have such kind of initializer"); 1049 break; 1050 } 1051 1052 default: { slangAssert(false && "Unknown kind of initializer"); } 1053 } 1054 } 1055 1056 void RSReflectionJava::genPointerTypeExportVariable(const RSExportVar *EV) { 1057 const RSExportType *ET = EV->getType(); 1058 const RSExportType *PointeeType; 1059 1060 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && 1061 "Variable should be type of pointer here"); 1062 1063 PointeeType = static_cast<const RSExportPointerType *>(ET)->getPointeeType(); 1064 std::string TypeName = GetTypeName(ET); 1065 std::string VarName = EV->getName(); 1066 1067 genPrivateExportVariable(TypeName, VarName); 1068 1069 // bind_*() 1070 startFunction(AM_Public, false, "void", "bind_" + VarName, 1, 1071 TypeName.c_str(), "v"); 1072 1073 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 1074 mOut.indent() << "if (v == null) bindAllocation(null, " 1075 << RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");\n"; 1076 1077 if (PointeeType->getClass() == RSExportType::ExportClassRecord) { 1078 mOut.indent() << "else bindAllocation(v.getAllocation(), " 1079 << RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");\n"; 1080 } else { 1081 mOut.indent() << "else bindAllocation(v, " << RS_EXPORT_VAR_INDEX_PREFIX 1082 << VarName << ");\n"; 1083 } 1084 1085 endFunction(); 1086 1087 genGetExportVariable(TypeName, VarName); 1088 } 1089 1090 void RSReflectionJava::genVectorTypeExportVariable(const RSExportVar *EV) { 1091 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) && 1092 "Variable should be type of vector here"); 1093 1094 std::string TypeName = GetTypeName(EV->getType()); 1095 std::string VarName = EV->getName(); 1096 1097 genPrivateExportVariable(TypeName, VarName); 1098 genSetExportVariable(TypeName, EV); 1099 genGetExportVariable(TypeName, VarName); 1100 genGetFieldID(VarName); 1101 } 1102 1103 void RSReflectionJava::genMatrixTypeExportVariable(const RSExportVar *EV) { 1104 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) && 1105 "Variable should be type of matrix here"); 1106 1107 const RSExportType *ET = EV->getType(); 1108 std::string TypeName = GetTypeName(ET); 1109 std::string VarName = EV->getName(); 1110 1111 genPrivateExportVariable(TypeName, VarName); 1112 1113 // set_*() 1114 if (!EV->isConst()) { 1115 const char *FieldPackerName = "fp"; 1116 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1, 1117 TypeName.c_str(), "v"); 1118 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 1119 1120 if (genCreateFieldPacker(ET, FieldPackerName)) 1121 genPackVarOfType(ET, "v", FieldPackerName); 1122 mOut.indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", " 1123 << FieldPackerName << ");\n"; 1124 1125 endFunction(); 1126 } 1127 1128 genGetExportVariable(TypeName, VarName); 1129 genGetFieldID(VarName); 1130 } 1131 1132 void 1133 RSReflectionJava::genConstantArrayTypeExportVariable(const RSExportVar *EV) { 1134 slangAssert( 1135 (EV->getType()->getClass() == RSExportType::ExportClassConstantArray) && 1136 "Variable should be type of constant array here"); 1137 1138 std::string TypeName = GetTypeName(EV->getType()); 1139 std::string VarName = EV->getName(); 1140 1141 genPrivateExportVariable(TypeName, VarName); 1142 genSetExportVariable(TypeName, EV); 1143 genGetExportVariable(TypeName, VarName); 1144 genGetFieldID(VarName); 1145 } 1146 1147 void RSReflectionJava::genRecordTypeExportVariable(const RSExportVar *EV) { 1148 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && 1149 "Variable should be type of struct here"); 1150 1151 std::string TypeName = GetTypeName(EV->getType()); 1152 std::string VarName = EV->getName(); 1153 1154 genPrivateExportVariable(TypeName, VarName); 1155 genSetExportVariable(TypeName, EV); 1156 genGetExportVariable(TypeName, VarName); 1157 genGetFieldID(VarName); 1158 } 1159 1160 void RSReflectionJava::genPrivateExportVariable(const std::string &TypeName, 1161 const std::string &VarName) { 1162 mOut.indent() << "private " << TypeName << " " << RS_EXPORT_VAR_PREFIX 1163 << VarName << ";\n"; 1164 } 1165 1166 void RSReflectionJava::genSetExportVariable(const std::string &TypeName, 1167 const RSExportVar *EV) { 1168 if (!EV->isConst()) { 1169 const char *FieldPackerName = "fp"; 1170 std::string VarName = EV->getName(); 1171 const RSExportType *ET = EV->getType(); 1172 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1, 1173 TypeName.c_str(), "v"); 1174 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n"; 1175 1176 if (genCreateFieldPacker(ET, FieldPackerName)) 1177 genPackVarOfType(ET, "v", FieldPackerName); 1178 1179 if (mRSContext->getTargetAPI() < SLANG_JB_TARGET_API) { 1180 // Legacy apps must use the old setVar() without Element/dim components. 1181 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName 1182 << ", " << FieldPackerName << ");\n"; 1183 } else { 1184 // We only have support for one-dimensional array reflection today, 1185 // but the entry point (i.e. setVar()) takes an array of dimensions. 1186 mOut.indent() << "int []__dimArr = new int[1];\n"; 1187 mOut.indent() << "__dimArr[0] = " << ET->getSize() << ";\n"; 1188 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName 1189 << ", " << FieldPackerName << ", " << RS_ELEM_PREFIX 1190 << ET->getElementName() << ", __dimArr);\n"; 1191 } 1192 1193 endFunction(); 1194 } 1195 } 1196 1197 void RSReflectionJava::genGetExportVariable(const std::string &TypeName, 1198 const std::string &VarName) { 1199 startFunction(AM_Public, false, TypeName.c_str(), "get_" + VarName, 0); 1200 1201 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n"; 1202 1203 endFunction(); 1204 } 1205 1206 void RSReflectionJava::genGetFieldID(const std::string &VarName) { 1207 // We only generate getFieldID_*() for non-Pointer (bind) types. 1208 if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) { 1209 startFunction(AM_Public, false, "Script.FieldID", "getFieldID_" + VarName, 1210 0); 1211 1212 mOut.indent() << "return createFieldID(" << RS_EXPORT_VAR_INDEX_PREFIX 1213 << VarName << ", null);\n"; 1214 1215 endFunction(); 1216 } 1217 } 1218 1219 /******************* Methods to generate script class /end *******************/ 1220 1221 bool RSReflectionJava::genCreateFieldPacker(const RSExportType *ET, 1222 const char *FieldPackerName) { 1223 size_t AllocSize = ET->getAllocSize(); 1224 if (AllocSize > 0) 1225 mOut.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" 1226 << AllocSize << ");\n"; 1227 else 1228 return false; 1229 return true; 1230 } 1231 1232 void RSReflectionJava::genPackVarOfType(const RSExportType *ET, 1233 const char *VarName, 1234 const char *FieldPackerName) { 1235 switch (ET->getClass()) { 1236 case RSExportType::ExportClassPrimitive: 1237 case RSExportType::ExportClassVector: { 1238 mOut.indent() << FieldPackerName << "." 1239 << GetPackerAPIName( 1240 static_cast<const RSExportPrimitiveType *>(ET)) << "(" 1241 << VarName << ");\n"; 1242 break; 1243 } 1244 case RSExportType::ExportClassPointer: { 1245 // Must reflect as type Allocation in Java 1246 const RSExportType *PointeeType = 1247 static_cast<const RSExportPointerType *>(ET)->getPointeeType(); 1248 1249 if (PointeeType->getClass() != RSExportType::ExportClassRecord) { 1250 mOut.indent() << FieldPackerName << ".addI32(" << VarName 1251 << ".getPtr());\n"; 1252 } else { 1253 mOut.indent() << FieldPackerName << ".addI32(" << VarName 1254 << ".getAllocation().getPtr());\n"; 1255 } 1256 break; 1257 } 1258 case RSExportType::ExportClassMatrix: { 1259 mOut.indent() << FieldPackerName << ".addMatrix(" << VarName << ");\n"; 1260 break; 1261 } 1262 case RSExportType::ExportClassConstantArray: { 1263 const RSExportConstantArrayType *ECAT = 1264 static_cast<const RSExportConstantArrayType *>(ET); 1265 1266 // TODO(zonr): more elegant way. Currently, we obtain the unique index 1267 // variable (this method involves recursive call which means 1268 // we may have more than one level loop, therefore we can't 1269 // always use the same index variable name here) name given 1270 // in the for-loop from counting the '.' in @VarName. 1271 unsigned Level = 0; 1272 size_t LastDotPos = 0; 1273 std::string ElementVarName(VarName); 1274 1275 while (LastDotPos != std::string::npos) { 1276 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1); 1277 Level++; 1278 } 1279 std::string IndexVarName("ct"); 1280 IndexVarName.append(llvm::utostr_32(Level)); 1281 1282 mOut.indent() << "for (int " << IndexVarName << " = 0; " << IndexVarName 1283 << " < " << ECAT->getSize() << "; " << IndexVarName << "++)"; 1284 mOut.startBlock(); 1285 1286 ElementVarName.append("[" + IndexVarName + "]"); 1287 genPackVarOfType(ECAT->getElementType(), ElementVarName.c_str(), 1288 FieldPackerName); 1289 1290 mOut.endBlock(); 1291 break; 1292 } 1293 case RSExportType::ExportClassRecord: { 1294 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET); 1295 // Relative pos from now on in field packer 1296 unsigned Pos = 0; 1297 1298 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 1299 E = ERT->fields_end(); 1300 I != E; I++) { 1301 const RSExportRecordType::Field *F = *I; 1302 std::string FieldName; 1303 size_t FieldOffset = F->getOffsetInParent(); 1304 const RSExportType *T = F->getType(); 1305 size_t FieldStoreSize = T->getStoreSize(); 1306 size_t FieldAllocSize = T->getAllocSize(); 1307 1308 if (VarName != nullptr) 1309 FieldName = VarName + ("." + F->getName()); 1310 else 1311 FieldName = F->getName(); 1312 1313 if (FieldOffset > Pos) { 1314 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos) 1315 << ");\n"; 1316 } 1317 1318 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName); 1319 1320 // There is padding in the field type 1321 if (FieldAllocSize > FieldStoreSize) { 1322 mOut.indent() << FieldPackerName << ".skip(" 1323 << (FieldAllocSize - FieldStoreSize) << ");\n"; 1324 } 1325 1326 Pos = FieldOffset + FieldAllocSize; 1327 } 1328 1329 // There maybe some padding after the struct 1330 if (ERT->getAllocSize() > Pos) { 1331 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos 1332 << ");\n"; 1333 } 1334 break; 1335 } 1336 default: { slangAssert(false && "Unknown class of type"); } 1337 } 1338 } 1339 1340 void RSReflectionJava::genAllocateVarOfType(const RSExportType *T, 1341 const std::string &VarName) { 1342 switch (T->getClass()) { 1343 case RSExportType::ExportClassPrimitive: { 1344 // Primitive type like int in Java has its own storage once it's declared. 1345 // 1346 // FIXME: Should we allocate storage for RS object? 1347 // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType()) 1348 // mOut.indent() << VarName << " = new " << GetTypeName(T) << "();\n"; 1349 break; 1350 } 1351 case RSExportType::ExportClassPointer: { 1352 // Pointer type is an instance of Allocation or a TypeClass whose value is 1353 // expected to be assigned by programmer later in Java program. Therefore 1354 // we don't reflect things like [VarName] = new Allocation(); 1355 mOut.indent() << VarName << " = null;\n"; 1356 break; 1357 } 1358 case RSExportType::ExportClassConstantArray: { 1359 const RSExportConstantArrayType *ECAT = 1360 static_cast<const RSExportConstantArrayType *>(T); 1361 const RSExportType *ElementType = ECAT->getElementType(); 1362 1363 mOut.indent() << VarName << " = new " << GetTypeName(ElementType) << "[" 1364 << ECAT->getSize() << "];\n"; 1365 1366 // Primitive type element doesn't need allocation code. 1367 if (ElementType->getClass() != RSExportType::ExportClassPrimitive) { 1368 mOut.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() 1369 << "; $ct++)"; 1370 mOut.startBlock(); 1371 1372 std::string ElementVarName(VarName); 1373 ElementVarName.append("[$ct]"); 1374 genAllocateVarOfType(ElementType, ElementVarName); 1375 1376 mOut.endBlock(); 1377 } 1378 break; 1379 } 1380 case RSExportType::ExportClassVector: 1381 case RSExportType::ExportClassMatrix: 1382 case RSExportType::ExportClassRecord: { 1383 mOut.indent() << VarName << " = new " << GetTypeName(T) << "();\n"; 1384 break; 1385 } 1386 } 1387 } 1388 1389 void RSReflectionJava::genNewItemBufferIfNull(const char *Index) { 1390 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME " == null) "; 1391 mOut << RS_TYPE_ITEM_BUFFER_NAME << " = new " << RS_TYPE_ITEM_CLASS_NAME 1392 << "[getType().getX() /* count */];\n"; 1393 if (Index != nullptr) { 1394 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME << "[" << Index 1395 << "] == null) "; 1396 mOut << RS_TYPE_ITEM_BUFFER_NAME << "[" << Index << "] = new " 1397 << RS_TYPE_ITEM_CLASS_NAME << "();\n"; 1398 } 1399 } 1400 1401 void RSReflectionJava::genNewItemBufferPackerIfNull() { 1402 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " == null) "; 1403 mOut << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = new FieldPacker(" 1404 << mItemSizeof << " * getType().getX()/* count */);\n"; 1405 } 1406 1407 /********************** Methods to generate type class **********************/ 1408 bool RSReflectionJava::genTypeClass(const RSExportRecordType *ERT, 1409 std::string &ErrorMsg) { 1410 std::string ClassName = ERT->getElementName(); 1411 std::string superClassName = getRSPackageName(); 1412 superClassName += RS_TYPE_CLASS_SUPER_CLASS_NAME; 1413 1414 if (!startClass(AM_Public, false, ClassName, superClassName.c_str(), 1415 ErrorMsg)) 1416 return false; 1417 1418 mGeneratedFileNames->push_back(ClassName); 1419 1420 genTypeItemClass(ERT); 1421 1422 // Declare item buffer and item buffer packer 1423 mOut.indent() << "private " << RS_TYPE_ITEM_CLASS_NAME << " " 1424 << RS_TYPE_ITEM_BUFFER_NAME << "[];\n"; 1425 mOut.indent() << "private FieldPacker " << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1426 << ";\n"; 1427 mOut.indent() << "private static java.lang.ref.WeakReference<Element> " 1428 << RS_TYPE_ELEMENT_REF_NAME 1429 << " = new java.lang.ref.WeakReference<Element>(null);\n"; 1430 1431 genTypeClassConstructor(ERT); 1432 genTypeClassCopyToArrayLocal(ERT); 1433 genTypeClassCopyToArray(ERT); 1434 genTypeClassItemSetter(ERT); 1435 genTypeClassItemGetter(ERT); 1436 genTypeClassComponentSetter(ERT); 1437 genTypeClassComponentGetter(ERT); 1438 genTypeClassCopyAll(ERT); 1439 if (!mRSContext->isCompatLib()) { 1440 // Skip the resize method if we are targeting a compatibility library. 1441 genTypeClassResize(); 1442 } 1443 1444 endClass(); 1445 1446 resetFieldIndex(); 1447 clearFieldIndexMap(); 1448 1449 return true; 1450 } 1451 1452 void RSReflectionJava::genTypeItemClass(const RSExportRecordType *ERT) { 1453 mOut.indent() << "static public class " RS_TYPE_ITEM_CLASS_NAME; 1454 mOut.startBlock(); 1455 1456 // Sizeof should not be exposed for 64-bit; it is not accurate 1457 if (mRSContext->getTargetAPI() < 21) { 1458 mOut.indent() << "public static final int sizeof = " << ERT->getAllocSize() 1459 << ";\n"; 1460 } 1461 1462 // Member elements 1463 mOut << "\n"; 1464 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1465 FE = ERT->fields_end(); 1466 FI != FE; FI++) { 1467 mOut.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() 1468 << ";\n"; 1469 } 1470 1471 // Constructor 1472 mOut << "\n"; 1473 mOut.indent() << RS_TYPE_ITEM_CLASS_NAME << "()"; 1474 mOut.startBlock(); 1475 1476 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1477 FE = ERT->fields_end(); 1478 FI != FE; FI++) { 1479 const RSExportRecordType::Field *F = *FI; 1480 genAllocateVarOfType(F->getType(), F->getName()); 1481 } 1482 1483 // end Constructor 1484 mOut.endBlock(); 1485 1486 // end Item class 1487 mOut.endBlock(); 1488 } 1489 1490 void RSReflectionJava::genTypeClassConstructor(const RSExportRecordType *ERT) { 1491 const char *RenderScriptVar = "rs"; 1492 1493 startFunction(AM_Public, true, "Element", "createElement", 1, "RenderScript", 1494 RenderScriptVar); 1495 1496 // TODO(all): Fix weak-refs + multi-context issue. 1497 // mOut.indent() << "Element e = " << RS_TYPE_ELEMENT_REF_NAME 1498 // << ".get();\n"; 1499 // mOut.indent() << "if (e != null) return e;\n"; 1500 RSReflectionJavaElementBuilder builder("eb", ERT, RenderScriptVar, &mOut, 1501 mRSContext, this); 1502 builder.generate(); 1503 1504 mOut.indent() << "return eb.create();\n"; 1505 // mOut.indent() << "e = eb.create();\n"; 1506 // mOut.indent() << RS_TYPE_ELEMENT_REF_NAME 1507 // << " = new java.lang.ref.WeakReference<Element>(e);\n"; 1508 // mOut.indent() << "return e;\n"; 1509 endFunction(); 1510 1511 // private with element 1512 startFunction(AM_Private, false, nullptr, getClassName(), 1, "RenderScript", 1513 RenderScriptVar); 1514 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n"; 1515 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n"; 1516 mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n"; 1517 endFunction(); 1518 1519 // 1D without usage 1520 startFunction(AM_Public, false, nullptr, getClassName(), 2, "RenderScript", 1521 RenderScriptVar, "int", "count"); 1522 1523 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n"; 1524 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n"; 1525 mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n"; 1526 // Call init() in super class 1527 mOut.indent() << "init(" << RenderScriptVar << ", count);\n"; 1528 endFunction(); 1529 1530 // 1D with usage 1531 startFunction(AM_Public, false, nullptr, getClassName(), 3, "RenderScript", 1532 RenderScriptVar, "int", "count", "int", "usages"); 1533 1534 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n"; 1535 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n"; 1536 mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n"; 1537 // Call init() in super class 1538 mOut.indent() << "init(" << RenderScriptVar << ", count, usages);\n"; 1539 endFunction(); 1540 1541 // create1D with usage 1542 startFunction(AM_Public, true, getClassName().c_str(), "create1D", 3, 1543 "RenderScript", RenderScriptVar, "int", "dimX", "int", 1544 "usages"); 1545 mOut.indent() << getClassName() << " obj = new " << getClassName() << "(" 1546 << RenderScriptVar << ");\n"; 1547 mOut.indent() << "obj.mAllocation = Allocation.createSized(" 1548 "rs, obj.mElement, dimX, usages);\n"; 1549 mOut.indent() << "return obj;\n"; 1550 endFunction(); 1551 1552 // create1D without usage 1553 startFunction(AM_Public, true, getClassName().c_str(), "create1D", 2, 1554 "RenderScript", RenderScriptVar, "int", "dimX"); 1555 mOut.indent() << "return create1D(" << RenderScriptVar 1556 << ", dimX, Allocation.USAGE_SCRIPT);\n"; 1557 endFunction(); 1558 1559 // create2D without usage 1560 startFunction(AM_Public, true, getClassName().c_str(), "create2D", 3, 1561 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY"); 1562 mOut.indent() << "return create2D(" << RenderScriptVar 1563 << ", dimX, dimY, Allocation.USAGE_SCRIPT);\n"; 1564 endFunction(); 1565 1566 // create2D with usage 1567 startFunction(AM_Public, true, getClassName().c_str(), "create2D", 4, 1568 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY", 1569 "int", "usages"); 1570 1571 mOut.indent() << getClassName() << " obj = new " << getClassName() << "(" 1572 << RenderScriptVar << ");\n"; 1573 mOut.indent() << "Type.Builder b = new Type.Builder(rs, obj.mElement);\n"; 1574 mOut.indent() << "b.setX(dimX);\n"; 1575 mOut.indent() << "b.setY(dimY);\n"; 1576 mOut.indent() << "Type t = b.create();\n"; 1577 mOut.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n"; 1578 mOut.indent() << "return obj;\n"; 1579 endFunction(); 1580 1581 // createTypeBuilder 1582 startFunction(AM_Public, true, "Type.Builder", "createTypeBuilder", 1, 1583 "RenderScript", RenderScriptVar); 1584 mOut.indent() << "Element e = createElement(" << RenderScriptVar << ");\n"; 1585 mOut.indent() << "return new Type.Builder(rs, e);\n"; 1586 endFunction(); 1587 1588 // createCustom with usage 1589 startFunction(AM_Public, true, getClassName().c_str(), "createCustom", 3, 1590 "RenderScript", RenderScriptVar, "Type.Builder", "tb", "int", 1591 "usages"); 1592 mOut.indent() << getClassName() << " obj = new " << getClassName() << "(" 1593 << RenderScriptVar << ");\n"; 1594 mOut.indent() << "Type t = tb.create();\n"; 1595 mOut.indent() << "if (t.getElement() != obj.mElement) {\n"; 1596 mOut.indent() << " throw new RSIllegalArgumentException(" 1597 "\"Type.Builder did not match expected element type.\");\n"; 1598 mOut.indent() << "}\n"; 1599 mOut.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n"; 1600 mOut.indent() << "return obj;\n"; 1601 endFunction(); 1602 } 1603 1604 void RSReflectionJava::genTypeClassCopyToArray(const RSExportRecordType *ERT) { 1605 startFunction(AM_Private, false, "void", "copyToArray", 2, 1606 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index"); 1607 1608 genNewItemBufferPackerIfNull(); 1609 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * " 1610 << mItemSizeof << ");\n"; 1611 1612 mOut.indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME 1613 ");\n"; 1614 1615 endFunction(); 1616 } 1617 1618 void 1619 RSReflectionJava::genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT) { 1620 startFunction(AM_Private, false, "void", "copyToArrayLocal", 2, 1621 RS_TYPE_ITEM_CLASS_NAME, "i", "FieldPacker", "fp"); 1622 1623 genPackVarOfType(ERT, "i", "fp"); 1624 1625 endFunction(); 1626 } 1627 1628 void RSReflectionJava::genTypeClassItemSetter(const RSExportRecordType *ERT) { 1629 startFunction(AM_PublicSynchronized, false, "void", "set", 3, 1630 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index", "boolean", 1631 "copyNow"); 1632 genNewItemBufferIfNull(nullptr); 1633 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << "[index] = i;\n"; 1634 1635 mOut.indent() << "if (copyNow) "; 1636 mOut.startBlock(); 1637 1638 mOut.indent() << "copyToArray(i, index);\n"; 1639 mOut.indent() << "FieldPacker fp = new FieldPacker(" << mItemSizeof << ");\n"; 1640 mOut.indent() << "copyToArrayLocal(i, fp);\n"; 1641 mOut.indent() << "mAllocation.setFromFieldPacker(index, fp);\n"; 1642 1643 // End of if (copyNow) 1644 mOut.endBlock(); 1645 1646 endFunction(); 1647 } 1648 1649 void RSReflectionJava::genTypeClassItemGetter(const RSExportRecordType *ERT) { 1650 startFunction(AM_PublicSynchronized, false, RS_TYPE_ITEM_CLASS_NAME, "get", 1, 1651 "int", "index"); 1652 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME 1653 << " == null) return null;\n"; 1654 mOut.indent() << "return " << RS_TYPE_ITEM_BUFFER_NAME << "[index];\n"; 1655 endFunction(); 1656 } 1657 1658 void 1659 RSReflectionJava::genTypeClassComponentSetter(const RSExportRecordType *ERT) { 1660 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1661 FE = ERT->fields_end(); 1662 FI != FE; FI++) { 1663 const RSExportRecordType::Field *F = *FI; 1664 size_t FieldOffset = F->getOffsetInParent(); 1665 size_t FieldStoreSize = F->getType()->getStoreSize(); 1666 unsigned FieldIndex = getFieldIndex(F); 1667 1668 startFunction(AM_PublicSynchronized, false, "void", "set_" + F->getName(), 1669 3, "int", "index", GetTypeName(F->getType()).c_str(), "v", 1670 "boolean", "copyNow"); 1671 genNewItemBufferPackerIfNull(); 1672 genNewItemBufferIfNull("index"); 1673 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << "[index]." << F->getName() 1674 << " = v;\n"; 1675 1676 mOut.indent() << "if (copyNow) "; 1677 mOut.startBlock(); 1678 1679 if (FieldOffset > 0) { 1680 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * " 1681 << mItemSizeof << " + " << FieldOffset 1682 << ");\n"; 1683 } else { 1684 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * " 1685 << mItemSizeof << ");\n"; 1686 } 1687 genPackVarOfType(F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME); 1688 1689 mOut.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize 1690 << ");\n"; 1691 genPackVarOfType(F->getType(), "v", "fp"); 1692 mOut.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex 1693 << ", fp);\n"; 1694 1695 // End of if (copyNow) 1696 mOut.endBlock(); 1697 1698 endFunction(); 1699 } 1700 } 1701 1702 void 1703 RSReflectionJava::genTypeClassComponentGetter(const RSExportRecordType *ERT) { 1704 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1705 FE = ERT->fields_end(); 1706 FI != FE; FI++) { 1707 const RSExportRecordType::Field *F = *FI; 1708 startFunction(AM_PublicSynchronized, false, 1709 GetTypeName(F->getType()).c_str(), "get_" + F->getName(), 1, 1710 "int", "index"); 1711 mOut.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME << " == null) return " 1712 << GetTypeNullValue(F->getType()) << ";\n"; 1713 mOut.indent() << "return " RS_TYPE_ITEM_BUFFER_NAME << "[index]." 1714 << F->getName() << ";\n"; 1715 endFunction(); 1716 } 1717 } 1718 1719 void RSReflectionJava::genTypeClassCopyAll(const RSExportRecordType *ERT) { 1720 startFunction(AM_PublicSynchronized, false, "void", "copyAll", 0); 1721 1722 mOut.indent() << "for (int ct = 0; ct < " << RS_TYPE_ITEM_BUFFER_NAME 1723 << ".length; ct++)" 1724 << " copyToArray(" << RS_TYPE_ITEM_BUFFER_NAME 1725 << "[ct], ct);\n"; 1726 mOut.indent() << "mAllocation.setFromFieldPacker(0, " 1727 << RS_TYPE_ITEM_BUFFER_PACKER_NAME ");\n"; 1728 1729 endFunction(); 1730 } 1731 1732 void RSReflectionJava::genTypeClassResize() { 1733 startFunction(AM_PublicSynchronized, false, "void", "resize", 1, "int", 1734 "newSize"); 1735 1736 mOut.indent() << "if (mItemArray != null) "; 1737 mOut.startBlock(); 1738 mOut.indent() << "int oldSize = mItemArray.length;\n"; 1739 mOut.indent() << "int copySize = Math.min(oldSize, newSize);\n"; 1740 mOut.indent() << "if (newSize == oldSize) return;\n"; 1741 mOut.indent() << "Item ni[] = new Item[newSize];\n"; 1742 mOut.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);\n"; 1743 mOut.indent() << "mItemArray = ni;\n"; 1744 mOut.endBlock(); 1745 mOut.indent() << "mAllocation.resize(newSize);\n"; 1746 1747 mOut.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME 1748 " != null) " RS_TYPE_ITEM_BUFFER_PACKER_NAME " = " 1749 "new FieldPacker(" << mItemSizeof << " * getType().getX()/* count */);\n"; 1750 1751 endFunction(); 1752 } 1753 1754 /******************** Methods to generate type class /end ********************/ 1755 1756 /********** Methods to create Element in Java of given record type ***********/ 1757 1758 RSReflectionJavaElementBuilder::RSReflectionJavaElementBuilder( 1759 const char *ElementBuilderName, const RSExportRecordType *ERT, 1760 const char *RenderScriptVar, GeneratedFile *Out, const RSContext *RSContext, 1761 RSReflectionJava *Reflection) 1762 : mElementBuilderName(ElementBuilderName), mERT(ERT), 1763 mRenderScriptVar(RenderScriptVar), mOut(Out), mPaddingFieldIndex(1), 1764 mRSContext(RSContext), mReflection(Reflection) { 1765 if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) { 1766 mPaddingPrefix = "#padding_"; 1767 } else { 1768 mPaddingPrefix = "#rs_padding_"; 1769 } 1770 } 1771 1772 void RSReflectionJavaElementBuilder::generate() { 1773 mOut->indent() << "Element.Builder " << mElementBuilderName 1774 << " = new Element.Builder(" << mRenderScriptVar << ");\n"; 1775 genAddElement(mERT, "", /* ArraySize = */ 0); 1776 } 1777 1778 void RSReflectionJavaElementBuilder::genAddElement(const RSExportType *ET, 1779 const std::string &VarName, 1780 unsigned ArraySize) { 1781 std::string ElementConstruct = GetBuiltinElementConstruct(ET); 1782 1783 if (ElementConstruct != "") { 1784 genAddStatementStart(); 1785 *mOut << ElementConstruct << "(" << mRenderScriptVar << ")"; 1786 genAddStatementEnd(VarName, ArraySize); 1787 } else { 1788 1789 switch (ET->getClass()) { 1790 case RSExportType::ExportClassPrimitive: { 1791 const RSExportPrimitiveType *EPT = 1792 static_cast<const RSExportPrimitiveType *>(ET); 1793 const char *DataTypeName = 1794 RSExportPrimitiveType::getRSReflectionType(EPT)->rs_type; 1795 genAddStatementStart(); 1796 *mOut << "Element.createUser(" << mRenderScriptVar 1797 << ", Element.DataType." << DataTypeName << ")"; 1798 genAddStatementEnd(VarName, ArraySize); 1799 break; 1800 } 1801 case RSExportType::ExportClassVector: { 1802 const RSExportVectorType *EVT = 1803 static_cast<const RSExportVectorType *>(ET); 1804 const char *DataTypeName = 1805 RSExportPrimitiveType::getRSReflectionType(EVT)->rs_type; 1806 genAddStatementStart(); 1807 *mOut << "Element.createVector(" << mRenderScriptVar 1808 << ", Element.DataType." << DataTypeName << ", " 1809 << EVT->getNumElement() << ")"; 1810 genAddStatementEnd(VarName, ArraySize); 1811 break; 1812 } 1813 case RSExportType::ExportClassPointer: 1814 // Pointer type variable should be resolved in 1815 // GetBuiltinElementConstruct() 1816 slangAssert(false && "??"); 1817 break; 1818 case RSExportType::ExportClassMatrix: 1819 // Matrix type variable should be resolved 1820 // in GetBuiltinElementConstruct() 1821 slangAssert(false && "??"); 1822 break; 1823 case RSExportType::ExportClassConstantArray: { 1824 const RSExportConstantArrayType *ECAT = 1825 static_cast<const RSExportConstantArrayType *>(ET); 1826 1827 const RSExportType *ElementType = ECAT->getElementType(); 1828 if (ElementType->getClass() != RSExportType::ExportClassRecord) { 1829 genAddElement(ECAT->getElementType(), VarName, ECAT->getSize()); 1830 } else { 1831 std::string NewElementBuilderName(mElementBuilderName); 1832 NewElementBuilderName.append(1, '_'); 1833 1834 RSReflectionJavaElementBuilder builder( 1835 NewElementBuilderName.c_str(), 1836 static_cast<const RSExportRecordType *>(ElementType), 1837 mRenderScriptVar, mOut, mRSContext, mReflection); 1838 builder.generate(); 1839 1840 ArraySize = ECAT->getSize(); 1841 genAddStatementStart(); 1842 *mOut << NewElementBuilderName << ".create()"; 1843 genAddStatementEnd(VarName, ArraySize); 1844 } 1845 break; 1846 } 1847 case RSExportType::ExportClassRecord: { 1848 // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType. 1849 // 1850 // TODO(zonr): Generalize these two function such that there's no 1851 // duplicated codes. 1852 const RSExportRecordType *ERT = 1853 static_cast<const RSExportRecordType *>(ET); 1854 int Pos = 0; // relative pos from now on 1855 1856 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 1857 E = ERT->fields_end(); 1858 I != E; I++) { 1859 const RSExportRecordType::Field *F = *I; 1860 int FieldOffset = F->getOffsetInParent(); 1861 const RSExportType *T = F->getType(); 1862 int FieldStoreSize = T->getStoreSize(); 1863 int FieldAllocSize = T->getAllocSize(); 1864 1865 std::string FieldName; 1866 if (!VarName.empty()) 1867 FieldName = VarName + "." + F->getName(); 1868 else 1869 FieldName = F->getName(); 1870 1871 // Alignment 1872 genAddPadding(FieldOffset - Pos); 1873 1874 // eb.add(...) 1875 mReflection->addFieldIndexMapping(F); 1876 if (F->getType()->getClass() != RSExportType::ExportClassRecord) { 1877 genAddElement(F->getType(), FieldName, 0); 1878 } else { 1879 std::string NewElementBuilderName(mElementBuilderName); 1880 NewElementBuilderName.append(1, '_'); 1881 1882 RSReflectionJavaElementBuilder builder( 1883 NewElementBuilderName.c_str(), 1884 static_cast<const RSExportRecordType *>(F->getType()), 1885 mRenderScriptVar, mOut, mRSContext, mReflection); 1886 builder.generate(); 1887 1888 genAddStatementStart(); 1889 *mOut << NewElementBuilderName << ".create()"; 1890 genAddStatementEnd(FieldName, ArraySize); 1891 } 1892 1893 if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) { 1894 // There is padding within the field type. This is only necessary 1895 // for HC-targeted APIs. 1896 genAddPadding(FieldAllocSize - FieldStoreSize); 1897 } 1898 1899 Pos = FieldOffset + FieldAllocSize; 1900 } 1901 1902 // There maybe some padding after the struct 1903 size_t RecordAllocSize = ERT->getAllocSize(); 1904 1905 genAddPadding(RecordAllocSize - Pos); 1906 break; 1907 } 1908 default: 1909 slangAssert(false && "Unknown class of type"); 1910 break; 1911 } 1912 } 1913 } 1914 1915 void RSReflectionJavaElementBuilder::genAddPadding(int PaddingSize) { 1916 while (PaddingSize > 0) { 1917 const std::string &VarName = createPaddingField(); 1918 genAddStatementStart(); 1919 if (PaddingSize >= 4) { 1920 *mOut << "Element.U32(" << mRenderScriptVar << ")"; 1921 PaddingSize -= 4; 1922 } else if (PaddingSize >= 2) { 1923 *mOut << "Element.U16(" << mRenderScriptVar << ")"; 1924 PaddingSize -= 2; 1925 } else if (PaddingSize >= 1) { 1926 *mOut << "Element.U8(" << mRenderScriptVar << ")"; 1927 PaddingSize -= 1; 1928 } 1929 genAddStatementEnd(VarName, 0); 1930 } 1931 } 1932 1933 void RSReflectionJavaElementBuilder::genAddStatementStart() { 1934 mOut->indent() << mElementBuilderName << ".add("; 1935 } 1936 1937 void 1938 RSReflectionJavaElementBuilder::genAddStatementEnd(const std::string &VarName, 1939 unsigned ArraySize) { 1940 *mOut << ", \"" << VarName << "\""; 1941 if (ArraySize > 0) { 1942 *mOut << ", " << ArraySize; 1943 } 1944 *mOut << ");\n"; 1945 // TODO Review incFieldIndex. It's probably better to assign the numbers at 1946 // the start rather 1947 // than as we're generating the code. 1948 mReflection->incFieldIndex(); 1949 } 1950 1951 /******** Methods to create Element in Java of given record type /end ********/ 1952 1953 bool RSReflectionJava::reflect() { 1954 std::string ErrorMsg; 1955 if (!genScriptClass(mScriptClassName, ErrorMsg)) { 1956 std::cerr << "Failed to generate class " << mScriptClassName << " (" 1957 << ErrorMsg << ")\n"; 1958 return false; 1959 } 1960 1961 mGeneratedFileNames->push_back(mScriptClassName); 1962 1963 // class ScriptField_<TypeName> 1964 for (RSContext::const_export_type_iterator 1965 TI = mRSContext->export_types_begin(), 1966 TE = mRSContext->export_types_end(); 1967 TI != TE; TI++) { 1968 const RSExportType *ET = TI->getValue(); 1969 1970 if (ET->getClass() == RSExportType::ExportClassRecord) { 1971 const RSExportRecordType *ERT = 1972 static_cast<const RSExportRecordType *>(ET); 1973 1974 if (!ERT->isArtificial() && !genTypeClass(ERT, ErrorMsg)) { 1975 std::cerr << "Failed to generate type class for struct '" 1976 << ERT->getName() << "' (" << ErrorMsg << ")\n"; 1977 return false; 1978 } 1979 } 1980 } 1981 1982 return true; 1983 } 1984 1985 const char *RSReflectionJava::AccessModifierStr(AccessModifier AM) { 1986 switch (AM) { 1987 case AM_Public: 1988 return "public"; 1989 break; 1990 case AM_Protected: 1991 return "protected"; 1992 break; 1993 case AM_Private: 1994 return "private"; 1995 break; 1996 case AM_PublicSynchronized: 1997 return "public synchronized"; 1998 break; 1999 default: 2000 return ""; 2001 break; 2002 } 2003 } 2004 2005 bool RSReflectionJava::startClass(AccessModifier AM, bool IsStatic, 2006 const std::string &ClassName, 2007 const char *SuperClassName, 2008 std::string &ErrorMsg) { 2009 // Open file for class 2010 std::string FileName = ClassName + ".java"; 2011 if (!mOut.startFile(mOutputDirectory, FileName, mRSSourceFileName, 2012 mRSContext->getLicenseNote(), true, 2013 mRSContext->getVerbose())) { 2014 return false; 2015 } 2016 2017 // Package 2018 if (!mPackageName.empty()) { 2019 mOut << "package " << mPackageName << ";\n"; 2020 } 2021 mOut << "\n"; 2022 2023 // Imports 2024 mOut << "import " << mRSPackageName << ".*;\n"; 2025 if (getEmbedBitcodeInJava()) { 2026 mOut << "import " << mPackageName << "." 2027 << RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName( 2028 mRSSourceFileName.c_str()) << ";\n"; 2029 } else { 2030 mOut << "import android.content.res.Resources;\n"; 2031 } 2032 mOut << "\n"; 2033 2034 // All reflected classes should be annotated as hidden, so that they won't 2035 // be exposed in SDK. 2036 mOut << "/**\n"; 2037 mOut << " * @hide\n"; 2038 mOut << " */\n"; 2039 2040 mOut << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " 2041 << ClassName; 2042 if (SuperClassName != nullptr) 2043 mOut << " extends " << SuperClassName; 2044 2045 mOut.startBlock(); 2046 2047 mClassName = ClassName; 2048 2049 return true; 2050 } 2051 2052 void RSReflectionJava::endClass() { 2053 mOut.endBlock(); 2054 mOut.closeFile(); 2055 clear(); 2056 } 2057 2058 void RSReflectionJava::startTypeClass(const std::string &ClassName) { 2059 mOut.indent() << "public static class " << ClassName; 2060 mOut.startBlock(); 2061 } 2062 2063 void RSReflectionJava::endTypeClass() { mOut.endBlock(); } 2064 2065 void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic, 2066 const char *ReturnType, 2067 const std::string &FunctionName, int Argc, 2068 ...) { 2069 ArgTy Args; 2070 va_list vl; 2071 va_start(vl, Argc); 2072 2073 for (int i = 0; i < Argc; i++) { 2074 const char *ArgType = va_arg(vl, const char *); 2075 const char *ArgName = va_arg(vl, const char *); 2076 2077 Args.push_back(std::make_pair(ArgType, ArgName)); 2078 } 2079 va_end(vl); 2080 2081 startFunction(AM, IsStatic, ReturnType, FunctionName, Args); 2082 } 2083 2084 void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic, 2085 const char *ReturnType, 2086 const std::string &FunctionName, 2087 const ArgTy &Args) { 2088 mOut.indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") 2089 << ((ReturnType) ? ReturnType : "") << " " << FunctionName 2090 << "("; 2091 2092 bool FirstArg = true; 2093 for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) { 2094 if (!FirstArg) 2095 mOut << ", "; 2096 else 2097 FirstArg = false; 2098 2099 mOut << I->first << " " << I->second; 2100 } 2101 2102 mOut << ")"; 2103 mOut.startBlock(); 2104 } 2105 2106 void RSReflectionJava::endFunction() { mOut.endBlock(); } 2107 2108 bool RSReflectionJava::addTypeNameForElement(const std::string &TypeName) { 2109 if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) { 2110 mTypesToCheck.insert(TypeName); 2111 return true; 2112 } else { 2113 return false; 2114 } 2115 } 2116 2117 bool RSReflectionJava::addTypeNameForFieldPacker(const std::string &TypeName) { 2118 if (mFieldPackerTypes.find(TypeName) == mFieldPackerTypes.end()) { 2119 mFieldPackerTypes.insert(TypeName); 2120 return true; 2121 } else { 2122 return false; 2123 } 2124 } 2125 2126 } // namespace slang 2127