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