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