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