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 60 namespace slang { 61 62 // Some utility function using internal in RSReflection 63 static 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 76 static 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 121 static 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 176 static 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 247 static 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 262 static 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 276 static 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 320 static 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 360 static 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 388 static 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 485 static 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 502 static 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 562 static 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 **********************/ 608 bool 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 648 void 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 701 void 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 716 void 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 759 void 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 slangAssert(false && "Unexpected type of value of initializer."); 813 } 814 } 815 break; 816 } 817 // TODO(zonr): Resolving initializer of a record (and matrix) type variable 818 // is complex. It cannot obtain by just simply evaluating the initializer 819 // expression. 820 case RSExportType::ExportClassMatrix: 821 case RSExportType::ExportClassConstantArray: 822 case RSExportType::ExportClassRecord: { 823 #if 0 824 unsigned InitIndex = 0; 825 const RSExportRecordType *ERT = 826 static_cast<const RSExportRecordType*>(ET); 827 828 slangAssert((Val.getKind() == clang::APValue::Vector) && 829 "Unexpected type of initializer for record type variable"); 830 831 C.indent() << RS_EXPORT_VAR_PREFIX << VarName 832 << " = new "RS_TYPE_CLASS_NAME_PREFIX << ERT->getName() 833 << "."RS_TYPE_ITEM_CLASS_NAME"();" << std::endl; 834 835 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 836 E = ERT->fields_end(); 837 I != E; 838 I++) { 839 const RSExportRecordType::Field *F = *I; 840 std::string FieldName = VarName + "." + F->getName(); 841 842 if (InitIndex > Val.getVectorLength()) 843 break; 844 845 genInitPrimitiveExportVariable(C, 846 FieldName, 847 Val.getVectorElt(InitIndex++)); 848 } 849 #endif 850 slangAssert(false && "Unsupported initializer for record/matrix/constant " 851 "array type variable currently"); 852 break; 853 } 854 default: { 855 slangAssert(false && "Unknown class of type"); 856 } 857 } 858 return; 859 } 860 861 void RSReflection::genExportVariable(Context &C, const RSExportVar *EV) { 862 const RSExportType *ET = EV->getType(); 863 864 C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX 865 << EV->getName() << " = " << C.getNextExportVarSlot() << ";" 866 << std::endl; 867 868 switch (ET->getClass()) { 869 case RSExportType::ExportClassPrimitive: { 870 genPrimitiveTypeExportVariable(C, EV); 871 break; 872 } 873 case RSExportType::ExportClassPointer: { 874 genPointerTypeExportVariable(C, EV); 875 break; 876 } 877 case RSExportType::ExportClassVector: { 878 genVectorTypeExportVariable(C, EV); 879 break; 880 } 881 case RSExportType::ExportClassMatrix: { 882 genMatrixTypeExportVariable(C, EV); 883 break; 884 } 885 case RSExportType::ExportClassConstantArray: { 886 genConstantArrayTypeExportVariable(C, EV); 887 break; 888 } 889 case RSExportType::ExportClassRecord: { 890 genRecordTypeExportVariable(C, EV); 891 break; 892 } 893 default: { 894 slangAssert(false && "Unknown class of type"); 895 } 896 } 897 898 return; 899 } 900 901 void RSReflection::genExportFunction(Context &C, const RSExportFunc *EF) { 902 C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX 903 << EF->getName() << " = " << C.getNextExportFuncSlot() << ";" 904 << std::endl; 905 906 // invoke_*() 907 Context::ArgTy Args; 908 909 if (EF->hasParam()) { 910 for (RSExportFunc::const_param_iterator I = EF->params_begin(), 911 E = EF->params_end(); 912 I != E; 913 I++) { 914 Args.push_back(std::make_pair(GetTypeName((*I)->getType()), 915 (*I)->getName())); 916 } 917 } 918 919 C.startFunction(Context::AM_Public, 920 false, 921 "void", 922 "invoke_" + EF->getName(/*Mangle=*/ false), 923 // We are using un-mangled name since Java 924 // supports method overloading. 925 Args); 926 927 if (!EF->hasParam()) { 928 C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");" 929 << std::endl; 930 } else { 931 const RSExportRecordType *ERT = EF->getParamPacketType(); 932 std::string FieldPackerName = EF->getName() + "_fp"; 933 934 if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str())) 935 genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str()); 936 937 C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", " 938 << FieldPackerName << ");" << std::endl; 939 } 940 941 C.endFunction(); 942 return; 943 } 944 945 void RSReflection::genExportForEach(Context &C, const RSExportForEach *EF) { 946 C.indent() << "private final static int "RS_EXPORT_FOREACH_INDEX_PREFIX 947 << EF->getName() << " = " << C.getNextExportForEachSlot() << ";" 948 << std::endl; 949 950 // forEach_*() 951 Context::ArgTy Args; 952 953 slangAssert(EF->getNumParameters() > 0); 954 955 if (EF->hasIn()) 956 Args.push_back(std::make_pair("Allocation", "ain")); 957 if (EF->hasOut()) 958 Args.push_back(std::make_pair("Allocation", "aout")); 959 960 const RSExportRecordType *ERT = EF->getParamPacketType(); 961 if (ERT) { 962 for (RSExportForEach::const_param_iterator I = EF->params_begin(), 963 E = EF->params_end(); 964 I != E; 965 I++) { 966 Args.push_back(std::make_pair(GetTypeName((*I)->getType()), 967 (*I)->getName())); 968 } 969 } 970 971 C.startFunction(Context::AM_Public, 972 false, 973 "void", 974 "forEach_" + EF->getName(), 975 Args); 976 977 const RSExportType *IET = EF->getInType(); 978 if (IET) { 979 genTypeCheck(C, IET, "ain"); 980 } 981 982 const RSExportType *OET = EF->getOutType(); 983 if (OET) { 984 genTypeCheck(C, OET, "aout"); 985 } 986 987 if (EF->hasIn() && EF->hasOut()) { 988 C.indent() << "// Verify dimensions" << std::endl; 989 C.indent() << "Type tIn = ain.getType();" << std::endl; 990 C.indent() << "Type tOut = aout.getType();" << std::endl; 991 C.indent() << "if ((tIn.getCount() != tOut.getCount()) ||" << std::endl; 992 C.indent() << " (tIn.getX() != tOut.getX()) ||" << std::endl; 993 C.indent() << " (tIn.getY() != tOut.getY()) ||" << std::endl; 994 C.indent() << " (tIn.getZ() != tOut.getZ()) ||" << std::endl; 995 C.indent() << " (tIn.hasFaces() != tOut.hasFaces()) ||" << std::endl; 996 C.indent() << " (tIn.hasMipmaps() != tOut.hasMipmaps())) {" << std::endl; 997 C.indent() << " throw new RSRuntimeException(\"Dimension mismatch " 998 << "between input and output parameters!\");"; 999 C.out() << std::endl; 1000 C.indent() << "}" << std::endl; 1001 } 1002 1003 std::string FieldPackerName = EF->getName() + "_fp"; 1004 if (ERT) { 1005 if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str())) { 1006 genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str()); 1007 } 1008 } 1009 C.indent() << "forEach("RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName(); 1010 1011 if (EF->hasIn()) 1012 C.out() << ", ain"; 1013 else 1014 C.out() << ", null"; 1015 1016 if (EF->hasOut()) 1017 C.out() << ", aout"; 1018 else 1019 C.out() << ", null"; 1020 1021 if (EF->hasUsrData()) 1022 C.out() << ", " << FieldPackerName; 1023 else 1024 C.out() << ", null"; 1025 1026 C.out() << ");" << std::endl; 1027 1028 C.endFunction(); 1029 return; 1030 } 1031 1032 void RSReflection::genTypeInstance(Context &C, 1033 const RSExportType *ET) { 1034 if (ET->getClass() == RSExportType::ExportClassPointer) { 1035 const RSExportPointerType *EPT = 1036 static_cast<const RSExportPointerType*>(ET); 1037 ET = EPT->getPointeeType(); 1038 switch (ET->getClass()) { 1039 case RSExportType::ExportClassPrimitive: { 1040 const RSExportPrimitiveType *EPT = 1041 static_cast<const RSExportPrimitiveType*>(ET); 1042 slangAssert(EPT); 1043 1044 switch (EPT->getKind()) { 1045 case RSExportPrimitiveType::DataKindPixelL: 1046 case RSExportPrimitiveType::DataKindPixelA: 1047 case RSExportPrimitiveType::DataKindPixelLA: 1048 case RSExportPrimitiveType::DataKindPixelRGB: 1049 case RSExportPrimitiveType::DataKindPixelRGBA: { 1050 break; 1051 } 1052 1053 case RSExportPrimitiveType::DataKindUser: 1054 default: { 1055 std::string TypeName = GetElementJavaTypeName(EPT->getType()); 1056 if (C.mTypesToCheck.find(TypeName) == C.mTypesToCheck.end()) { 1057 C.indent() << "__" << TypeName << " = Element." << TypeName 1058 << "(rs);" << std::endl; 1059 C.mTypesToCheck.insert(TypeName); 1060 } 1061 break; 1062 } 1063 } 1064 break; 1065 } 1066 1067 case RSExportType::ExportClassVector: { 1068 const RSExportVectorType *EVT = 1069 static_cast<const RSExportVectorType*>(ET); 1070 slangAssert(EVT); 1071 1072 const char *TypeName = GetVectorElementName(EVT); 1073 if (C.mTypesToCheck.find(TypeName) == C.mTypesToCheck.end()) { 1074 C.indent() << "__" << TypeName << " = Element." << TypeName 1075 << "(rs);" << std::endl; 1076 C.mTypesToCheck.insert(TypeName); 1077 } 1078 break; 1079 } 1080 1081 case RSExportType::ExportClassRecord: { 1082 const RSExportRecordType *ERT = 1083 static_cast<const RSExportRecordType*>(ET); 1084 slangAssert(ERT); 1085 1086 std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName(); 1087 if (C.mTypesToCheck.find(ClassName) == C.mTypesToCheck.end()) { 1088 C.indent() << "__" << ClassName << " = " << ClassName << 1089 ".createElement(rs);" << std::endl; 1090 C.mTypesToCheck.insert(ClassName); 1091 } 1092 break; 1093 } 1094 1095 default: 1096 break; 1097 } 1098 } 1099 } 1100 1101 void RSReflection::genTypeCheck(Context &C, 1102 const RSExportType *ET, 1103 const char *VarName) { 1104 C.indent() << "// check " << VarName << std::endl; 1105 1106 if (ET->getClass() == RSExportType::ExportClassPointer) { 1107 const RSExportPointerType *EPT = 1108 static_cast<const RSExportPointerType*>(ET); 1109 ET = EPT->getPointeeType(); 1110 } 1111 1112 std::string TypeName; 1113 1114 switch (ET->getClass()) { 1115 case RSExportType::ExportClassPrimitive: { 1116 const RSExportPrimitiveType *EPT = 1117 static_cast<const RSExportPrimitiveType*>(ET); 1118 slangAssert(EPT); 1119 1120 if (EPT->getKind() == RSExportPrimitiveType::DataKindUser) { 1121 TypeName = GetElementJavaTypeName(EPT->getType()); 1122 } 1123 break; 1124 } 1125 1126 case RSExportType::ExportClassVector: { 1127 const RSExportVectorType *EVT = 1128 static_cast<const RSExportVectorType*>(ET); 1129 slangAssert(EVT); 1130 TypeName = GetVectorElementName(EVT); 1131 break; 1132 } 1133 1134 case RSExportType::ExportClassRecord: { 1135 const RSExportRecordType *ERT = 1136 static_cast<const RSExportRecordType*>(ET); 1137 slangAssert(ERT); 1138 TypeName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName(); 1139 break; 1140 } 1141 1142 default: 1143 break; 1144 } 1145 1146 if (!TypeName.empty()) { 1147 C.indent() << "if (!" << VarName 1148 << ".getType().getElement().isCompatible(__" 1149 << TypeName << ")) {" << std::endl; 1150 C.indent() << " throw new RSRuntimeException(\"Type mismatch with " 1151 << TypeName << "!\");" << std::endl; 1152 C.indent() << "}" << std::endl; 1153 } 1154 1155 return; 1156 } 1157 1158 1159 void RSReflection::genPrimitiveTypeExportVariable( 1160 Context &C, 1161 const RSExportVar *EV) { 1162 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive) 1163 && "Variable should be type of primitive here"); 1164 1165 const RSExportPrimitiveType *EPT = 1166 static_cast<const RSExportPrimitiveType*>(EV->getType()); 1167 const char *TypeName = GetPrimitiveTypeName(EPT); 1168 1169 C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX 1170 << EV->getName() << ";" << std::endl; 1171 1172 // set_*() 1173 if (!EV->isConst()) { 1174 C.startFunction(Context::AM_Public, 1175 false, 1176 "void", 1177 "set_" + EV->getName(), 1178 1, 1179 TypeName, "v"); 1180 C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl; 1181 1182 C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() 1183 << ", v);" << std::endl; 1184 1185 C.endFunction(); 1186 } 1187 1188 genGetExportVariable(C, TypeName, EV->getName()); 1189 1190 return; 1191 } 1192 1193 void RSReflection::genPointerTypeExportVariable(Context &C, 1194 const RSExportVar *EV) { 1195 const RSExportType *ET = EV->getType(); 1196 const RSExportType *PointeeType; 1197 std::string TypeName; 1198 1199 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) && 1200 "Variable should be type of pointer here"); 1201 1202 PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType(); 1203 TypeName = GetTypeName(ET); 1204 1205 C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX 1206 << EV->getName() << ";" << std::endl; 1207 1208 // bind_*() 1209 C.startFunction(Context::AM_Public, 1210 false, 1211 "void", 1212 "bind_" + EV->getName(), 1213 1, 1214 TypeName.c_str(), "v"); 1215 1216 C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl; 1217 C.indent() << "if (v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX 1218 << EV->getName() << ");" << std::endl; 1219 1220 if (PointeeType->getClass() == RSExportType::ExportClassRecord) 1221 C.indent() << "else bindAllocation(v.getAllocation(), " 1222 RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" 1223 << std::endl; 1224 else 1225 C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX 1226 << EV->getName() << ");" << std::endl; 1227 1228 C.endFunction(); 1229 1230 genGetExportVariable(C, TypeName, EV->getName()); 1231 1232 return; 1233 } 1234 1235 void RSReflection::genVectorTypeExportVariable(Context &C, 1236 const RSExportVar *EV) { 1237 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) && 1238 "Variable should be type of vector here"); 1239 1240 const RSExportVectorType *EVT = 1241 static_cast<const RSExportVectorType*>(EV->getType()); 1242 const char *TypeName = GetVectorTypeName(EVT); 1243 const char *FieldPackerName = "fp"; 1244 1245 C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX 1246 << EV->getName() << ";" << std::endl; 1247 1248 // set_*() 1249 if (!EV->isConst()) { 1250 C.startFunction(Context::AM_Public, 1251 false, 1252 "void", 1253 "set_" + EV->getName(), 1254 1, 1255 TypeName, "v"); 1256 C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl; 1257 1258 if (genCreateFieldPacker(C, EVT, FieldPackerName)) 1259 genPackVarOfType(C, EVT, "v", FieldPackerName); 1260 C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " 1261 << FieldPackerName << ");" << std::endl; 1262 1263 C.endFunction(); 1264 } 1265 1266 genGetExportVariable(C, TypeName, EV->getName()); 1267 return; 1268 } 1269 1270 void RSReflection::genMatrixTypeExportVariable(Context &C, 1271 const RSExportVar *EV) { 1272 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) && 1273 "Variable should be type of matrix here"); 1274 1275 const RSExportMatrixType *EMT = 1276 static_cast<const RSExportMatrixType*>(EV->getType()); 1277 const char *TypeName = GetMatrixTypeName(EMT); 1278 const char *FieldPackerName = "fp"; 1279 1280 C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX 1281 << EV->getName() << ";" << std::endl; 1282 1283 // set_*() 1284 if (!EV->isConst()) { 1285 C.startFunction(Context::AM_Public, 1286 false, 1287 "void", 1288 "set_" + EV->getName(), 1289 1, 1290 TypeName, "v"); 1291 C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl; 1292 1293 if (genCreateFieldPacker(C, EMT, FieldPackerName)) 1294 genPackVarOfType(C, EMT, "v", FieldPackerName); 1295 C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " 1296 << FieldPackerName << ");" << std::endl; 1297 1298 C.endFunction(); 1299 } 1300 1301 genGetExportVariable(C, TypeName, EV->getName()); 1302 return; 1303 } 1304 1305 void RSReflection::genConstantArrayTypeExportVariable( 1306 Context &C, 1307 const RSExportVar *EV) { 1308 slangAssert((EV->getType()->getClass() == 1309 RSExportType::ExportClassConstantArray) && 1310 "Variable should be type of constant array here"); 1311 1312 const RSExportConstantArrayType *ECAT = 1313 static_cast<const RSExportConstantArrayType*>(EV->getType()); 1314 std::string TypeName = GetTypeName(ECAT); 1315 const char *FieldPackerName = "fp"; 1316 1317 C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX 1318 << EV->getName() << ";" << std::endl; 1319 1320 // set_*() 1321 if (!EV->isConst()) { 1322 C.startFunction(Context::AM_Public, 1323 false, 1324 "void", 1325 "set_" + EV->getName(), 1326 1, 1327 TypeName.c_str(), "v"); 1328 C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl; 1329 1330 if (genCreateFieldPacker(C, ECAT, FieldPackerName)) 1331 genPackVarOfType(C, ECAT, "v", FieldPackerName); 1332 C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " 1333 << FieldPackerName << ");" << std::endl; 1334 1335 C.endFunction(); 1336 } 1337 1338 genGetExportVariable(C, TypeName, EV->getName()); 1339 return; 1340 } 1341 1342 void RSReflection::genRecordTypeExportVariable(Context &C, 1343 const RSExportVar *EV) { 1344 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && 1345 "Variable should be type of struct here"); 1346 1347 const RSExportRecordType *ERT = 1348 static_cast<const RSExportRecordType*>(EV->getType()); 1349 std::string TypeName = 1350 RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME; 1351 const char *FieldPackerName = "fp"; 1352 1353 C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX 1354 << EV->getName() << ";" << std::endl; 1355 1356 // set_*() 1357 if (!EV->isConst()) { 1358 C.startFunction(Context::AM_Public, 1359 false, 1360 "void", 1361 "set_" + EV->getName(), 1362 1, 1363 TypeName.c_str(), "v"); 1364 C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl; 1365 1366 if (genCreateFieldPacker(C, ERT, FieldPackerName)) 1367 genPackVarOfType(C, ERT, "v", FieldPackerName); 1368 C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() 1369 << ", " << FieldPackerName << ");" << std::endl; 1370 1371 C.endFunction(); 1372 } 1373 1374 genGetExportVariable(C, TypeName.c_str(), EV->getName()); 1375 return; 1376 } 1377 1378 void RSReflection::genGetExportVariable(Context &C, 1379 const std::string &TypeName, 1380 const std::string &VarName) { 1381 C.startFunction(Context::AM_Public, 1382 false, 1383 TypeName.c_str(), 1384 "get_" + VarName, 1385 0); 1386 1387 C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << std::endl; 1388 1389 C.endFunction(); 1390 return; 1391 } 1392 1393 /******************* Methods to generate script class /end *******************/ 1394 1395 bool RSReflection::genCreateFieldPacker(Context &C, 1396 const RSExportType *ET, 1397 const char *FieldPackerName) { 1398 size_t AllocSize = RSExportType::GetTypeAllocSize(ET); 1399 if (AllocSize > 0) 1400 C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" 1401 << AllocSize << ");" << std::endl; 1402 else 1403 return false; 1404 return true; 1405 } 1406 1407 void RSReflection::genPackVarOfType(Context &C, 1408 const RSExportType *ET, 1409 const char *VarName, 1410 const char *FieldPackerName) { 1411 switch (ET->getClass()) { 1412 case RSExportType::ExportClassPrimitive: 1413 case RSExportType::ExportClassVector: { 1414 C.indent() << FieldPackerName << "." 1415 << GetPackerAPIName( 1416 static_cast<const RSExportPrimitiveType*>(ET)) 1417 << "(" << VarName << ");" << std::endl; 1418 break; 1419 } 1420 case RSExportType::ExportClassPointer: { 1421 // Must reflect as type Allocation in Java 1422 const RSExportType *PointeeType = 1423 static_cast<const RSExportPointerType*>(ET)->getPointeeType(); 1424 1425 if (PointeeType->getClass() != RSExportType::ExportClassRecord) 1426 C.indent() << FieldPackerName << ".addI32(" << VarName 1427 << ".getPtr());" << std::endl; 1428 else 1429 C.indent() << FieldPackerName << ".addI32(" << VarName 1430 << ".getAllocation().getPtr());" << std::endl; 1431 break; 1432 } 1433 case RSExportType::ExportClassMatrix: { 1434 C.indent() << FieldPackerName << ".addMatrix(" << VarName << ");" 1435 << std::endl; 1436 break; 1437 } 1438 case RSExportType::ExportClassConstantArray: { 1439 const RSExportConstantArrayType *ECAT = 1440 static_cast<const RSExportConstantArrayType *>(ET); 1441 1442 // TODO(zonr): more elegant way. Currently, we obtain the unique index 1443 // variable (this method involves recursive call which means 1444 // we may have more than one level loop, therefore we can't 1445 // always use the same index variable name here) name given 1446 // in the for-loop from counting the '.' in @VarName. 1447 unsigned Level = 0; 1448 size_t LastDotPos = 0; 1449 std::string ElementVarName(VarName); 1450 1451 while (LastDotPos != std::string::npos) { 1452 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1); 1453 Level++; 1454 } 1455 std::string IndexVarName("ct"); 1456 IndexVarName.append(llvm::utostr_32(Level)); 1457 1458 C.indent() << "for (int " << IndexVarName << " = 0; " << 1459 IndexVarName << " < " << ECAT->getSize() << "; " << 1460 IndexVarName << "++)"; 1461 C.startBlock(); 1462 1463 ElementVarName.append("[" + IndexVarName + "]"); 1464 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(), 1465 FieldPackerName); 1466 1467 C.endBlock(); 1468 break; 1469 } 1470 case RSExportType::ExportClassRecord: { 1471 const RSExportRecordType *ERT = 1472 static_cast<const RSExportRecordType*>(ET); 1473 // Relative pos from now on in field packer 1474 unsigned Pos = 0; 1475 1476 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 1477 E = ERT->fields_end(); 1478 I != E; 1479 I++) { 1480 const RSExportRecordType::Field *F = *I; 1481 std::string FieldName; 1482 size_t FieldOffset = F->getOffsetInParent(); 1483 size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); 1484 size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType()); 1485 1486 if (VarName != NULL) 1487 FieldName = VarName + ("." + F->getName()); 1488 else 1489 FieldName = F->getName(); 1490 1491 if (FieldOffset > Pos) 1492 C.indent() << FieldPackerName << ".skip(" 1493 << (FieldOffset - Pos) << ");" << std::endl; 1494 1495 genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName); 1496 1497 // There is padding in the field type 1498 if (FieldAllocSize > FieldStoreSize) 1499 C.indent() << FieldPackerName << ".skip(" 1500 << (FieldAllocSize - FieldStoreSize) 1501 << ");" << std::endl; 1502 1503 Pos = FieldOffset + FieldAllocSize; 1504 } 1505 1506 // There maybe some padding after the struct 1507 if (RSExportType::GetTypeAllocSize(ERT) > Pos) 1508 C.indent() << FieldPackerName << ".skip(" 1509 << RSExportType::GetTypeAllocSize(ERT) - Pos << ");" 1510 << std::endl; 1511 break; 1512 } 1513 default: { 1514 slangAssert(false && "Unknown class of type"); 1515 } 1516 } 1517 1518 return; 1519 } 1520 1521 void RSReflection::genAllocateVarOfType(Context &C, 1522 const RSExportType *T, 1523 const std::string &VarName) { 1524 switch (T->getClass()) { 1525 case RSExportType::ExportClassPrimitive: { 1526 // Primitive type like int in Java has its own storage once it's declared. 1527 // 1528 // FIXME: Should we allocate storage for RS object? 1529 // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType()) 1530 // C.indent() << VarName << " = new " << GetTypeName(T) << "();" 1531 // << std::endl; 1532 break; 1533 } 1534 case RSExportType::ExportClassPointer: { 1535 // Pointer type is an instance of Allocation or a TypeClass whose value is 1536 // expected to be assigned by programmer later in Java program. Therefore 1537 // we don't reflect things like [VarName] = new Allocation(); 1538 C.indent() << VarName << " = null;" << std::endl; 1539 break; 1540 } 1541 case RSExportType::ExportClassConstantArray: { 1542 const RSExportConstantArrayType *ECAT = 1543 static_cast<const RSExportConstantArrayType *>(T); 1544 const RSExportType *ElementType = ECAT->getElementType(); 1545 1546 C.indent() << VarName << " = new " << GetTypeName(ElementType) 1547 << "[" << ECAT->getSize() << "];" << std::endl; 1548 1549 // Primitive type element doesn't need allocation code. 1550 if (ElementType->getClass() != RSExportType::ExportClassPrimitive) { 1551 C.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() << "; " 1552 "$ct++)"; 1553 C.startBlock(); 1554 1555 std::string ElementVarName(VarName); 1556 ElementVarName.append("[$ct]"); 1557 genAllocateVarOfType(C, ElementType, ElementVarName); 1558 1559 C.endBlock(); 1560 } 1561 break; 1562 } 1563 case RSExportType::ExportClassVector: 1564 case RSExportType::ExportClassMatrix: 1565 case RSExportType::ExportClassRecord: { 1566 C.indent() << VarName << " = new " << GetTypeName(T) << "();" 1567 << std::endl; 1568 break; 1569 } 1570 } 1571 return; 1572 } 1573 1574 void RSReflection::genNewItemBufferIfNull(Context &C, 1575 const char *Index) { 1576 C.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) " 1577 RS_TYPE_ITEM_BUFFER_NAME " = " 1578 "new " RS_TYPE_ITEM_CLASS_NAME 1579 "[getType().getX() /* count */];" 1580 << std::endl; 1581 if (Index != NULL) 1582 C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] == null) " 1583 RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = " 1584 "new "RS_TYPE_ITEM_CLASS_NAME"();" << std::endl; 1585 return; 1586 } 1587 1588 void RSReflection::genNewItemBufferPackerIfNull(Context &C) { 1589 C.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME " == null) " 1590 RS_TYPE_ITEM_BUFFER_PACKER_NAME " = " 1591 "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME 1592 ".sizeof * getType().getX()/* count */" 1593 ");" << std::endl; 1594 return; 1595 } 1596 1597 /********************** Methods to generate type class **********************/ 1598 bool RSReflection::genTypeClass(Context &C, 1599 const RSExportRecordType *ERT, 1600 std::string &ErrorMsg) { 1601 std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName(); 1602 1603 if (!C.startClass(Context::AM_Public, 1604 false, 1605 ClassName, 1606 RS_TYPE_CLASS_SUPER_CLASS_NAME, 1607 ErrorMsg)) 1608 return false; 1609 1610 mGeneratedFileNames->push_back(ClassName); 1611 1612 genTypeItemClass(C, ERT); 1613 1614 // Declare item buffer and item buffer packer 1615 C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[]" 1616 ";" << std::endl; 1617 C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";" 1618 << std::endl; 1619 1620 genTypeClassConstructor(C, ERT); 1621 genTypeClassCopyToArrayLocal(C, ERT); 1622 genTypeClassCopyToArray(C, ERT); 1623 genTypeClassItemSetter(C, ERT); 1624 genTypeClassItemGetter(C, ERT); 1625 genTypeClassComponentSetter(C, ERT); 1626 genTypeClassComponentGetter(C, ERT); 1627 genTypeClassCopyAll(C, ERT); 1628 genTypeClassResize(C); 1629 1630 C.endClass(); 1631 1632 C.resetFieldIndex(); 1633 C.clearFieldIndexMap(); 1634 1635 return true; 1636 } 1637 1638 void RSReflection::genTypeItemClass(Context &C, 1639 const RSExportRecordType *ERT) { 1640 C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME; 1641 C.startBlock(); 1642 1643 C.indent() << "public static final int sizeof = " 1644 << RSExportType::GetTypeAllocSize(ERT) << ";" << std::endl; 1645 1646 // Member elements 1647 C.out() << std::endl; 1648 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1649 FE = ERT->fields_end(); 1650 FI != FE; 1651 FI++) { 1652 C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() 1653 << ";" << std::endl; 1654 } 1655 1656 // Constructor 1657 C.out() << std::endl; 1658 C.indent() << RS_TYPE_ITEM_CLASS_NAME"()"; 1659 C.startBlock(); 1660 1661 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1662 FE = ERT->fields_end(); 1663 FI != FE; 1664 FI++) { 1665 const RSExportRecordType::Field *F = *FI; 1666 genAllocateVarOfType(C, F->getType(), F->getName()); 1667 } 1668 1669 // end Constructor 1670 C.endBlock(); 1671 1672 // end Item class 1673 C.endBlock(); 1674 1675 return; 1676 } 1677 1678 void RSReflection::genTypeClassConstructor(Context &C, 1679 const RSExportRecordType *ERT) { 1680 const char *RenderScriptVar = "rs"; 1681 1682 C.startFunction(Context::AM_Public, 1683 true, 1684 "Element", 1685 "createElement", 1686 1, 1687 "RenderScript", RenderScriptVar); 1688 genBuildElement(C, "eb", ERT, RenderScriptVar, /* IsInline = */false); 1689 C.endFunction(); 1690 1691 C.startFunction(Context::AM_Public, 1692 false, 1693 NULL, 1694 C.getClassName(), 1695 2, 1696 "RenderScript", RenderScriptVar, 1697 "int", "count"); 1698 1699 C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl; 1700 C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl; 1701 C.indent() << "mElement = createElement(" << RenderScriptVar << ");" 1702 << std::endl; 1703 // Call init() in super class 1704 C.indent() << "init(" << RenderScriptVar << ", count);" << std::endl; 1705 C.endFunction(); 1706 1707 C.startFunction(Context::AM_Public, 1708 false, 1709 NULL, 1710 C.getClassName(), 1711 3, 1712 "RenderScript", RenderScriptVar, 1713 "int", "count", 1714 "int", "usages"); 1715 1716 C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl; 1717 C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl; 1718 C.indent() << "mElement = createElement(" << RenderScriptVar << ");" 1719 << std::endl; 1720 // Call init() in super class 1721 C.indent() << "init(" << RenderScriptVar << ", count, usages);" << std::endl; 1722 C.endFunction(); 1723 1724 return; 1725 } 1726 1727 void RSReflection::genTypeClassCopyToArray(Context &C, 1728 const RSExportRecordType *ERT) { 1729 C.startFunction(Context::AM_Private, 1730 false, 1731 "void", 1732 "copyToArray", 1733 2, 1734 RS_TYPE_ITEM_CLASS_NAME, "i", 1735 "int", "index"); 1736 1737 genNewItemBufferPackerIfNull(C); 1738 C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1739 ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" 1740 << std::endl; 1741 1742 C.indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME 1743 ");" << std::endl; 1744 1745 C.endFunction(); 1746 return; 1747 } 1748 1749 void RSReflection::genTypeClassCopyToArrayLocal(Context &C, 1750 const RSExportRecordType *ERT) { 1751 C.startFunction(Context::AM_Private, 1752 false, 1753 "void", 1754 "copyToArrayLocal", 1755 2, 1756 RS_TYPE_ITEM_CLASS_NAME, "i", 1757 "FieldPacker", "fp"); 1758 1759 genPackVarOfType(C, ERT, "i", "fp"); 1760 1761 C.endFunction(); 1762 return; 1763 } 1764 1765 void RSReflection::genTypeClassItemSetter(Context &C, 1766 const RSExportRecordType *ERT) { 1767 C.startFunction(Context::AM_PublicSynchronized, 1768 false, 1769 "void", 1770 "set", 1771 3, 1772 RS_TYPE_ITEM_CLASS_NAME, "i", 1773 "int", "index", 1774 "boolean", "copyNow"); 1775 genNewItemBufferIfNull(C, NULL); 1776 C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << std::endl; 1777 1778 C.indent() << "if (copyNow) "; 1779 C.startBlock(); 1780 1781 C.indent() << "copyToArray(i, index);" << std::endl; 1782 C.indent() << "FieldPacker fp = new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME 1783 ".sizeof);" << std::endl; 1784 C.indent() << "copyToArrayLocal(i, fp);" << std::endl; 1785 C.indent() << "mAllocation.setFromFieldPacker(index, fp);" << std::endl; 1786 1787 // End of if (copyNow) 1788 C.endBlock(); 1789 1790 C.endFunction(); 1791 return; 1792 } 1793 1794 void RSReflection::genTypeClassItemGetter(Context &C, 1795 const RSExportRecordType *ERT) { 1796 C.startFunction(Context::AM_PublicSynchronized, 1797 false, 1798 RS_TYPE_ITEM_CLASS_NAME, 1799 "get", 1800 1, 1801 "int", "index"); 1802 C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;" 1803 << std::endl; 1804 C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index];" << std::endl; 1805 C.endFunction(); 1806 return; 1807 } 1808 1809 void RSReflection::genTypeClassComponentSetter(Context &C, 1810 const RSExportRecordType *ERT) { 1811 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1812 FE = ERT->fields_end(); 1813 FI != FE; 1814 FI++) { 1815 const RSExportRecordType::Field *F = *FI; 1816 size_t FieldOffset = F->getOffsetInParent(); 1817 size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); 1818 unsigned FieldIndex = C.getFieldIndex(F); 1819 1820 C.startFunction(Context::AM_PublicSynchronized, 1821 false, 1822 "void", 1823 "set_" + F->getName(), 3, 1824 "int", "index", 1825 GetTypeName(F->getType()).c_str(), "v", 1826 "boolean", "copyNow"); 1827 genNewItemBufferPackerIfNull(C); 1828 genNewItemBufferIfNull(C, "index"); 1829 C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName() 1830 << " = v;" << std::endl; 1831 1832 C.indent() << "if (copyNow) "; 1833 C.startBlock(); 1834 1835 if (FieldOffset > 0) 1836 C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1837 ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof + " 1838 << FieldOffset << ");" << std::endl; 1839 else 1840 C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME 1841 ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" 1842 << std::endl; 1843 genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME); 1844 1845 C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");" 1846 << std::endl; 1847 genPackVarOfType(C, F->getType(), "v", "fp"); 1848 C.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex 1849 << ", fp);" 1850 << std::endl; 1851 1852 // End of if (copyNow) 1853 C.endBlock(); 1854 1855 C.endFunction(); 1856 } 1857 return; 1858 } 1859 1860 void RSReflection::genTypeClassComponentGetter(Context &C, 1861 const RSExportRecordType *ERT) { 1862 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(), 1863 FE = ERT->fields_end(); 1864 FI != FE; 1865 FI++) { 1866 const RSExportRecordType::Field *F = *FI; 1867 C.startFunction(Context::AM_PublicSynchronized, 1868 false, 1869 GetTypeName(F->getType()).c_str(), 1870 "get_" + F->getName(), 1871 1, 1872 "int", "index"); 1873 C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return " 1874 << GetTypeNullValue(F->getType()) << ";" << std::endl; 1875 C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName() 1876 << ";" << std::endl; 1877 C.endFunction(); 1878 } 1879 return; 1880 } 1881 1882 void RSReflection::genTypeClassCopyAll(Context &C, 1883 const RSExportRecordType *ERT) { 1884 C.startFunction(Context::AM_PublicSynchronized, false, "void", "copyAll", 0); 1885 1886 C.indent() << "for (int ct = 0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++)" 1887 " copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);" 1888 << std::endl; 1889 C.indent() << "mAllocation.setFromFieldPacker(0, " 1890 RS_TYPE_ITEM_BUFFER_PACKER_NAME");" 1891 << std::endl; 1892 1893 C.endFunction(); 1894 return; 1895 } 1896 1897 void RSReflection::genTypeClassResize(Context &C) { 1898 C.startFunction(Context::AM_PublicSynchronized, 1899 false, 1900 "void", 1901 "resize", 1902 1, 1903 "int", "newSize"); 1904 1905 C.indent() << "if (mItemArray != null) "; 1906 C.startBlock(); 1907 C.indent() << "int oldSize = mItemArray.length;" << std::endl; 1908 C.indent() << "int copySize = Math.min(oldSize, newSize);" << std::endl; 1909 C.indent() << "if (newSize == oldSize) return;" << std::endl; 1910 C.indent() << "Item ni[] = new Item[newSize];" << std::endl; 1911 C.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);" 1912 << std::endl; 1913 C.indent() << "mItemArray = ni;" << std::endl; 1914 C.endBlock(); 1915 C.indent() << "mAllocation.resize(newSize);" << std::endl; 1916 1917 C.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME " != null) " 1918 RS_TYPE_ITEM_BUFFER_PACKER_NAME " = " 1919 "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME 1920 ".sizeof * getType().getX()/* count */" 1921 ");" << std::endl; 1922 1923 C.endFunction(); 1924 return; 1925 } 1926 1927 /******************** Methods to generate type class /end ********************/ 1928 1929 /********** Methods to create Element in Java of given record type ***********/ 1930 void RSReflection::genBuildElement(Context &C, 1931 const char *ElementBuilderName, 1932 const RSExportRecordType *ERT, 1933 const char *RenderScriptVar, 1934 bool IsInline) { 1935 C.indent() << "Element.Builder " << ElementBuilderName << " = " 1936 "new Element.Builder(" << RenderScriptVar << ");" << std::endl; 1937 1938 // eb.add(...) 1939 genAddElementToElementBuilder(C, 1940 ERT, 1941 "", 1942 ElementBuilderName, 1943 RenderScriptVar, 1944 /* ArraySize = */0); 1945 1946 if (!IsInline) 1947 C.indent() << "return " << ElementBuilderName << ".create();" << std::endl; 1948 return; 1949 } 1950 1951 #define EB_ADD(x) do { \ 1952 C.indent() << ElementBuilderName \ 1953 << ".add(" << x << ", \"" << VarName << "\""; \ 1954 if (ArraySize > 0) \ 1955 C.out() << ", " << ArraySize; \ 1956 C.out() << ");" << std::endl; \ 1957 C.incFieldIndex(); \ 1958 } while (false) 1959 1960 void RSReflection::genAddElementToElementBuilder(Context &C, 1961 const RSExportType *ET, 1962 const std::string &VarName, 1963 const char *ElementBuilderName, 1964 const char *RenderScriptVar, 1965 unsigned ArraySize) { 1966 const char *ElementConstruct = GetBuiltinElementConstruct(ET); 1967 1968 if (ElementConstruct != NULL) { 1969 EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")"); 1970 } else { 1971 if ((ET->getClass() == RSExportType::ExportClassPrimitive) || 1972 (ET->getClass() == RSExportType::ExportClassVector)) { 1973 const RSExportPrimitiveType *EPT = 1974 static_cast<const RSExportPrimitiveType*>(ET); 1975 const char *DataKindName = GetElementDataKindName(EPT->getKind()); 1976 const char *DataTypeName = GetElementDataTypeName(EPT->getType()); 1977 int Size = (ET->getClass() == RSExportType::ExportClassVector) ? 1978 static_cast<const RSExportVectorType*>(ET)->getNumElement() : 1979 1; 1980 1981 switch (EPT->getKind()) { 1982 case RSExportPrimitiveType::DataKindPixelL: 1983 case RSExportPrimitiveType::DataKindPixelA: 1984 case RSExportPrimitiveType::DataKindPixelLA: 1985 case RSExportPrimitiveType::DataKindPixelRGB: 1986 case RSExportPrimitiveType::DataKindPixelRGBA: { 1987 // Element.createPixel() 1988 EB_ADD("Element.createPixel(" << RenderScriptVar << ", " 1989 << DataTypeName << ", " 1990 << DataKindName << ")"); 1991 break; 1992 } 1993 case RSExportPrimitiveType::DataKindUser: 1994 default: { 1995 if (EPT->getClass() == RSExportType::ExportClassPrimitive) { 1996 // Element.createUser() 1997 EB_ADD("Element.createUser(" << RenderScriptVar << ", " 1998 << DataTypeName << ")"); 1999 } else { 2000 slangAssert((ET->getClass() == RSExportType::ExportClassVector) && 2001 "Unexpected type."); 2002 EB_ADD("Element.createVector(" << RenderScriptVar << ", " 2003 << DataTypeName << ", " 2004 << Size << ")"); 2005 } 2006 break; 2007 } 2008 } 2009 #ifndef NDEBUG 2010 } else if (ET->getClass() == RSExportType::ExportClassPointer) { 2011 // Pointer type variable should be resolved in 2012 // GetBuiltinElementConstruct() 2013 slangAssert(false && "??"); 2014 } else if (ET->getClass() == RSExportType::ExportClassMatrix) { 2015 // Matrix type variable should be resolved 2016 // in GetBuiltinElementConstruct() 2017 slangAssert(false && "??"); 2018 #endif 2019 } else if (ET->getClass() == RSExportType::ExportClassConstantArray) { 2020 const RSExportConstantArrayType *ECAT = 2021 static_cast<const RSExportConstantArrayType *>(ET); 2022 2023 const RSExportType *ElementType = ECAT->getElementType(); 2024 if (ElementType->getClass() != RSExportType::ExportClassRecord) { 2025 genAddElementToElementBuilder(C, 2026 ECAT->getElementType(), 2027 VarName, 2028 ElementBuilderName, 2029 RenderScriptVar, 2030 ECAT->getSize()); 2031 } else { 2032 std::string NewElementBuilderName(ElementBuilderName); 2033 NewElementBuilderName.append(1, '_'); 2034 2035 genBuildElement(C, 2036 NewElementBuilderName.c_str(), 2037 static_cast<const RSExportRecordType*>(ElementType), 2038 RenderScriptVar, 2039 /* IsInline = */true); 2040 ArraySize = ECAT->getSize(); 2041 EB_ADD(NewElementBuilderName << ".create()"); 2042 } 2043 } else if (ET->getClass() == RSExportType::ExportClassRecord) { 2044 // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType. 2045 // 2046 // TODO(zonr): Generalize these two function such that there's no 2047 // duplicated codes. 2048 const RSExportRecordType *ERT = 2049 static_cast<const RSExportRecordType*>(ET); 2050 int Pos = 0; // relative pos from now on 2051 2052 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), 2053 E = ERT->fields_end(); 2054 I != E; 2055 I++) { 2056 const RSExportRecordType::Field *F = *I; 2057 std::string FieldName; 2058 int FieldOffset = F->getOffsetInParent(); 2059 int FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType()); 2060 int FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType()); 2061 2062 if (!VarName.empty()) 2063 FieldName = VarName + "." + F->getName(); 2064 else 2065 FieldName = F->getName(); 2066 2067 // Alignment 2068 genAddPaddingToElementBuiler(C, 2069 (FieldOffset - Pos), 2070 ElementBuilderName, 2071 RenderScriptVar); 2072 2073 // eb.add(...) 2074 C.addFieldIndexMapping(F); 2075 if (F->getType()->getClass() != RSExportType::ExportClassRecord) { 2076 genAddElementToElementBuilder(C, 2077 F->getType(), 2078 FieldName, 2079 ElementBuilderName, 2080 RenderScriptVar, 2081 0); 2082 } else { 2083 std::string NewElementBuilderName(ElementBuilderName); 2084 NewElementBuilderName.append(1, '_'); 2085 2086 genBuildElement(C, 2087 NewElementBuilderName.c_str(), 2088 static_cast<const RSExportRecordType*>(F->getType()), 2089 RenderScriptVar, 2090 /* IsInline = */true); 2091 2092 const std::string &VarName = FieldName; // Hack for EB_ADD macro 2093 EB_ADD(NewElementBuilderName << ".create()"); 2094 } 2095 2096 // There is padding within the field type 2097 genAddPaddingToElementBuiler(C, 2098 (FieldAllocSize - FieldStoreSize), 2099 ElementBuilderName, 2100 RenderScriptVar); 2101 2102 Pos = FieldOffset + FieldAllocSize; 2103 } 2104 2105 // There maybe some padding after the struct 2106 size_t RecordAllocSize = RSExportType::GetTypeAllocSize(ERT); 2107 2108 genAddPaddingToElementBuiler(C, 2109 RecordAllocSize - Pos, 2110 ElementBuilderName, 2111 RenderScriptVar); 2112 } else { 2113 slangAssert(false && "Unknown class of type"); 2114 } 2115 } 2116 } 2117 2118 void RSReflection::genAddPaddingToElementBuiler(Context &C, 2119 int PaddingSize, 2120 const char *ElementBuilderName, 2121 const char *RenderScriptVar) { 2122 unsigned ArraySize = 0; // Hack the EB_ADD macro 2123 while (PaddingSize > 0) { 2124 const std::string &VarName = C.createPaddingField(); 2125 if (PaddingSize >= 4) { 2126 EB_ADD("Element.U32(" << RenderScriptVar << ")"); 2127 PaddingSize -= 4; 2128 } else if (PaddingSize >= 2) { 2129 EB_ADD("Element.U16(" << RenderScriptVar << ")"); 2130 PaddingSize -= 2; 2131 } else if (PaddingSize >= 1) { 2132 EB_ADD("Element.U8(" << RenderScriptVar << ")"); 2133 PaddingSize -= 1; 2134 } 2135 } 2136 return; 2137 } 2138 2139 #undef EB_ADD 2140 /******** Methods to create Element in Java of given record type /end ********/ 2141 2142 bool RSReflection::reflect(const std::string &OutputPathBase, 2143 const std::string &OutputPackageName, 2144 const std::string &InputFileName, 2145 const std::string &OutputBCFileName) { 2146 Context *C = NULL; 2147 std::string ResourceId = ""; 2148 2149 if (!GetClassNameFromFileName(OutputBCFileName, ResourceId)) 2150 return false; 2151 2152 if (ResourceId.empty()) 2153 ResourceId = "<Resource ID>"; 2154 2155 if (OutputPackageName.empty() || OutputPackageName == "-") 2156 C = new Context(OutputPathBase, InputFileName, "<Package Name>", 2157 ResourceId, true); 2158 else 2159 C = new Context(OutputPathBase, InputFileName, OutputPackageName, 2160 ResourceId, false); 2161 2162 if (C != NULL) { 2163 std::string ErrorMsg, ScriptClassName; 2164 // class ScriptC_<ScriptName> 2165 if (!GetClassNameFromFileName(InputFileName, ScriptClassName)) 2166 return false; 2167 2168 if (ScriptClassName.empty()) 2169 ScriptClassName = "<Input Script Name>"; 2170 2171 ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX); 2172 2173 if (mRSContext->getLicenseNote() != NULL) { 2174 C->setLicenseNote(*(mRSContext->getLicenseNote())); 2175 } 2176 2177 if (!genScriptClass(*C, ScriptClassName, ErrorMsg)) { 2178 std::cerr << "Failed to generate class " << ScriptClassName << " (" 2179 << ErrorMsg << ")" << std::endl; 2180 return false; 2181 } 2182 2183 mGeneratedFileNames->push_back(ScriptClassName); 2184 2185 // class ScriptField_<TypeName> 2186 for (RSContext::const_export_type_iterator TI = 2187 mRSContext->export_types_begin(), 2188 TE = mRSContext->export_types_end(); 2189 TI != TE; 2190 TI++) { 2191 const RSExportType *ET = TI->getValue(); 2192 2193 if (ET->getClass() == RSExportType::ExportClassRecord) { 2194 const RSExportRecordType *ERT = 2195 static_cast<const RSExportRecordType*>(ET); 2196 2197 if (!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) { 2198 std::cerr << "Failed to generate type class for struct '" 2199 << ERT->getName() << "' (" << ErrorMsg << ")" << std::endl; 2200 return false; 2201 } 2202 } 2203 } 2204 } 2205 2206 return true; 2207 } 2208 2209 /************************** RSReflection::Context **************************/ 2210 const char *const RSReflection::Context::ApacheLicenseNote = 2211 "/*\n" 2212 " * Copyright (C) 2011 The Android Open Source Project\n" 2213 " *\n" 2214 " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" 2215 " * you may not use this file except in compliance with the License.\n" 2216 " * You may obtain a copy of the License at\n" 2217 " *\n" 2218 " * http://www.apache.org/licenses/LICENSE-2.0\n" 2219 " *\n" 2220 " * Unless required by applicable law or agreed to in writing, software\n" 2221 " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" 2222 " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or " 2223 "implied.\n" 2224 " * See the License for the specific language governing permissions and\n" 2225 " * limitations under the License.\n" 2226 " */\n" 2227 "\n"; 2228 2229 const char *const RSReflection::Context::Import[] = { 2230 // Renderscript java class 2231 "android.renderscript.*", 2232 // Import R 2233 "android.content.res.Resources", 2234 // Import for debugging 2235 // "android.util.Log", 2236 }; 2237 2238 bool RSReflection::Context::openClassFile(const std::string &ClassName, 2239 std::string &ErrorMsg) { 2240 if (!mUseStdout) { 2241 mOF.clear(); 2242 std::string Path = 2243 RSSlangReflectUtils::ComputePackagedPath(mOutputPathBase.c_str(), 2244 mPackageName.c_str()); 2245 2246 if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg)) 2247 return false; 2248 2249 std::string ClassFile = Path + OS_PATH_SEPARATOR_STR + ClassName + ".java"; 2250 2251 mOF.open(ClassFile.c_str()); 2252 if (!mOF.good()) { 2253 ErrorMsg = "failed to open file '" + ClassFile + "' for write"; 2254 return false; 2255 } 2256 } 2257 return true; 2258 } 2259 2260 const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) { 2261 switch (AM) { 2262 case AM_Public: return "public"; break; 2263 case AM_Protected: return "protected"; break; 2264 case AM_Private: return "private"; break; 2265 case AM_PublicSynchronized: return "public synchronized"; break; 2266 default: return ""; break; 2267 } 2268 } 2269 2270 bool RSReflection::Context::startClass(AccessModifier AM, 2271 bool IsStatic, 2272 const std::string &ClassName, 2273 const char *SuperClassName, 2274 std::string &ErrorMsg) { 2275 if (mVerbose) 2276 std::cout << "Generating " << ClassName << ".java ..." << std::endl; 2277 2278 // Open file for class 2279 if (!openClassFile(ClassName, ErrorMsg)) 2280 return false; 2281 2282 // License 2283 out() << mLicenseNote; 2284 2285 // Notice of generated file 2286 out() << "/*" << std::endl; 2287 out() << " * This file is auto-generated. DO NOT MODIFY!" << std::endl; 2288 out() << " * The source Renderscript file: " << mInputRSFile << std::endl; 2289 out() << " */" << std::endl; 2290 2291 // Package 2292 if (!mPackageName.empty()) 2293 out() << "package " << mPackageName << ";" << std::endl; 2294 out() << std::endl; 2295 2296 // Imports 2297 for (unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++) 2298 out() << "import " << Import[i] << ";" << std::endl; 2299 out() << std::endl; 2300 2301 // All reflected classes should be annotated as hidden, so that they won't 2302 // be exposed in SDK. 2303 out() << "/**" << std::endl; 2304 out() << " * @hide" << std::endl; 2305 out() << " */" << std::endl; 2306 2307 out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " 2308 << ClassName; 2309 if (SuperClassName != NULL) 2310 out() << " extends " << SuperClassName; 2311 2312 startBlock(); 2313 2314 mClassName = ClassName; 2315 2316 return true; 2317 } 2318 2319 void RSReflection::Context::endClass() { 2320 endBlock(); 2321 if (!mUseStdout) 2322 mOF.close(); 2323 clear(); 2324 return; 2325 } 2326 2327 void RSReflection::Context::startBlock(bool ShouldIndent) { 2328 if (ShouldIndent) 2329 indent() << "{" << std::endl; 2330 else 2331 out() << " {" << std::endl; 2332 incIndentLevel(); 2333 return; 2334 } 2335 2336 void RSReflection::Context::endBlock() { 2337 decIndentLevel(); 2338 indent() << "}" << std::endl << std::endl; 2339 return; 2340 } 2341 2342 void RSReflection::Context::startTypeClass(const std::string &ClassName) { 2343 indent() << "public static class " << ClassName; 2344 startBlock(); 2345 return; 2346 } 2347 2348 void RSReflection::Context::endTypeClass() { 2349 endBlock(); 2350 return; 2351 } 2352 2353 void RSReflection::Context::startFunction(AccessModifier AM, 2354 bool IsStatic, 2355 const char *ReturnType, 2356 const std::string &FunctionName, 2357 int Argc, ...) { 2358 ArgTy Args; 2359 va_list vl; 2360 va_start(vl, Argc); 2361 2362 for (int i = 0; i < Argc; i++) { 2363 const char *ArgType = va_arg(vl, const char*); 2364 const char *ArgName = va_arg(vl, const char*); 2365 2366 Args.push_back(std::make_pair(ArgType, ArgName)); 2367 } 2368 va_end(vl); 2369 2370 startFunction(AM, IsStatic, ReturnType, FunctionName, Args); 2371 2372 return; 2373 } 2374 2375 void RSReflection::Context::startFunction(AccessModifier AM, 2376 bool IsStatic, 2377 const char *ReturnType, 2378 const std::string &FunctionName, 2379 const ArgTy &Args) { 2380 indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") 2381 << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "("; 2382 2383 bool FirstArg = true; 2384 for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); 2385 I != E; 2386 I++) { 2387 if (!FirstArg) 2388 out() << ", "; 2389 else 2390 FirstArg = false; 2391 2392 out() << I->first << " " << I->second; 2393 } 2394 2395 out() << ")"; 2396 startBlock(); 2397 2398 return; 2399 } 2400 2401 void RSReflection::Context::endFunction() { 2402 endBlock(); 2403 return; 2404 } 2405 2406 } // namespace slang 2407