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