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