slang_rs_export_type.cpp revision 11274a7324b478ec13e1d10a1b81350b34a65ab1
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::NamedDecl *ND, 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 (ND) { 111 DiagEngine->Report( 112 clang::FullSourceLoc(ND->getLocation(), SM), 113 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message)) 114 << ND->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->hasLinkage() && (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 ValidateType(). 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// C - ASTContext (for diagnostics + builtin types). 365// T - sub-type that we are validating. 366// ND - (optional) top-level named declaration that we are validating. 367// SPS - set of types we have already seen/validated. 368// InCompositeType - true if we are within an outer composite type. 369// UnionDecl - set if we are in a sub-type of a union. 370// TargetAPI - target SDK API level. 371// IsFilterscript - whether or not we are compiling for Filterscript 372static bool ValidateTypeHelper( 373 clang::ASTContext &C, 374 const clang::Type *&T, 375 clang::NamedDecl *ND, 376 clang::SourceLocation Loc, 377 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 378 bool InCompositeType, 379 clang::RecordDecl *UnionDecl, 380 unsigned int TargetAPI, 381 bool IsFilterscript) { 382 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 383 return true; 384 385 if (SPS.count(T)) 386 return true; 387 388 switch (T->getTypeClass()) { 389 case clang::Type::Record: { 390 if (RSExportPrimitiveType::IsRSObjectType(T)) { 391 clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL); 392 if (VD && !ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) { 393 return false; 394 } 395 } 396 397 if (RSExportPrimitiveType::GetRSSpecificType(T) != 398 RSExportPrimitiveType::DataTypeUnknown) { 399 if (!UnionDecl) { 400 return true; 401 } else if (RSExportPrimitiveType::IsRSObjectType(T)) { 402 ReportTypeError(&C.getDiagnostics(), NULL, UnionDecl, 403 "unions containing RS object types are not allowed"); 404 return false; 405 } 406 } 407 408 clang::RecordDecl *RD = NULL; 409 410 // Check internal struct 411 if (T->isUnionType()) { 412 RD = T->getAsUnionType()->getDecl(); 413 UnionDecl = RD; 414 } else if (T->isStructureType()) { 415 RD = T->getAsStructureType()->getDecl(); 416 } else { 417 slangAssert(false && "Unknown type cannot be exported"); 418 return false; 419 } 420 421 if (RD != NULL) { 422 RD = RD->getDefinition(); 423 if (RD == NULL) { 424 // FIXME 425 return true; 426 } 427 } 428 429 // Fast check 430 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 431 return false; 432 433 // Insert myself into checking set 434 SPS.insert(T); 435 436 // Check all elements 437 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 438 FE = RD->field_end(); 439 FI != FE; 440 FI++) { 441 const clang::FieldDecl *FD = *FI; 442 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 443 FT = GET_CANONICAL_TYPE(FT); 444 445 if (!ValidateTypeHelper(C, FT, ND, Loc, SPS, true, UnionDecl, 446 TargetAPI, IsFilterscript)) { 447 return false; 448 } 449 } 450 451 return true; 452 } 453 454 case clang::Type::Builtin: { 455 if (IsFilterscript) { 456 clang::QualType QT = T->getCanonicalTypeInternal(); 457 if (QT == C.DoubleTy || 458 QT == C.LongDoubleTy || 459 QT == C.LongTy || 460 QT == C.LongLongTy) { 461 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics(); 462 if (ND) { 463 DiagEngine.Report( 464 clang::FullSourceLoc(Loc, C.getSourceManager()), 465 DiagEngine.getCustomDiagID( 466 clang::DiagnosticsEngine::Error, 467 "Builtin types > 32 bits in size are forbidden in " 468 "Filterscript: '%0'")) << ND->getName(); 469 } else { 470 DiagEngine.Report( 471 clang::FullSourceLoc(Loc, C.getSourceManager()), 472 DiagEngine.getCustomDiagID( 473 clang::DiagnosticsEngine::Error, 474 "Builtin types > 32 bits in size are forbidden in " 475 "Filterscript")); 476 } 477 return false; 478 } 479 } 480 break; 481 } 482 483 case clang::Type::Pointer: { 484 if (IsFilterscript) { 485 if (ND) { 486 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics(); 487 DiagEngine.Report( 488 clang::FullSourceLoc(Loc, C.getSourceManager()), 489 DiagEngine.getCustomDiagID( 490 clang::DiagnosticsEngine::Error, 491 "Pointers are forbidden in Filterscript: '%0'")) << ND->getName(); 492 return false; 493 } else { 494 // TODO(srhines): Find a better way to handle expressions (i.e. no 495 // NamedDecl) involving pointers in FS that should be allowed. 496 // An example would be calls to library functions like 497 // rsMatrixMultiply() that take rs_matrixNxN * types. 498 } 499 } 500 501 const clang::PointerType *PT = 502 UNSAFE_CAST_TYPE(const clang::PointerType, T); 503 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 504 505 return ValidateTypeHelper(C, PointeeType, ND, Loc, SPS, InCompositeType, 506 UnionDecl, TargetAPI, IsFilterscript); 507 } 508 509 case clang::Type::ExtVector: { 510 const clang::ExtVectorType *EVT = 511 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 512 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 513 if (TargetAPI < SLANG_ICS_TARGET_API && 514 InCompositeType && 515 EVT->getNumElements() == 3) { 516 ReportTypeError(&C.getDiagnostics(), ND, NULL, 517 "structs containing vectors of dimension 3 cannot " 518 "be exported at this API level: '%0'"); 519 return false; 520 } 521 return ValidateTypeHelper(C, ElementType, ND, Loc, SPS, true, UnionDecl, 522 TargetAPI, IsFilterscript); 523 } 524 525 case clang::Type::ConstantArray: { 526 const clang::ConstantArrayType *CAT = 527 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 528 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 529 return ValidateTypeHelper(C, ElementType, ND, Loc, SPS, true, UnionDecl, 530 TargetAPI, IsFilterscript); 531 } 532 533 default: { 534 break; 535 } 536 } 537 538 return true; 539} 540 541} // namespace 542 543/****************************** RSExportType ******************************/ 544bool RSExportType::NormalizeType(const clang::Type *&T, 545 llvm::StringRef &TypeName, 546 clang::DiagnosticsEngine *DiagEngine, 547 const clang::VarDecl *VD) { 548 if ((T = TypeExportable(T, DiagEngine, VD)) == NULL) { 549 return false; 550 } 551 // Get type name 552 TypeName = RSExportType::GetTypeName(T); 553 if (TypeName.empty()) { 554 if (DiagEngine) { 555 if (VD) { 556 DiagEngine->Report( 557 clang::FullSourceLoc(VD->getLocation(), 558 DiagEngine->getSourceManager()), 559 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 560 "anonymous types cannot be exported")); 561 } else { 562 DiagEngine->Report( 563 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 564 "anonymous types cannot be exported")); 565 } 566 } 567 return false; 568 } 569 570 return true; 571} 572 573bool RSExportType::ValidateType(clang::ASTContext &C, clang::QualType QT, 574 clang::NamedDecl *ND, clang::SourceLocation Loc, unsigned int TargetAPI, 575 bool IsFilterscript) { 576 const clang::Type *T = QT.getTypePtr(); 577 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 578 llvm::SmallPtrSet<const clang::Type*, 8>(); 579 580 return ValidateTypeHelper(C, T, ND, Loc, SPS, false, NULL, TargetAPI, 581 IsFilterscript); 582 return true; 583} 584 585bool RSExportType::ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI, 586 bool IsFilterscript) { 587 return ValidateType(VD->getASTContext(), VD->getType(), VD, 588 VD->getLocation(), TargetAPI, IsFilterscript); 589} 590 591const clang::Type 592*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 593 if (DD) { 594 clang::QualType T; 595 if (DD->getTypeSourceInfo()) 596 T = DD->getTypeSourceInfo()->getType(); 597 else 598 T = DD->getType(); 599 600 if (T.isNull()) 601 return NULL; 602 else 603 return T.getTypePtr(); 604 } 605 return NULL; 606} 607 608llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 609 T = GET_CANONICAL_TYPE(T); 610 if (T == NULL) 611 return llvm::StringRef(); 612 613 switch (T->getTypeClass()) { 614 case clang::Type::Builtin: { 615 const clang::BuiltinType *BT = 616 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 617 618 switch (BT->getKind()) { 619#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 620 case builtin_type: \ 621 return cname; \ 622 break; 623#include "RSClangBuiltinEnums.inc" 624 default: { 625 slangAssert(false && "Unknown data type of the builtin"); 626 break; 627 } 628 } 629 break; 630 } 631 case clang::Type::Record: { 632 clang::RecordDecl *RD; 633 if (T->isStructureType()) { 634 RD = T->getAsStructureType()->getDecl(); 635 } else { 636 break; 637 } 638 639 llvm::StringRef Name = RD->getName(); 640 if (Name.empty()) { 641 if (RD->getTypedefNameForAnonDecl() != NULL) { 642 Name = RD->getTypedefNameForAnonDecl()->getName(); 643 } 644 645 if (Name.empty()) { 646 // Try to find a name from redeclaration (i.e. typedef) 647 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 648 RE = RD->redecls_end(); 649 RI != RE; 650 RI++) { 651 slangAssert(*RI != NULL && "cannot be NULL object"); 652 653 Name = (*RI)->getName(); 654 if (!Name.empty()) 655 break; 656 } 657 } 658 } 659 return Name; 660 } 661 case clang::Type::Pointer: { 662 // "*" plus pointee name 663 const clang::Type *PT = GET_POINTEE_TYPE(T); 664 llvm::StringRef PointeeName; 665 if (NormalizeType(PT, PointeeName, NULL, NULL)) { 666 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 667 Name[0] = '*'; 668 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 669 Name[PointeeName.size() + 1] = '\0'; 670 return Name; 671 } 672 break; 673 } 674 case clang::Type::ExtVector: { 675 const clang::ExtVectorType *EVT = 676 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 677 return RSExportVectorType::GetTypeName(EVT); 678 break; 679 } 680 case clang::Type::ConstantArray : { 681 // Construct name for a constant array is too complicated. 682 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE; 683 } 684 default: { 685 break; 686 } 687 } 688 689 return llvm::StringRef(); 690} 691 692 693RSExportType *RSExportType::Create(RSContext *Context, 694 const clang::Type *T, 695 const llvm::StringRef &TypeName) { 696 // Lookup the context to see whether the type was processed before. 697 // Newly created RSExportType will insert into context 698 // in RSExportType::RSExportType() 699 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 700 701 if (ETI != Context->export_types_end()) 702 return ETI->second; 703 704 RSExportType *ET = NULL; 705 switch (T->getTypeClass()) { 706 case clang::Type::Record: { 707 RSExportPrimitiveType::DataType dt = 708 RSExportPrimitiveType::GetRSSpecificType(TypeName); 709 switch (dt) { 710 case RSExportPrimitiveType::DataTypeUnknown: { 711 // User-defined types 712 ET = RSExportRecordType::Create(Context, 713 T->getAsStructureType(), 714 TypeName); 715 break; 716 } 717 case RSExportPrimitiveType::DataTypeRSMatrix2x2: { 718 // 2 x 2 Matrix type 719 ET = RSExportMatrixType::Create(Context, 720 T->getAsStructureType(), 721 TypeName, 722 2); 723 break; 724 } 725 case RSExportPrimitiveType::DataTypeRSMatrix3x3: { 726 // 3 x 3 Matrix type 727 ET = RSExportMatrixType::Create(Context, 728 T->getAsStructureType(), 729 TypeName, 730 3); 731 break; 732 } 733 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 734 // 4 x 4 Matrix type 735 ET = RSExportMatrixType::Create(Context, 736 T->getAsStructureType(), 737 TypeName, 738 4); 739 break; 740 } 741 default: { 742 // Others are primitive types 743 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 744 break; 745 } 746 } 747 break; 748 } 749 case clang::Type::Builtin: { 750 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 751 break; 752 } 753 case clang::Type::Pointer: { 754 ET = RSExportPointerType::Create(Context, 755 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName); 756 // FIXME: free the name (allocated in RSExportType::GetTypeName) 757 delete [] TypeName.data(); 758 break; 759 } 760 case clang::Type::ExtVector: { 761 ET = RSExportVectorType::Create(Context, 762 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName); 763 break; 764 } 765 case clang::Type::ConstantArray: { 766 ET = RSExportConstantArrayType::Create( 767 Context, 768 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T)); 769 break; 770 } 771 default: { 772 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 773 DiagEngine->Report( 774 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 775 "unknown type cannot be exported: '%0'")) 776 << T->getTypeClassName(); 777 break; 778 } 779 } 780 781 return ET; 782} 783 784RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 785 llvm::StringRef TypeName; 786 if (NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)) { 787 return Create(Context, T, TypeName); 788 } else { 789 return NULL; 790 } 791} 792 793RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 794 const clang::VarDecl *VD) { 795 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 796} 797 798size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 799 return ET->getRSContext()->getTargetData()->getTypeStoreSize( 800 ET->getLLVMType()); 801} 802 803size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 804 if (ET->getClass() == RSExportType::ExportClassRecord) 805 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 806 else 807 return ET->getRSContext()->getTargetData()->getTypeAllocSize( 808 ET->getLLVMType()); 809} 810 811RSExportType::RSExportType(RSContext *Context, 812 ExportClass Class, 813 const llvm::StringRef &Name) 814 : RSExportable(Context, RSExportable::EX_TYPE), 815 mClass(Class), 816 // Make a copy on Name since memory stored @Name is either allocated in 817 // ASTContext or allocated in GetTypeName which will be destroyed later. 818 mName(Name.data(), Name.size()), 819 mLLVMType(NULL), 820 mSpecType(NULL) { 821 // Don't cache the type whose name start with '<'. Those type failed to 822 // get their name since constructing their name in GetTypeName() requiring 823 // complicated work. 824 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX)) 825 // TODO(zonr): Need to check whether the insertion is successful or not. 826 Context->insertExportType(llvm::StringRef(Name), this); 827 return; 828} 829 830bool RSExportType::keep() { 831 if (!RSExportable::keep()) 832 return false; 833 // Invalidate converted LLVM type. 834 mLLVMType = NULL; 835 return true; 836} 837 838bool RSExportType::equals(const RSExportable *E) const { 839 CHECK_PARENT_EQUALITY(RSExportable, E); 840 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 841} 842 843RSExportType::~RSExportType() { 844 delete mSpecType; 845} 846 847/************************** RSExportPrimitiveType **************************/ 848llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 849RSExportPrimitiveType::RSSpecificTypeMap; 850 851llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 852 853bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 854 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 855 return true; 856 else 857 return false; 858} 859 860RSExportPrimitiveType::DataType 861RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 862 if (TypeName.empty()) 863 return DataTypeUnknown; 864 865 if (RSSpecificTypeMap->empty()) { 866#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \ 867 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 868#include "RSMatrixTypeEnums.inc" 869#define ENUM_RS_OBJECT_TYPE(type, cname) \ 870 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 871#include "RSObjectTypeEnums.inc" 872 } 873 874 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 875 if (I == RSSpecificTypeMap->end()) 876 return DataTypeUnknown; 877 else 878 return I->getValue(); 879} 880 881RSExportPrimitiveType::DataType 882RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 883 T = GET_CANONICAL_TYPE(T); 884 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 885 return DataTypeUnknown; 886 887 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 888} 889 890bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 891 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType)); 892} 893 894bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 895 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType)); 896} 897 898bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 899 bool RSObjectTypeSeen = false; 900 while (T && T->isArrayType()) { 901 T = T->getArrayElementTypeNoTypeQual(); 902 } 903 904 const clang::RecordType *RT = T->getAsStructureType(); 905 if (!RT) { 906 return false; 907 } 908 const clang::RecordDecl *RD = RT->getDecl(); 909 RD = RD->getDefinition(); 910 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 911 FE = RD->field_end(); 912 FI != FE; 913 FI++) { 914 // We just look through all field declarations to see if we find a 915 // declaration for an RS object type (or an array of one). 916 const clang::FieldDecl *FD = *FI; 917 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 918 while (FT && FT->isArrayType()) { 919 FT = FT->getArrayElementTypeNoTypeQual(); 920 } 921 922 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT); 923 if (IsRSObjectType(DT)) { 924 // RS object types definitely need to be zero-initialized 925 RSObjectTypeSeen = true; 926 } else { 927 switch (DT) { 928 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 929 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 930 case RSExportPrimitiveType::DataTypeRSMatrix4x4: 931 // Matrix types should get zero-initialized as well 932 RSObjectTypeSeen = true; 933 break; 934 default: 935 // Ignore all other primitive types 936 break; 937 } 938 while (FT && FT->isArrayType()) { 939 FT = FT->getArrayElementTypeNoTypeQual(); 940 } 941 if (FT->isStructureType()) { 942 // Recursively handle structs of structs (even though these can't 943 // be exported, it is possible for a user to have them internally). 944 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 945 } 946 } 947 } 948 949 return RSObjectTypeSeen; 950} 951 952const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = { 953#define ENUM_RS_DATA_TYPE(type, cname, bits) \ 954 bits, 955#include "RSDataTypeEnums.inc" 956 0 // DataTypeMax 957}; 958 959size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 960 slangAssert(((EPT->getType() > DataTypeUnknown) && 961 (EPT->getType() < DataTypeMax)) && 962 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 963 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ]; 964} 965 966RSExportPrimitiveType::DataType 967RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 968 if (T == NULL) 969 return DataTypeUnknown; 970 971 switch (T->getTypeClass()) { 972 case clang::Type::Builtin: { 973 const clang::BuiltinType *BT = 974 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 975 switch (BT->getKind()) { 976#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 977 case builtin_type: { \ 978 return DataType ## type; \ 979 } 980#include "RSClangBuiltinEnums.inc" 981 // The size of type WChar depend on platform so we abandon the support 982 // to them. 983 default: { 984 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 985 DiagEngine->Report( 986 DiagEngine->getCustomDiagID( 987 clang::DiagnosticsEngine::Error, 988 "built-in type cannot be exported: '%0'")) 989 << T->getTypeClassName(); 990 break; 991 } 992 } 993 break; 994 } 995 case clang::Type::Record: { 996 // must be RS object type 997 return RSExportPrimitiveType::GetRSSpecificType(T); 998 } 999 default: { 1000 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 1001 DiagEngine->Report( 1002 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1003 "primitive type cannot be exported: '%0'")) 1004 << T->getTypeClassName(); 1005 break; 1006 } 1007 } 1008 1009 return DataTypeUnknown; 1010} 1011 1012RSExportPrimitiveType 1013*RSExportPrimitiveType::Create(RSContext *Context, 1014 const clang::Type *T, 1015 const llvm::StringRef &TypeName, 1016 bool Normalized) { 1017 DataType DT = GetDataType(Context, T); 1018 1019 if ((DT == DataTypeUnknown) || TypeName.empty()) 1020 return NULL; 1021 else 1022 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 1023 DT, Normalized); 1024} 1025 1026RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 1027 const clang::Type *T) { 1028 llvm::StringRef TypeName; 1029 if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL) 1030 && IsPrimitiveType(T)) { 1031 return Create(Context, T, TypeName); 1032 } else { 1033 return NULL; 1034 } 1035} 1036 1037llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 1038 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1039 1040 if (isRSObjectType()) { 1041 // struct { 1042 // int *p; 1043 // } __attribute__((packed, aligned(pointer_size))) 1044 // 1045 // which is 1046 // 1047 // <{ [1 x i32] }> in LLVM 1048 // 1049 if (RSObjectLLVMType == NULL) { 1050 std::vector<llvm::Type *> Elements; 1051 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 1052 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 1053 } 1054 return RSObjectLLVMType; 1055 } 1056 1057 switch (mType) { 1058 case DataTypeFloat32: { 1059 return llvm::Type::getFloatTy(C); 1060 break; 1061 } 1062 case DataTypeFloat64: { 1063 return llvm::Type::getDoubleTy(C); 1064 break; 1065 } 1066 case DataTypeBoolean: { 1067 return llvm::Type::getInt1Ty(C); 1068 break; 1069 } 1070 case DataTypeSigned8: 1071 case DataTypeUnsigned8: { 1072 return llvm::Type::getInt8Ty(C); 1073 break; 1074 } 1075 case DataTypeSigned16: 1076 case DataTypeUnsigned16: 1077 case DataTypeUnsigned565: 1078 case DataTypeUnsigned5551: 1079 case DataTypeUnsigned4444: { 1080 return llvm::Type::getInt16Ty(C); 1081 break; 1082 } 1083 case DataTypeSigned32: 1084 case DataTypeUnsigned32: { 1085 return llvm::Type::getInt32Ty(C); 1086 break; 1087 } 1088 case DataTypeSigned64: 1089 case DataTypeUnsigned64: { 1090 return llvm::Type::getInt64Ty(C); 1091 break; 1092 } 1093 default: { 1094 slangAssert(false && "Unknown data type"); 1095 } 1096 } 1097 1098 return NULL; 1099} 1100 1101union RSType *RSExportPrimitiveType::convertToSpecType() const { 1102 llvm::OwningPtr<union RSType> ST(new union RSType); 1103 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive); 1104 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in 1105 // slang_rs_type_spec.h 1106 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType()); 1107 return ST.take(); 1108} 1109 1110bool RSExportPrimitiveType::equals(const RSExportable *E) const { 1111 CHECK_PARENT_EQUALITY(RSExportType, E); 1112 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 1113} 1114 1115RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) { 1116 if (DT > DataTypeUnknown && DT < DataTypeMax) { 1117 return &gReflectionTypes[DT]; 1118 } else { 1119 return NULL; 1120 } 1121} 1122 1123/**************************** RSExportPointerType ****************************/ 1124 1125RSExportPointerType 1126*RSExportPointerType::Create(RSContext *Context, 1127 const clang::PointerType *PT, 1128 const llvm::StringRef &TypeName) { 1129 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 1130 const RSExportType *PointeeET; 1131 1132 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 1133 PointeeET = RSExportType::Create(Context, PointeeType); 1134 } else { 1135 // Double or higher dimension of pointer, export as int* 1136 PointeeET = RSExportPrimitiveType::Create(Context, 1137 Context->getASTContext().IntTy.getTypePtr()); 1138 } 1139 1140 if (PointeeET == NULL) { 1141 // Error diagnostic is emitted for corresponding pointee type 1142 return NULL; 1143 } 1144 1145 return new RSExportPointerType(Context, TypeName, PointeeET); 1146} 1147 1148llvm::Type *RSExportPointerType::convertToLLVMType() const { 1149 llvm::Type *PointeeType = mPointeeType->getLLVMType(); 1150 return llvm::PointerType::getUnqual(PointeeType); 1151} 1152 1153union RSType *RSExportPointerType::convertToSpecType() const { 1154 llvm::OwningPtr<union RSType> ST(new union RSType); 1155 1156 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer); 1157 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType()); 1158 1159 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL) 1160 return ST.take(); 1161 else 1162 return NULL; 1163} 1164 1165bool RSExportPointerType::keep() { 1166 if (!RSExportType::keep()) 1167 return false; 1168 const_cast<RSExportType*>(mPointeeType)->keep(); 1169 return true; 1170} 1171 1172bool RSExportPointerType::equals(const RSExportable *E) const { 1173 CHECK_PARENT_EQUALITY(RSExportType, E); 1174 return (static_cast<const RSExportPointerType*>(E) 1175 ->getPointeeType()->equals(getPointeeType())); 1176} 1177 1178/***************************** RSExportVectorType *****************************/ 1179llvm::StringRef 1180RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 1181 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1182 1183 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 1184 return llvm::StringRef(); 1185 1186 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType, 1187 ElementType); 1188 if ((EVT->getNumElements() < 1) || 1189 (EVT->getNumElements() > 4)) 1190 return llvm::StringRef(); 1191 1192 switch (BT->getKind()) { 1193 // Compiler is smart enough to optimize following *big if branches* since 1194 // they all become "constant comparison" after macro expansion 1195#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 1196 case builtin_type: { \ 1197 const char *Name[] = { cname"2", cname"3", cname"4" }; \ 1198 return Name[EVT->getNumElements() - 2]; \ 1199 break; \ 1200 } 1201#include "RSClangBuiltinEnums.inc" 1202 default: { 1203 return llvm::StringRef(); 1204 } 1205 } 1206} 1207 1208RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 1209 const clang::ExtVectorType *EVT, 1210 const llvm::StringRef &TypeName, 1211 bool Normalized) { 1212 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 1213 1214 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1215 RSExportPrimitiveType::DataType DT = 1216 RSExportPrimitiveType::GetDataType(Context, ElementType); 1217 1218 if (DT != RSExportPrimitiveType::DataTypeUnknown) 1219 return new RSExportVectorType(Context, 1220 TypeName, 1221 DT, 1222 Normalized, 1223 EVT->getNumElements()); 1224 else 1225 return NULL; 1226} 1227 1228llvm::Type *RSExportVectorType::convertToLLVMType() const { 1229 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 1230 return llvm::VectorType::get(ElementType, getNumElement()); 1231} 1232 1233union RSType *RSExportVectorType::convertToSpecType() const { 1234 llvm::OwningPtr<union RSType> ST(new union RSType); 1235 1236 RS_TYPE_SET_CLASS(ST, RS_TC_Vector); 1237 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType()); 1238 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement()); 1239 1240 return ST.take(); 1241} 1242 1243bool RSExportVectorType::equals(const RSExportable *E) const { 1244 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 1245 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 1246 == getNumElement()); 1247} 1248 1249/***************************** RSExportMatrixType *****************************/ 1250RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 1251 const clang::RecordType *RT, 1252 const llvm::StringRef &TypeName, 1253 unsigned Dim) { 1254 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 1255 slangAssert((Dim > 1) && "Invalid dimension of matrix"); 1256 1257 // Check whether the struct rs_matrix is in our expected form (but assume it's 1258 // correct if we're not sure whether it's correct or not) 1259 const clang::RecordDecl* RD = RT->getDecl(); 1260 RD = RD->getDefinition(); 1261 if (RD != NULL) { 1262 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 1263 const clang::SourceManager *SM = Context->getSourceManager(); 1264 // Find definition, perform further examination 1265 if (RD->field_empty()) { 1266 DiagEngine->Report( 1267 clang::FullSourceLoc(RD->getLocation(), *SM), 1268 DiagEngine->getCustomDiagID( 1269 clang::DiagnosticsEngine::Error, 1270 "invalid matrix struct: must have 1 field for saving values: '%0'")) 1271 << RD->getName(); 1272 return NULL; 1273 } 1274 1275 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 1276 const clang::FieldDecl *FD = *FIT; 1277 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1278 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 1279 DiagEngine->Report( 1280 clang::FullSourceLoc(RD->getLocation(), *SM), 1281 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1282 "invalid matrix struct: first field should" 1283 " be an array with constant size: '%0'")) 1284 << RD->getName(); 1285 return NULL; 1286 } 1287 const clang::ConstantArrayType *CAT = 1288 static_cast<const clang::ConstantArrayType *>(FT); 1289 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1290 if ((ElementType == NULL) || 1291 (ElementType->getTypeClass() != clang::Type::Builtin) || 1292 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() != 1293 clang::BuiltinType::Float)) { 1294 DiagEngine->Report( 1295 clang::FullSourceLoc(RD->getLocation(), *SM), 1296 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1297 "invalid matrix struct: first field " 1298 "should be a float array: '%0'")) 1299 << RD->getName(); 1300 return NULL; 1301 } 1302 1303 if (CAT->getSize() != Dim * Dim) { 1304 DiagEngine->Report( 1305 clang::FullSourceLoc(RD->getLocation(), *SM), 1306 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1307 "invalid matrix struct: first field " 1308 "should be an array with size %0: '%1'")) 1309 << (Dim * Dim) << (RD->getName()); 1310 return NULL; 1311 } 1312 1313 FIT++; 1314 if (FIT != RD->field_end()) { 1315 DiagEngine->Report( 1316 clang::FullSourceLoc(RD->getLocation(), *SM), 1317 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1318 "invalid matrix struct: must have " 1319 "exactly 1 field: '%0'")) 1320 << RD->getName(); 1321 return NULL; 1322 } 1323 } 1324 1325 return new RSExportMatrixType(Context, TypeName, Dim); 1326} 1327 1328llvm::Type *RSExportMatrixType::convertToLLVMType() const { 1329 // Construct LLVM type: 1330 // struct { 1331 // float X[mDim * mDim]; 1332 // } 1333 1334 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1335 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 1336 mDim * mDim); 1337 return llvm::StructType::get(C, X, false); 1338} 1339 1340union RSType *RSExportMatrixType::convertToSpecType() const { 1341 llvm::OwningPtr<union RSType> ST(new union RSType); 1342 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix); 1343 switch (getDim()) { 1344 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break; 1345 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break; 1346 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break; 1347 default: slangAssert(false && "Matrix type with unsupported dimension."); 1348 } 1349 return ST.take(); 1350} 1351 1352bool RSExportMatrixType::equals(const RSExportable *E) const { 1353 CHECK_PARENT_EQUALITY(RSExportType, E); 1354 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 1355} 1356 1357/************************* RSExportConstantArrayType *************************/ 1358RSExportConstantArrayType 1359*RSExportConstantArrayType::Create(RSContext *Context, 1360 const clang::ConstantArrayType *CAT) { 1361 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 1362 1363 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large"); 1364 1365 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 1366 slangAssert((Size > 0) && "Constant array should have size greater than 0"); 1367 1368 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1369 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 1370 1371 if (ElementET == NULL) { 1372 return NULL; 1373 } 1374 1375 return new RSExportConstantArrayType(Context, 1376 ElementET, 1377 Size); 1378} 1379 1380llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 1381 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 1382} 1383 1384union RSType *RSExportConstantArrayType::convertToSpecType() const { 1385 llvm::OwningPtr<union RSType> ST(new union RSType); 1386 1387 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray); 1388 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE( 1389 ST, getElementType()->getSpecType()); 1390 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize()); 1391 1392 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL) 1393 return ST.take(); 1394 else 1395 return NULL; 1396} 1397 1398bool RSExportConstantArrayType::keep() { 1399 if (!RSExportType::keep()) 1400 return false; 1401 const_cast<RSExportType*>(mElementType)->keep(); 1402 return true; 1403} 1404 1405bool RSExportConstantArrayType::equals(const RSExportable *E) const { 1406 CHECK_PARENT_EQUALITY(RSExportType, E); 1407 const RSExportConstantArrayType *RHS = 1408 static_cast<const RSExportConstantArrayType*>(E); 1409 return ((getSize() == RHS->getSize()) && 1410 (getElementType()->equals(RHS->getElementType()))); 1411} 1412 1413/**************************** RSExportRecordType ****************************/ 1414RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 1415 const clang::RecordType *RT, 1416 const llvm::StringRef &TypeName, 1417 bool mIsArtificial) { 1418 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 1419 1420 const clang::RecordDecl *RD = RT->getDecl(); 1421 slangAssert(RD->isStruct()); 1422 1423 RD = RD->getDefinition(); 1424 if (RD == NULL) { 1425 slangAssert(false && "struct is not defined in this module"); 1426 return NULL; 1427 } 1428 1429 // Struct layout construct by clang. We rely on this for obtaining the 1430 // alloc size of a struct and offset of every field in that struct. 1431 const clang::ASTRecordLayout *RL = 1432 &Context->getASTContext().getASTRecordLayout(RD); 1433 slangAssert((RL != NULL) && 1434 "Failed to retrieve the struct layout from Clang."); 1435 1436 RSExportRecordType *ERT = 1437 new RSExportRecordType(Context, 1438 TypeName, 1439 RD->hasAttr<clang::PackedAttr>(), 1440 mIsArtificial, 1441 RL->getSize().getQuantity()); 1442 unsigned int Index = 0; 1443 1444 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1445 FE = RD->field_end(); 1446 FI != FE; 1447 FI++, Index++) { 1448 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 1449 1450 // FIXME: All fields should be primitive type 1451 slangAssert(FI->getKind() == clang::Decl::Field); 1452 clang::FieldDecl *FD = *FI; 1453 1454 if (FD->isBitField()) { 1455 return NULL; 1456 } 1457 1458 // Type 1459 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1460 1461 if (ET != NULL) { 1462 ERT->mFields.push_back( 1463 new Field(ET, FD->getName(), ERT, 1464 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1465 } else { 1466 DiagEngine->Report( 1467 clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()), 1468 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1469 "field type cannot be exported: '%0.%1'")) 1470 << RD->getName() << FD->getName(); 1471 return NULL; 1472 } 1473 } 1474 1475 return ERT; 1476} 1477 1478llvm::Type *RSExportRecordType::convertToLLVMType() const { 1479 // Create an opaque type since struct may reference itself recursively. 1480 1481 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to? 1482 std::vector<llvm::Type*> FieldTypes; 1483 1484 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1485 FI != FE; 1486 FI++) { 1487 const Field *F = *FI; 1488 const RSExportType *FET = F->getType(); 1489 1490 FieldTypes.push_back(FET->getLLVMType()); 1491 } 1492 1493 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1494 FieldTypes, 1495 mIsPacked); 1496 if (ST != NULL) { 1497 return ST; 1498 } else { 1499 return NULL; 1500 } 1501} 1502 1503union RSType *RSExportRecordType::convertToSpecType() const { 1504 unsigned NumFields = getFields().size(); 1505 unsigned AllocSize = sizeof(union RSType) + 1506 sizeof(struct RSRecordField) * NumFields; 1507 llvm::OwningPtr<union RSType> ST( 1508 reinterpret_cast<union RSType*>(operator new(AllocSize))); 1509 1510 ::memset(ST.get(), 0, AllocSize); 1511 1512 RS_TYPE_SET_CLASS(ST, RS_TC_Record); 1513 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str()); 1514 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields); 1515 1516 setSpecTypeTemporarily(ST.get()); 1517 1518 unsigned FieldIdx = 0; 1519 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1520 FI != FE; 1521 FI++, FieldIdx++) { 1522 const Field *F = *FI; 1523 1524 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str()); 1525 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType()); 1526 } 1527 1528 // TODO(slang): Check whether all fields were created normally. 1529 1530 return ST.take(); 1531} 1532 1533bool RSExportRecordType::keep() { 1534 if (!RSExportType::keep()) 1535 return false; 1536 for (std::list<const Field*>::iterator I = mFields.begin(), 1537 E = mFields.end(); 1538 I != E; 1539 I++) { 1540 const_cast<RSExportType*>((*I)->getType())->keep(); 1541 } 1542 return true; 1543} 1544 1545bool RSExportRecordType::equals(const RSExportable *E) const { 1546 CHECK_PARENT_EQUALITY(RSExportType, E); 1547 1548 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1549 1550 if (ERT->getFields().size() != getFields().size()) 1551 return false; 1552 1553 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1554 1555 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1556 if (!(*AI)->getType()->equals((*BI)->getType())) 1557 return false; 1558 AI++; 1559 BI++; 1560 } 1561 1562 return true; 1563} 1564 1565void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const { 1566 memset(rtd, 0, sizeof(*rtd)); 1567 rtd->vecSize = 1; 1568 1569 switch(getClass()) { 1570 case RSExportType::ExportClassPrimitive: { 1571 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this); 1572 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT); 1573 return; 1574 } 1575 case RSExportType::ExportClassPointer: { 1576 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this); 1577 const RSExportType *PointeeType = EPT->getPointeeType(); 1578 PointeeType->convertToRTD(rtd); 1579 rtd->isPointer = true; 1580 return; 1581 } 1582 case RSExportType::ExportClassVector: { 1583 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this); 1584 rtd->type = EVT->getRSReflectionType(EVT); 1585 rtd->vecSize = EVT->getNumElement(); 1586 return; 1587 } 1588 case RSExportType::ExportClassMatrix: { 1589 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this); 1590 unsigned Dim = EMT->getDim(); 1591 slangAssert((Dim >= 2) && (Dim <= 4)); 1592 rtd->type = &gReflectionTypes[15 + Dim-2]; 1593 return; 1594 } 1595 case RSExportType::ExportClassConstantArray: { 1596 const RSExportConstantArrayType* CAT = 1597 static_cast<const RSExportConstantArrayType*>(this); 1598 CAT->getElementType()->convertToRTD(rtd); 1599 rtd->arraySize = CAT->getSize(); 1600 return; 1601 } 1602 case RSExportType::ExportClassRecord: { 1603 slangAssert(!"RSExportType::ExportClassRecord not implemented"); 1604 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item"; 1605 } 1606 default: { 1607 slangAssert(false && "Unknown class of type"); 1608 } 1609 } 1610} 1611 1612 1613} // namespace slang 1614