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