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