1 /* 2 * Copyright 2010-2012, 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_export_type.h" 18 19 #include <list> 20 #include <vector> 21 22 #include "clang/AST/RecordLayout.h" 23 24 #include "llvm/ADT/StringExtras.h" 25 26 #include "llvm/DerivedTypes.h" 27 28 #include "llvm/Target/TargetData.h" 29 30 #include "llvm/Type.h" 31 32 #include "slang_assert.h" 33 #include "slang_rs_context.h" 34 #include "slang_rs_export_element.h" 35 #include "slang_rs_type_spec.h" 36 #include "slang_version.h" 37 38 #define CHECK_PARENT_EQUALITY(ParentClass, E) \ 39 if (!ParentClass::equals(E)) \ 40 return false; 41 42 namespace slang { 43 44 namespace { 45 46 static RSReflectionType gReflectionTypes[] = { 47 {"FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false}, 48 {"FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false}, 49 {"FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false}, 50 {"SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false}, 51 {"SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false}, 52 {"SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false}, 53 {"SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false}, 54 {"UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true}, 55 {"UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true}, 56 {"UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true}, 57 {"UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false}, 58 59 {"BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false}, 60 61 {"UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false}, 62 {"UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false}, 63 {"UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false}, 64 65 {"MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false}, 66 {"MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false}, 67 {"MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false}, 68 69 {"RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false}, 70 {"RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false}, 71 {"RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false}, 72 {"RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false}, 73 {"RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false}, 74 {"RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false}, 75 {"RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false}, 76 {"RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false}, 77 {"RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false}, 78 {"RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false}, 79 {"RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false}, 80 {"RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false} 81 }; 82 83 static const clang::Type *TypeExportableHelper( 84 const clang::Type *T, 85 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 86 clang::DiagnosticsEngine *DiagEngine, 87 const clang::VarDecl *VD, 88 const clang::RecordDecl *TopLevelRecord); 89 90 static void ReportTypeError(clang::DiagnosticsEngine *DiagEngine, 91 const clang::VarDecl *VD, 92 const clang::RecordDecl *TopLevelRecord, 93 const char *Message, 94 unsigned int TargetAPI = 0) { 95 if (!DiagEngine) { 96 return; 97 } 98 99 const clang::SourceManager &SM = DiagEngine->getSourceManager(); 100 101 // Attempt to use the type declaration first (if we have one). 102 // Fall back to the variable definition, if we are looking at something 103 // like an array declaration that can't be exported. 104 if (TopLevelRecord) { 105 DiagEngine->Report( 106 clang::FullSourceLoc(TopLevelRecord->getLocation(), SM), 107 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message)) 108 << TopLevelRecord->getName() << TargetAPI; 109 } else if (VD) { 110 DiagEngine->Report( 111 clang::FullSourceLoc(VD->getLocation(), SM), 112 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message)) 113 << VD->getName() << TargetAPI; 114 } else { 115 slangAssert(false && "Variables should be validated before exporting"); 116 } 117 } 118 119 static const clang::Type *ConstantArrayTypeExportableHelper( 120 const clang::ConstantArrayType *CAT, 121 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 122 clang::DiagnosticsEngine *DiagEngine, 123 const clang::VarDecl *VD, 124 const clang::RecordDecl *TopLevelRecord) { 125 // Check element type 126 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 127 if (ElementType->isArrayType()) { 128 ReportTypeError(DiagEngine, VD, TopLevelRecord, 129 "multidimensional arrays cannot be exported: '%0'"); 130 return NULL; 131 } else if (ElementType->isExtVectorType()) { 132 const clang::ExtVectorType *EVT = 133 static_cast<const clang::ExtVectorType*>(ElementType); 134 unsigned numElements = EVT->getNumElements(); 135 136 const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 137 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) { 138 ReportTypeError(DiagEngine, VD, TopLevelRecord, 139 "vectors of non-primitive types cannot be exported: '%0'"); 140 return NULL; 141 } 142 143 if (numElements == 3 && CAT->getSize() != 1) { 144 ReportTypeError(DiagEngine, VD, TopLevelRecord, 145 "arrays of width 3 vector types cannot be exported: '%0'"); 146 return NULL; 147 } 148 } 149 150 if (TypeExportableHelper(ElementType, SPS, DiagEngine, VD, 151 TopLevelRecord) == NULL) { 152 return NULL; 153 } else { 154 return CAT; 155 } 156 } 157 158 static const clang::Type *TypeExportableHelper( 159 clang::Type const *T, 160 llvm::SmallPtrSet<clang::Type const *, 8> &SPS, 161 clang::DiagnosticsEngine *DiagEngine, 162 clang::VarDecl const *VD, 163 clang::RecordDecl const *TopLevelRecord) { 164 // Normalize first 165 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 166 return NULL; 167 168 if (SPS.count(T)) 169 return T; 170 171 switch (T->getTypeClass()) { 172 case clang::Type::Builtin: { 173 const clang::BuiltinType *BT = 174 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 175 176 switch (BT->getKind()) { 177 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 178 case builtin_type: 179 #include "RSClangBuiltinEnums.inc" 180 return T; 181 default: { 182 return NULL; 183 } 184 } 185 } 186 case clang::Type::Record: { 187 if (RSExportPrimitiveType::GetRSSpecificType(T) != 188 RSExportPrimitiveType::DataTypeUnknown) { 189 return T; // RS object type, no further checks are needed 190 } 191 192 // Check internal struct 193 if (T->isUnionType()) { 194 ReportTypeError(DiagEngine, VD, T->getAsUnionType()->getDecl(), 195 "unions cannot be exported: '%0'"); 196 return NULL; 197 } else if (!T->isStructureType()) { 198 slangAssert(false && "Unknown type cannot be exported"); 199 return NULL; 200 } 201 202 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 203 if (RD != NULL) { 204 RD = RD->getDefinition(); 205 if (RD == NULL) { 206 ReportTypeError(DiagEngine, NULL, T->getAsStructureType()->getDecl(), 207 "struct is not defined in this module"); 208 return NULL; 209 } 210 } 211 212 if (!TopLevelRecord) { 213 TopLevelRecord = RD; 214 } 215 if (RD->getName().empty()) { 216 ReportTypeError(DiagEngine, NULL, RD, 217 "anonymous structures cannot be exported"); 218 return NULL; 219 } 220 221 // Fast check 222 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 223 return NULL; 224 225 // Insert myself into checking set 226 SPS.insert(T); 227 228 // Check all element 229 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 230 FE = RD->field_end(); 231 FI != FE; 232 FI++) { 233 const clang::FieldDecl *FD = *FI; 234 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 235 FT = GET_CANONICAL_TYPE(FT); 236 237 if (!TypeExportableHelper(FT, SPS, DiagEngine, VD, TopLevelRecord)) { 238 return NULL; 239 } 240 241 // We don't support bit fields yet 242 // 243 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32 244 if (FD->isBitField()) { 245 if (DiagEngine) { 246 DiagEngine->Report( 247 clang::FullSourceLoc(FD->getLocation(), 248 DiagEngine->getSourceManager()), 249 DiagEngine->getCustomDiagID( 250 clang::DiagnosticsEngine::Error, 251 "bit fields are not able to be exported: '%0.%1'")) 252 << RD->getName() 253 << FD->getName(); 254 } 255 return NULL; 256 } 257 } 258 259 return T; 260 } 261 case clang::Type::Pointer: { 262 if (TopLevelRecord) { 263 ReportTypeError(DiagEngine, VD, TopLevelRecord, 264 "structures containing pointers cannot be exported: '%0'"); 265 return NULL; 266 } 267 268 const clang::PointerType *PT = 269 UNSAFE_CAST_TYPE(const clang::PointerType, T); 270 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 271 272 if (PointeeType->getTypeClass() == clang::Type::Pointer) { 273 ReportTypeError(DiagEngine, VD, TopLevelRecord, 274 "multiple levels of pointers cannot be exported: '%0'"); 275 return NULL; 276 } 277 // We don't support pointer with array-type pointee or unsupported pointee 278 // type 279 if (PointeeType->isArrayType() || 280 (TypeExportableHelper(PointeeType, SPS, DiagEngine, VD, 281 TopLevelRecord) == NULL)) 282 return NULL; 283 else 284 return T; 285 } 286 case clang::Type::ExtVector: { 287 const clang::ExtVectorType *EVT = 288 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 289 // Only vector with size 2, 3 and 4 are supported. 290 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4) 291 return NULL; 292 293 // Check base element type 294 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 295 296 if ((ElementType->getTypeClass() != clang::Type::Builtin) || 297 (TypeExportableHelper(ElementType, SPS, DiagEngine, VD, 298 TopLevelRecord) == NULL)) 299 return NULL; 300 else 301 return T; 302 } 303 case clang::Type::ConstantArray: { 304 const clang::ConstantArrayType *CAT = 305 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 306 307 return ConstantArrayTypeExportableHelper(CAT, SPS, DiagEngine, VD, 308 TopLevelRecord); 309 } 310 default: { 311 return NULL; 312 } 313 } 314 } 315 316 // Return the type that can be used to create RSExportType, will always return 317 // the canonical type 318 // If the Type T is not exportable, this function returns NULL. DiagEngine is 319 // used to generate proper Clang diagnostic messages when a 320 // non-exportable type is detected. TopLevelRecord is used to capture the 321 // highest struct (in the case of a nested hierarchy) for detecting other 322 // types that cannot be exported (mostly pointers within a struct). 323 static const clang::Type *TypeExportable(const clang::Type *T, 324 clang::DiagnosticsEngine *DiagEngine, 325 const clang::VarDecl *VD) { 326 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 327 llvm::SmallPtrSet<const clang::Type*, 8>(); 328 329 return TypeExportableHelper(T, SPS, DiagEngine, VD, NULL); 330 } 331 332 static bool ValidateRSObjectInVarDecl(clang::VarDecl *VD, 333 bool InCompositeType, 334 unsigned int TargetAPI) { 335 if (TargetAPI < SLANG_JB_TARGET_API) { 336 // Only if we are already in a composite type (like an array or structure). 337 if (InCompositeType) { 338 // Only if we are actually exported (i.e. non-static). 339 if (VD->getLinkage() == clang::ExternalLinkage) { 340 // Only if we are not a pointer to an object. 341 const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr()); 342 if (T->getTypeClass() != clang::Type::Pointer) { 343 clang::ASTContext &C = VD->getASTContext(); 344 ReportTypeError(&C.getDiagnostics(), VD, NULL, 345 "arrays/structures containing RS object types " 346 "cannot be exported in target API < %1: '%0'", 347 SLANG_JB_TARGET_API); 348 return false; 349 } 350 } 351 } 352 } 353 354 return true; 355 } 356 357 // Helper function for ValidateVarDecl(). We do a recursive descent on the 358 // type hierarchy to ensure that we can properly export/handle the 359 // declaration. 360 // \return true if the variable declaration is valid, 361 // false if it is invalid (along with proper diagnostics). 362 // 363 // VD - top-level variable declaration that we are validating. 364 // T - sub-type of VD's type that we are validating. 365 // SPS - set of types we have already seen/validated. 366 // InCompositeType - true if we are within an outer composite type. 367 // UnionDecl - set if we are in a sub-type of a union. 368 // TargetAPI - target SDK API level. 369 static bool ValidateVarDeclHelper( 370 clang::VarDecl *VD, 371 const clang::Type *&T, 372 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 373 bool InCompositeType, 374 clang::RecordDecl *UnionDecl, 375 unsigned int TargetAPI) { 376 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 377 return true; 378 379 if (SPS.count(T)) 380 return true; 381 382 switch (T->getTypeClass()) { 383 case clang::Type::Record: { 384 if (RSExportPrimitiveType::IsRSObjectType(T)) { 385 if (!ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) { 386 return false; 387 } 388 } 389 390 if (RSExportPrimitiveType::GetRSSpecificType(T) != 391 RSExportPrimitiveType::DataTypeUnknown) { 392 if (!UnionDecl) { 393 return true; 394 } else if (RSExportPrimitiveType::IsRSObjectType(T)) { 395 clang::ASTContext &C = VD->getASTContext(); 396 ReportTypeError(&C.getDiagnostics(), VD, UnionDecl, 397 "unions containing RS object types are not allowed"); 398 return false; 399 } 400 } 401 402 clang::RecordDecl *RD = NULL; 403 404 // Check internal struct 405 if (T->isUnionType()) { 406 RD = T->getAsUnionType()->getDecl(); 407 UnionDecl = RD; 408 } else if (T->isStructureType()) { 409 RD = T->getAsStructureType()->getDecl(); 410 } else { 411 slangAssert(false && "Unknown type cannot be exported"); 412 return false; 413 } 414 415 if (RD != NULL) { 416 RD = RD->getDefinition(); 417 if (RD == NULL) { 418 // FIXME 419 return true; 420 } 421 } 422 423 // Fast check 424 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 425 return false; 426 427 // Insert myself into checking set 428 SPS.insert(T); 429 430 // Check all elements 431 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 432 FE = RD->field_end(); 433 FI != FE; 434 FI++) { 435 const clang::FieldDecl *FD = *FI; 436 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 437 FT = GET_CANONICAL_TYPE(FT); 438 439 if (!ValidateVarDeclHelper(VD, FT, SPS, true, UnionDecl, TargetAPI)) { 440 return false; 441 } 442 } 443 444 return true; 445 } 446 447 case clang::Type::Builtin: { 448 break; 449 } 450 451 case clang::Type::Pointer: { 452 const clang::PointerType *PT = 453 UNSAFE_CAST_TYPE(const clang::PointerType, T); 454 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 455 456 return ValidateVarDeclHelper(VD, PointeeType, SPS, InCompositeType, 457 UnionDecl, TargetAPI); 458 } 459 460 case clang::Type::ExtVector: { 461 const clang::ExtVectorType *EVT = 462 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 463 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 464 return ValidateVarDeclHelper(VD, ElementType, SPS, true, UnionDecl, 465 TargetAPI); 466 } 467 468 case clang::Type::ConstantArray: { 469 const clang::ConstantArrayType *CAT = 470 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 471 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 472 return ValidateVarDeclHelper(VD, ElementType, SPS, true, UnionDecl, 473 TargetAPI); 474 } 475 476 default: { 477 break; 478 } 479 } 480 481 return true; 482 } 483 484 } // namespace 485 486 /****************************** RSExportType ******************************/ 487 bool RSExportType::NormalizeType(const clang::Type *&T, 488 llvm::StringRef &TypeName, 489 clang::DiagnosticsEngine *DiagEngine, 490 const clang::VarDecl *VD) { 491 if ((T = TypeExportable(T, DiagEngine, VD)) == NULL) { 492 return false; 493 } 494 // Get type name 495 TypeName = RSExportType::GetTypeName(T); 496 if (TypeName.empty()) { 497 if (DiagEngine) { 498 if (VD) { 499 DiagEngine->Report( 500 clang::FullSourceLoc(VD->getLocation(), 501 DiagEngine->getSourceManager()), 502 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 503 "anonymous types cannot be exported")); 504 } else { 505 DiagEngine->Report( 506 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 507 "anonymous types cannot be exported")); 508 } 509 } 510 return false; 511 } 512 513 return true; 514 } 515 516 bool RSExportType::ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI) { 517 const clang::Type *T = VD->getType().getTypePtr(); 518 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 519 llvm::SmallPtrSet<const clang::Type*, 8>(); 520 521 return ValidateVarDeclHelper(VD, T, SPS, false, NULL, TargetAPI); 522 } 523 524 const clang::Type 525 *RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 526 if (DD) { 527 clang::QualType T; 528 if (DD->getTypeSourceInfo()) 529 T = DD->getTypeSourceInfo()->getType(); 530 else 531 T = DD->getType(); 532 533 if (T.isNull()) 534 return NULL; 535 else 536 return T.getTypePtr(); 537 } 538 return NULL; 539 } 540 541 llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 542 T = GET_CANONICAL_TYPE(T); 543 if (T == NULL) 544 return llvm::StringRef(); 545 546 switch (T->getTypeClass()) { 547 case clang::Type::Builtin: { 548 const clang::BuiltinType *BT = 549 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 550 551 switch (BT->getKind()) { 552 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 553 case builtin_type: \ 554 return cname; \ 555 break; 556 #include "RSClangBuiltinEnums.inc" 557 default: { 558 slangAssert(false && "Unknown data type of the builtin"); 559 break; 560 } 561 } 562 break; 563 } 564 case clang::Type::Record: { 565 clang::RecordDecl *RD; 566 if (T->isStructureType()) { 567 RD = T->getAsStructureType()->getDecl(); 568 } else { 569 break; 570 } 571 572 llvm::StringRef Name = RD->getName(); 573 if (Name.empty()) { 574 if (RD->getTypedefNameForAnonDecl() != NULL) { 575 Name = RD->getTypedefNameForAnonDecl()->getName(); 576 } 577 578 if (Name.empty()) { 579 // Try to find a name from redeclaration (i.e. typedef) 580 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 581 RE = RD->redecls_end(); 582 RI != RE; 583 RI++) { 584 slangAssert(*RI != NULL && "cannot be NULL object"); 585 586 Name = (*RI)->getName(); 587 if (!Name.empty()) 588 break; 589 } 590 } 591 } 592 return Name; 593 } 594 case clang::Type::Pointer: { 595 // "*" plus pointee name 596 const clang::Type *PT = GET_POINTEE_TYPE(T); 597 llvm::StringRef PointeeName; 598 if (NormalizeType(PT, PointeeName, NULL, NULL)) { 599 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 600 Name[0] = '*'; 601 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 602 Name[PointeeName.size() + 1] = '\0'; 603 return Name; 604 } 605 break; 606 } 607 case clang::Type::ExtVector: { 608 const clang::ExtVectorType *EVT = 609 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 610 return RSExportVectorType::GetTypeName(EVT); 611 break; 612 } 613 case clang::Type::ConstantArray : { 614 // Construct name for a constant array is too complicated. 615 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE; 616 } 617 default: { 618 break; 619 } 620 } 621 622 return llvm::StringRef(); 623 } 624 625 626 RSExportType *RSExportType::Create(RSContext *Context, 627 const clang::Type *T, 628 const llvm::StringRef &TypeName) { 629 // Lookup the context to see whether the type was processed before. 630 // Newly created RSExportType will insert into context 631 // in RSExportType::RSExportType() 632 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 633 634 if (ETI != Context->export_types_end()) 635 return ETI->second; 636 637 RSExportType *ET = NULL; 638 switch (T->getTypeClass()) { 639 case clang::Type::Record: { 640 RSExportPrimitiveType::DataType dt = 641 RSExportPrimitiveType::GetRSSpecificType(TypeName); 642 switch (dt) { 643 case RSExportPrimitiveType::DataTypeUnknown: { 644 // User-defined types 645 ET = RSExportRecordType::Create(Context, 646 T->getAsStructureType(), 647 TypeName); 648 break; 649 } 650 case RSExportPrimitiveType::DataTypeRSMatrix2x2: { 651 // 2 x 2 Matrix type 652 ET = RSExportMatrixType::Create(Context, 653 T->getAsStructureType(), 654 TypeName, 655 2); 656 break; 657 } 658 case RSExportPrimitiveType::DataTypeRSMatrix3x3: { 659 // 3 x 3 Matrix type 660 ET = RSExportMatrixType::Create(Context, 661 T->getAsStructureType(), 662 TypeName, 663 3); 664 break; 665 } 666 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 667 // 4 x 4 Matrix type 668 ET = RSExportMatrixType::Create(Context, 669 T->getAsStructureType(), 670 TypeName, 671 4); 672 break; 673 } 674 default: { 675 // Others are primitive types 676 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 677 break; 678 } 679 } 680 break; 681 } 682 case clang::Type::Builtin: { 683 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 684 break; 685 } 686 case clang::Type::Pointer: { 687 ET = RSExportPointerType::Create(Context, 688 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName); 689 // FIXME: free the name (allocated in RSExportType::GetTypeName) 690 delete [] TypeName.data(); 691 break; 692 } 693 case clang::Type::ExtVector: { 694 ET = RSExportVectorType::Create(Context, 695 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName); 696 break; 697 } 698 case clang::Type::ConstantArray: { 699 ET = RSExportConstantArrayType::Create( 700 Context, 701 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T)); 702 break; 703 } 704 default: { 705 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 706 DiagEngine->Report( 707 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 708 "unknown type cannot be exported: '%0'")) 709 << T->getTypeClassName(); 710 break; 711 } 712 } 713 714 return ET; 715 } 716 717 RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 718 llvm::StringRef TypeName; 719 if (NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)) { 720 return Create(Context, T, TypeName); 721 } else { 722 return NULL; 723 } 724 } 725 726 RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 727 const clang::VarDecl *VD) { 728 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 729 } 730 731 size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 732 return ET->getRSContext()->getTargetData()->getTypeStoreSize( 733 ET->getLLVMType()); 734 } 735 736 size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 737 if (ET->getClass() == RSExportType::ExportClassRecord) 738 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 739 else 740 return ET->getRSContext()->getTargetData()->getTypeAllocSize( 741 ET->getLLVMType()); 742 } 743 744 RSExportType::RSExportType(RSContext *Context, 745 ExportClass Class, 746 const llvm::StringRef &Name) 747 : RSExportable(Context, RSExportable::EX_TYPE), 748 mClass(Class), 749 // Make a copy on Name since memory stored @Name is either allocated in 750 // ASTContext or allocated in GetTypeName which will be destroyed later. 751 mName(Name.data(), Name.size()), 752 mLLVMType(NULL), 753 mSpecType(NULL) { 754 // Don't cache the type whose name start with '<'. Those type failed to 755 // get their name since constructing their name in GetTypeName() requiring 756 // complicated work. 757 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX)) 758 // TODO(zonr): Need to check whether the insertion is successful or not. 759 Context->insertExportType(llvm::StringRef(Name), this); 760 return; 761 } 762 763 bool RSExportType::keep() { 764 if (!RSExportable::keep()) 765 return false; 766 // Invalidate converted LLVM type. 767 mLLVMType = NULL; 768 return true; 769 } 770 771 bool RSExportType::equals(const RSExportable *E) const { 772 CHECK_PARENT_EQUALITY(RSExportable, E); 773 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 774 } 775 776 RSExportType::~RSExportType() { 777 delete mSpecType; 778 } 779 780 /************************** RSExportPrimitiveType **************************/ 781 llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 782 RSExportPrimitiveType::RSSpecificTypeMap; 783 784 llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 785 786 bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 787 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 788 return true; 789 else 790 return false; 791 } 792 793 RSExportPrimitiveType::DataType 794 RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 795 if (TypeName.empty()) 796 return DataTypeUnknown; 797 798 if (RSSpecificTypeMap->empty()) { 799 #define ENUM_RS_MATRIX_TYPE(type, cname, dim) \ 800 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 801 #include "RSMatrixTypeEnums.inc" 802 #define ENUM_RS_OBJECT_TYPE(type, cname) \ 803 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 804 #include "RSObjectTypeEnums.inc" 805 } 806 807 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 808 if (I == RSSpecificTypeMap->end()) 809 return DataTypeUnknown; 810 else 811 return I->getValue(); 812 } 813 814 RSExportPrimitiveType::DataType 815 RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 816 T = GET_CANONICAL_TYPE(T); 817 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 818 return DataTypeUnknown; 819 820 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 821 } 822 823 bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 824 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType)); 825 } 826 827 bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 828 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType)); 829 } 830 831 bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 832 bool RSObjectTypeSeen = false; 833 while (T && T->isArrayType()) { 834 T = T->getArrayElementTypeNoTypeQual(); 835 } 836 837 const clang::RecordType *RT = T->getAsStructureType(); 838 if (!RT) { 839 return false; 840 } 841 const clang::RecordDecl *RD = RT->getDecl(); 842 RD = RD->getDefinition(); 843 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 844 FE = RD->field_end(); 845 FI != FE; 846 FI++) { 847 // We just look through all field declarations to see if we find a 848 // declaration for an RS object type (or an array of one). 849 const clang::FieldDecl *FD = *FI; 850 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 851 while (FT && FT->isArrayType()) { 852 FT = FT->getArrayElementTypeNoTypeQual(); 853 } 854 855 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT); 856 if (IsRSObjectType(DT)) { 857 // RS object types definitely need to be zero-initialized 858 RSObjectTypeSeen = true; 859 } else { 860 switch (DT) { 861 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 862 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 863 case RSExportPrimitiveType::DataTypeRSMatrix4x4: 864 // Matrix types should get zero-initialized as well 865 RSObjectTypeSeen = true; 866 break; 867 default: 868 // Ignore all other primitive types 869 break; 870 } 871 while (FT && FT->isArrayType()) { 872 FT = FT->getArrayElementTypeNoTypeQual(); 873 } 874 if (FT->isStructureType()) { 875 // Recursively handle structs of structs (even though these can't 876 // be exported, it is possible for a user to have them internally). 877 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 878 } 879 } 880 } 881 882 return RSObjectTypeSeen; 883 } 884 885 const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = { 886 #define ENUM_RS_DATA_TYPE(type, cname, bits) \ 887 bits, 888 #include "RSDataTypeEnums.inc" 889 0 // DataTypeMax 890 }; 891 892 size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 893 slangAssert(((EPT->getType() > DataTypeUnknown) && 894 (EPT->getType() < DataTypeMax)) && 895 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 896 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ]; 897 } 898 899 RSExportPrimitiveType::DataType 900 RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 901 if (T == NULL) 902 return DataTypeUnknown; 903 904 switch (T->getTypeClass()) { 905 case clang::Type::Builtin: { 906 const clang::BuiltinType *BT = 907 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 908 switch (BT->getKind()) { 909 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 910 case builtin_type: { \ 911 return DataType ## type; \ 912 } 913 #include "RSClangBuiltinEnums.inc" 914 // The size of type WChar depend on platform so we abandon the support 915 // to them. 916 default: { 917 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 918 DiagEngine->Report( 919 DiagEngine->getCustomDiagID( 920 clang::DiagnosticsEngine::Error, 921 "built-in type cannot be exported: '%0'")) 922 << T->getTypeClassName(); 923 break; 924 } 925 } 926 break; 927 } 928 case clang::Type::Record: { 929 // must be RS object type 930 return RSExportPrimitiveType::GetRSSpecificType(T); 931 } 932 default: { 933 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 934 DiagEngine->Report( 935 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 936 "primitive type cannot be exported: '%0'")) 937 << T->getTypeClassName(); 938 break; 939 } 940 } 941 942 return DataTypeUnknown; 943 } 944 945 RSExportPrimitiveType 946 *RSExportPrimitiveType::Create(RSContext *Context, 947 const clang::Type *T, 948 const llvm::StringRef &TypeName, 949 bool Normalized) { 950 DataType DT = GetDataType(Context, T); 951 952 if ((DT == DataTypeUnknown) || TypeName.empty()) 953 return NULL; 954 else 955 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 956 DT, Normalized); 957 } 958 959 RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 960 const clang::Type *T) { 961 llvm::StringRef TypeName; 962 if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL) 963 && IsPrimitiveType(T)) { 964 return Create(Context, T, TypeName); 965 } else { 966 return NULL; 967 } 968 } 969 970 llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 971 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 972 973 if (isRSObjectType()) { 974 // struct { 975 // int *p; 976 // } __attribute__((packed, aligned(pointer_size))) 977 // 978 // which is 979 // 980 // <{ [1 x i32] }> in LLVM 981 // 982 if (RSObjectLLVMType == NULL) { 983 std::vector<llvm::Type *> Elements; 984 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 985 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 986 } 987 return RSObjectLLVMType; 988 } 989 990 switch (mType) { 991 case DataTypeFloat32: { 992 return llvm::Type::getFloatTy(C); 993 break; 994 } 995 case DataTypeFloat64: { 996 return llvm::Type::getDoubleTy(C); 997 break; 998 } 999 case DataTypeBoolean: { 1000 return llvm::Type::getInt1Ty(C); 1001 break; 1002 } 1003 case DataTypeSigned8: 1004 case DataTypeUnsigned8: { 1005 return llvm::Type::getInt8Ty(C); 1006 break; 1007 } 1008 case DataTypeSigned16: 1009 case DataTypeUnsigned16: 1010 case DataTypeUnsigned565: 1011 case DataTypeUnsigned5551: 1012 case DataTypeUnsigned4444: { 1013 return llvm::Type::getInt16Ty(C); 1014 break; 1015 } 1016 case DataTypeSigned32: 1017 case DataTypeUnsigned32: { 1018 return llvm::Type::getInt32Ty(C); 1019 break; 1020 } 1021 case DataTypeSigned64: 1022 case DataTypeUnsigned64: { 1023 return llvm::Type::getInt64Ty(C); 1024 break; 1025 } 1026 default: { 1027 slangAssert(false && "Unknown data type"); 1028 } 1029 } 1030 1031 return NULL; 1032 } 1033 1034 union RSType *RSExportPrimitiveType::convertToSpecType() const { 1035 llvm::OwningPtr<union RSType> ST(new union RSType); 1036 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive); 1037 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in 1038 // slang_rs_type_spec.h 1039 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType()); 1040 return ST.take(); 1041 } 1042 1043 bool RSExportPrimitiveType::equals(const RSExportable *E) const { 1044 CHECK_PARENT_EQUALITY(RSExportType, E); 1045 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 1046 } 1047 1048 RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) { 1049 if (DT > DataTypeUnknown && DT < DataTypeMax) { 1050 return &gReflectionTypes[DT]; 1051 } else { 1052 return NULL; 1053 } 1054 } 1055 1056 /**************************** RSExportPointerType ****************************/ 1057 1058 RSExportPointerType 1059 *RSExportPointerType::Create(RSContext *Context, 1060 const clang::PointerType *PT, 1061 const llvm::StringRef &TypeName) { 1062 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 1063 const RSExportType *PointeeET; 1064 1065 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 1066 PointeeET = RSExportType::Create(Context, PointeeType); 1067 } else { 1068 // Double or higher dimension of pointer, export as int* 1069 PointeeET = RSExportPrimitiveType::Create(Context, 1070 Context->getASTContext().IntTy.getTypePtr()); 1071 } 1072 1073 if (PointeeET == NULL) { 1074 // Error diagnostic is emitted for corresponding pointee type 1075 return NULL; 1076 } 1077 1078 return new RSExportPointerType(Context, TypeName, PointeeET); 1079 } 1080 1081 llvm::Type *RSExportPointerType::convertToLLVMType() const { 1082 llvm::Type *PointeeType = mPointeeType->getLLVMType(); 1083 return llvm::PointerType::getUnqual(PointeeType); 1084 } 1085 1086 union RSType *RSExportPointerType::convertToSpecType() const { 1087 llvm::OwningPtr<union RSType> ST(new union RSType); 1088 1089 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer); 1090 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType()); 1091 1092 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL) 1093 return ST.take(); 1094 else 1095 return NULL; 1096 } 1097 1098 bool RSExportPointerType::keep() { 1099 if (!RSExportType::keep()) 1100 return false; 1101 const_cast<RSExportType*>(mPointeeType)->keep(); 1102 return true; 1103 } 1104 1105 bool RSExportPointerType::equals(const RSExportable *E) const { 1106 CHECK_PARENT_EQUALITY(RSExportType, E); 1107 return (static_cast<const RSExportPointerType*>(E) 1108 ->getPointeeType()->equals(getPointeeType())); 1109 } 1110 1111 /***************************** RSExportVectorType *****************************/ 1112 llvm::StringRef 1113 RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 1114 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1115 1116 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 1117 return llvm::StringRef(); 1118 1119 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType, 1120 ElementType); 1121 if ((EVT->getNumElements() < 1) || 1122 (EVT->getNumElements() > 4)) 1123 return llvm::StringRef(); 1124 1125 switch (BT->getKind()) { 1126 // Compiler is smart enough to optimize following *big if branches* since 1127 // they all become "constant comparison" after macro expansion 1128 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 1129 case builtin_type: { \ 1130 const char *Name[] = { cname"2", cname"3", cname"4" }; \ 1131 return Name[EVT->getNumElements() - 2]; \ 1132 break; \ 1133 } 1134 #include "RSClangBuiltinEnums.inc" 1135 default: { 1136 return llvm::StringRef(); 1137 } 1138 } 1139 } 1140 1141 RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 1142 const clang::ExtVectorType *EVT, 1143 const llvm::StringRef &TypeName, 1144 bool Normalized) { 1145 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 1146 1147 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1148 RSExportPrimitiveType::DataType DT = 1149 RSExportPrimitiveType::GetDataType(Context, ElementType); 1150 1151 if (DT != RSExportPrimitiveType::DataTypeUnknown) 1152 return new RSExportVectorType(Context, 1153 TypeName, 1154 DT, 1155 Normalized, 1156 EVT->getNumElements()); 1157 else 1158 return NULL; 1159 } 1160 1161 llvm::Type *RSExportVectorType::convertToLLVMType() const { 1162 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 1163 return llvm::VectorType::get(ElementType, getNumElement()); 1164 } 1165 1166 union RSType *RSExportVectorType::convertToSpecType() const { 1167 llvm::OwningPtr<union RSType> ST(new union RSType); 1168 1169 RS_TYPE_SET_CLASS(ST, RS_TC_Vector); 1170 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType()); 1171 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement()); 1172 1173 return ST.take(); 1174 } 1175 1176 bool RSExportVectorType::equals(const RSExportable *E) const { 1177 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 1178 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 1179 == getNumElement()); 1180 } 1181 1182 /***************************** RSExportMatrixType *****************************/ 1183 RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 1184 const clang::RecordType *RT, 1185 const llvm::StringRef &TypeName, 1186 unsigned Dim) { 1187 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 1188 slangAssert((Dim > 1) && "Invalid dimension of matrix"); 1189 1190 // Check whether the struct rs_matrix is in our expected form (but assume it's 1191 // correct if we're not sure whether it's correct or not) 1192 const clang::RecordDecl* RD = RT->getDecl(); 1193 RD = RD->getDefinition(); 1194 if (RD != NULL) { 1195 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 1196 const clang::SourceManager *SM = Context->getSourceManager(); 1197 // Find definition, perform further examination 1198 if (RD->field_empty()) { 1199 DiagEngine->Report( 1200 clang::FullSourceLoc(RD->getLocation(), *SM), 1201 DiagEngine->getCustomDiagID( 1202 clang::DiagnosticsEngine::Error, 1203 "invalid matrix struct: must have 1 field for saving values: '%0'")) 1204 << RD->getName(); 1205 return NULL; 1206 } 1207 1208 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 1209 const clang::FieldDecl *FD = *FIT; 1210 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1211 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 1212 DiagEngine->Report( 1213 clang::FullSourceLoc(RD->getLocation(), *SM), 1214 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1215 "invalid matrix struct: first field should" 1216 " be an array with constant size: '%0'")) 1217 << RD->getName(); 1218 return NULL; 1219 } 1220 const clang::ConstantArrayType *CAT = 1221 static_cast<const clang::ConstantArrayType *>(FT); 1222 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1223 if ((ElementType == NULL) || 1224 (ElementType->getTypeClass() != clang::Type::Builtin) || 1225 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() != 1226 clang::BuiltinType::Float)) { 1227 DiagEngine->Report( 1228 clang::FullSourceLoc(RD->getLocation(), *SM), 1229 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1230 "invalid matrix struct: first field " 1231 "should be a float array: '%0'")) 1232 << RD->getName(); 1233 return NULL; 1234 } 1235 1236 if (CAT->getSize() != Dim * Dim) { 1237 DiagEngine->Report( 1238 clang::FullSourceLoc(RD->getLocation(), *SM), 1239 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1240 "invalid matrix struct: first field " 1241 "should be an array with size %0: '%1'")) 1242 << (Dim * Dim) << (RD->getName()); 1243 return NULL; 1244 } 1245 1246 FIT++; 1247 if (FIT != RD->field_end()) { 1248 DiagEngine->Report( 1249 clang::FullSourceLoc(RD->getLocation(), *SM), 1250 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1251 "invalid matrix struct: must have " 1252 "exactly 1 field: '%0'")) 1253 << RD->getName(); 1254 return NULL; 1255 } 1256 } 1257 1258 return new RSExportMatrixType(Context, TypeName, Dim); 1259 } 1260 1261 llvm::Type *RSExportMatrixType::convertToLLVMType() const { 1262 // Construct LLVM type: 1263 // struct { 1264 // float X[mDim * mDim]; 1265 // } 1266 1267 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1268 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 1269 mDim * mDim); 1270 return llvm::StructType::get(C, X, false); 1271 } 1272 1273 union RSType *RSExportMatrixType::convertToSpecType() const { 1274 llvm::OwningPtr<union RSType> ST(new union RSType); 1275 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix); 1276 switch (getDim()) { 1277 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break; 1278 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break; 1279 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break; 1280 default: slangAssert(false && "Matrix type with unsupported dimension."); 1281 } 1282 return ST.take(); 1283 } 1284 1285 bool RSExportMatrixType::equals(const RSExportable *E) const { 1286 CHECK_PARENT_EQUALITY(RSExportType, E); 1287 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 1288 } 1289 1290 /************************* RSExportConstantArrayType *************************/ 1291 RSExportConstantArrayType 1292 *RSExportConstantArrayType::Create(RSContext *Context, 1293 const clang::ConstantArrayType *CAT) { 1294 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 1295 1296 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large"); 1297 1298 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 1299 slangAssert((Size > 0) && "Constant array should have size greater than 0"); 1300 1301 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1302 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 1303 1304 if (ElementET == NULL) { 1305 return NULL; 1306 } 1307 1308 return new RSExportConstantArrayType(Context, 1309 ElementET, 1310 Size); 1311 } 1312 1313 llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 1314 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 1315 } 1316 1317 union RSType *RSExportConstantArrayType::convertToSpecType() const { 1318 llvm::OwningPtr<union RSType> ST(new union RSType); 1319 1320 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray); 1321 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE( 1322 ST, getElementType()->getSpecType()); 1323 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize()); 1324 1325 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL) 1326 return ST.take(); 1327 else 1328 return NULL; 1329 } 1330 1331 bool RSExportConstantArrayType::keep() { 1332 if (!RSExportType::keep()) 1333 return false; 1334 const_cast<RSExportType*>(mElementType)->keep(); 1335 return true; 1336 } 1337 1338 bool RSExportConstantArrayType::equals(const RSExportable *E) const { 1339 CHECK_PARENT_EQUALITY(RSExportType, E); 1340 const RSExportConstantArrayType *RHS = 1341 static_cast<const RSExportConstantArrayType*>(E); 1342 return ((getSize() == RHS->getSize()) && 1343 (getElementType()->equals(RHS->getElementType()))); 1344 } 1345 1346 /**************************** RSExportRecordType ****************************/ 1347 RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 1348 const clang::RecordType *RT, 1349 const llvm::StringRef &TypeName, 1350 bool mIsArtificial) { 1351 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 1352 1353 const clang::RecordDecl *RD = RT->getDecl(); 1354 slangAssert(RD->isStruct()); 1355 1356 RD = RD->getDefinition(); 1357 if (RD == NULL) { 1358 slangAssert(false && "struct is not defined in this module"); 1359 return NULL; 1360 } 1361 1362 // Struct layout construct by clang. We rely on this for obtaining the 1363 // alloc size of a struct and offset of every field in that struct. 1364 const clang::ASTRecordLayout *RL = 1365 &Context->getASTContext().getASTRecordLayout(RD); 1366 slangAssert((RL != NULL) && 1367 "Failed to retrieve the struct layout from Clang."); 1368 1369 RSExportRecordType *ERT = 1370 new RSExportRecordType(Context, 1371 TypeName, 1372 RD->hasAttr<clang::PackedAttr>(), 1373 mIsArtificial, 1374 RL->getSize().getQuantity()); 1375 unsigned int Index = 0; 1376 1377 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1378 FE = RD->field_end(); 1379 FI != FE; 1380 FI++, Index++) { 1381 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 1382 1383 // FIXME: All fields should be primitive type 1384 slangAssert((*FI)->getKind() == clang::Decl::Field); 1385 clang::FieldDecl *FD = *FI; 1386 1387 if (FD->isBitField()) { 1388 return NULL; 1389 } 1390 1391 // Type 1392 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1393 1394 if (ET != NULL) { 1395 ERT->mFields.push_back( 1396 new Field(ET, FD->getName(), ERT, 1397 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1398 } else { 1399 DiagEngine->Report( 1400 clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()), 1401 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1402 "field type cannot be exported: '%0.%1'")) 1403 << RD->getName() << FD->getName(); 1404 return NULL; 1405 } 1406 } 1407 1408 return ERT; 1409 } 1410 1411 llvm::Type *RSExportRecordType::convertToLLVMType() const { 1412 // Create an opaque type since struct may reference itself recursively. 1413 1414 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to? 1415 std::vector<llvm::Type*> FieldTypes; 1416 1417 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1418 FI != FE; 1419 FI++) { 1420 const Field *F = *FI; 1421 const RSExportType *FET = F->getType(); 1422 1423 FieldTypes.push_back(FET->getLLVMType()); 1424 } 1425 1426 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1427 FieldTypes, 1428 mIsPacked); 1429 if (ST != NULL) { 1430 return ST; 1431 } else { 1432 return NULL; 1433 } 1434 } 1435 1436 union RSType *RSExportRecordType::convertToSpecType() const { 1437 unsigned NumFields = getFields().size(); 1438 unsigned AllocSize = sizeof(union RSType) + 1439 sizeof(struct RSRecordField) * NumFields; 1440 llvm::OwningPtr<union RSType> ST( 1441 reinterpret_cast<union RSType*>(operator new(AllocSize))); 1442 1443 ::memset(ST.get(), 0, AllocSize); 1444 1445 RS_TYPE_SET_CLASS(ST, RS_TC_Record); 1446 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str()); 1447 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields); 1448 1449 setSpecTypeTemporarily(ST.get()); 1450 1451 unsigned FieldIdx = 0; 1452 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1453 FI != FE; 1454 FI++, FieldIdx++) { 1455 const Field *F = *FI; 1456 1457 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str()); 1458 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType()); 1459 } 1460 1461 // TODO(slang): Check whether all fields were created normally. 1462 1463 return ST.take(); 1464 } 1465 1466 bool RSExportRecordType::keep() { 1467 if (!RSExportType::keep()) 1468 return false; 1469 for (std::list<const Field*>::iterator I = mFields.begin(), 1470 E = mFields.end(); 1471 I != E; 1472 I++) { 1473 const_cast<RSExportType*>((*I)->getType())->keep(); 1474 } 1475 return true; 1476 } 1477 1478 bool RSExportRecordType::equals(const RSExportable *E) const { 1479 CHECK_PARENT_EQUALITY(RSExportType, E); 1480 1481 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1482 1483 if (ERT->getFields().size() != getFields().size()) 1484 return false; 1485 1486 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1487 1488 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1489 if (!(*AI)->getType()->equals((*BI)->getType())) 1490 return false; 1491 AI++; 1492 BI++; 1493 } 1494 1495 return true; 1496 } 1497 1498 void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const { 1499 memset(rtd, 0, sizeof(*rtd)); 1500 rtd->vecSize = 1; 1501 1502 switch(getClass()) { 1503 case RSExportType::ExportClassPrimitive: { 1504 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this); 1505 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT); 1506 return; 1507 } 1508 case RSExportType::ExportClassPointer: { 1509 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this); 1510 const RSExportType *PointeeType = EPT->getPointeeType(); 1511 PointeeType->convertToRTD(rtd); 1512 rtd->isPointer = true; 1513 return; 1514 } 1515 case RSExportType::ExportClassVector: { 1516 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this); 1517 rtd->type = EVT->getRSReflectionType(EVT); 1518 rtd->vecSize = EVT->getNumElement(); 1519 return; 1520 } 1521 case RSExportType::ExportClassMatrix: { 1522 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this); 1523 unsigned Dim = EMT->getDim(); 1524 slangAssert((Dim >= 2) && (Dim <= 4)); 1525 rtd->type = &gReflectionTypes[15 + Dim-2]; 1526 return; 1527 } 1528 case RSExportType::ExportClassConstantArray: { 1529 const RSExportConstantArrayType* CAT = 1530 static_cast<const RSExportConstantArrayType*>(this); 1531 CAT->getElementType()->convertToRTD(rtd); 1532 rtd->arraySize = CAT->getSize(); 1533 return; 1534 } 1535 case RSExportType::ExportClassRecord: { 1536 slangAssert(!"RSExportType::ExportClassRecord not implemented"); 1537 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item"; 1538 } 1539 default: { 1540 slangAssert(false && "Unknown class of type"); 1541 } 1542 } 1543 } 1544 1545 1546 } // namespace slang 1547