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