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