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