slang_rs_export_type.cpp revision a7b7518aa3725d5cff1c1a6319ec7a6b8b244e0e
1/* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "slang_rs_export_type.h" 18 19#include <list> 20#include <vector> 21 22#include "clang/AST/RecordLayout.h" 23 24#include "llvm/ADT/StringExtras.h" 25 26#include "llvm/DerivedTypes.h" 27 28#include "llvm/Target/TargetData.h" 29 30#include "llvm/Type.h" 31 32#include "slang_rs_context.h" 33#include "slang_rs_export_element.h" 34#include "slang_rs_type_spec.h" 35 36#define CHECK_PARENT_EQUALITY(ParentClass, E) \ 37 if (!ParentClass::equals(E)) \ 38 return false; 39 40namespace slang { 41 42namespace { 43 44const clang::Type *TypeExportableHelper( 45 const clang::Type *T, 46 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 47 clang::Diagnostic *Diags, 48 clang::SourceManager *SM, 49 const clang::RecordDecl *TopLevelRecord) { 50 // Normalize first 51 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 52 return NULL; 53 54 if (SPS.count(T)) 55 return T; 56 57 switch (T->getTypeClass()) { 58 case clang::Type::Builtin: { 59 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T); 60 61 switch (BT->getKind()) { 62#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 63 case builtin_type: 64#include "RSClangBuiltinEnums.inc" 65 return T; 66 default: { 67 return NULL; 68 } 69 } 70 } 71 case clang::Type::Record: { 72 if (RSExportPrimitiveType::GetRSSpecificType(T) != 73 RSExportPrimitiveType::DataTypeUnknown) 74 return T; // RS object type, no further checks are needed 75 76 // Check internal struct 77 clang::RecordDecl *RD = NULL; 78 if (T->isUnionType()) { 79 RD = T->getAsUnionType()->getDecl(); 80 if (Diags && SM) { 81 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 82 Diags->getCustomDiagID(clang::Diagnostic::Error, 83 "unions cannot " 84 "be exported: '%0'")) 85 << RD->getName(); 86 } 87 return NULL; 88 } else if (!T->isStructureType()) { 89 assert(false && "Unknown type cannot be exported"); 90 return NULL; 91 } 92 93 RD = T->getAsStructureType()->getDecl(); 94 if (RD != NULL) 95 RD = RD->getDefinition(); 96 97 if (!TopLevelRecord) { 98 TopLevelRecord = RD; 99 } 100 if (RD->getName().empty()) { 101 if (Diags && SM) { 102 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 103 Diags->getCustomDiagID(clang::Diagnostic::Error, 104 "anonymous structures cannot " 105 "be exported")); 106 } 107 return NULL; 108 } 109 110 // Fast check 111 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 112 return NULL; 113 114 // Insert myself into checking set 115 SPS.insert(T); 116 117 // Check all element 118 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 119 FE = RD->field_end(); 120 FI != FE; 121 FI++) { 122 const clang::FieldDecl *FD = *FI; 123 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 124 FT = GET_CANONICAL_TYPE(FT); 125 126 if (!TypeExportableHelper(FT, SPS, Diags, SM, TopLevelRecord)) { 127 return NULL; 128 } 129 } 130 131 return T; 132 } 133 case clang::Type::Pointer: { 134 if (TopLevelRecord) { 135 if (Diags && SM) { 136 Diags->Report(clang::FullSourceLoc(TopLevelRecord->getLocation(), 137 *SM), 138 Diags->getCustomDiagID(clang::Diagnostic::Error, 139 "structures containing pointers " 140 "cannot be exported: '%0'")) 141 << TopLevelRecord->getName(); 142 } 143 return NULL; 144 } 145 const clang::PointerType *PT = UNSAFE_CAST_TYPE(clang::PointerType, T); 146 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 147 148 if (PointeeType->getTypeClass() == clang::Type::Pointer) 149 return T; 150 // We don't support pointer with array-type pointee or unsupported pointee 151 // type 152 if (PointeeType->isArrayType() || 153 (TypeExportableHelper(PointeeType, SPS, Diags, SM, 154 TopLevelRecord) == NULL)) 155 return NULL; 156 else 157 return T; 158 } 159 case clang::Type::ExtVector: { 160 const clang::ExtVectorType *EVT = 161 UNSAFE_CAST_TYPE(clang::ExtVectorType, T); 162 // Only vector with size 2, 3 and 4 are supported. 163 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4) 164 return NULL; 165 166 // Check base element type 167 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 168 169 if ((ElementType->getTypeClass() != clang::Type::Builtin) || 170 (TypeExportableHelper(ElementType, SPS, Diags, SM, 171 TopLevelRecord) == NULL)) 172 return NULL; 173 else 174 return T; 175 } 176 case clang::Type::ConstantArray: { 177 const clang::ConstantArrayType *CAT = 178 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T); 179 180 // Check size 181 if (CAT->getSize().getActiveBits() > 32) { 182 fprintf(stderr, "RSExportConstantArrayType::Create : array with too " 183 "large size (> 2^32).\n"); 184 return NULL; 185 } 186 // Check element type 187 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 188 if (ElementType->isArrayType()) { 189 fprintf(stderr, "RSExportType::TypeExportableHelper : constant array " 190 "with 2 or higher dimension of constant is not " 191 "supported.\n"); 192 return NULL; 193 } 194 if (TypeExportableHelper(ElementType, SPS, Diags, SM, 195 TopLevelRecord) == NULL) 196 return NULL; 197 else 198 return T; 199 } 200 default: { 201 return NULL; 202 } 203 } 204} 205 206// Return the type that can be used to create RSExportType, will always return 207// the canonical type 208// If the Type T is not exportable, this function returns NULL. Diags and SM 209// are used to generate proper Clang diagnostic messages when a 210// non-exportable type is detected. TopLevelRecord is used to capture the 211// highest struct (in the case of a nested hierarchy) for detecting other 212// types that cannot be exported (mostly pointers within a struct). 213static const clang::Type *TypeExportable(const clang::Type *T, 214 clang::Diagnostic *Diags, 215 clang::SourceManager *SM) { 216 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 217 llvm::SmallPtrSet<const clang::Type*, 8>(); 218 219 return TypeExportableHelper(T, SPS, Diags, SM, NULL); 220} 221 222} // namespace 223 224/****************************** RSExportType ******************************/ 225bool RSExportType::NormalizeType(const clang::Type *&T, 226 llvm::StringRef &TypeName, 227 clang::Diagnostic *Diags, 228 clang::SourceManager *SM) { 229 if ((T = TypeExportable(T, Diags, SM)) == NULL) { 230 return false; 231 } 232 // Get type name 233 TypeName = RSExportType::GetTypeName(T); 234 if (TypeName.empty()) { 235 if (Diags && SM) { 236 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error, 237 "anonymous types cannot " 238 "be exported")); 239 } 240 return false; 241 } 242 243 return true; 244} 245 246const clang::Type 247*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 248 if (DD) { 249 clang::QualType T; 250 if (DD->getTypeSourceInfo()) 251 T = DD->getTypeSourceInfo()->getType(); 252 else 253 T = DD->getType(); 254 255 if (T.isNull()) 256 return NULL; 257 else 258 return T.getTypePtr(); 259 } 260 return NULL; 261} 262 263llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 264 T = GET_CANONICAL_TYPE(T); 265 if (T == NULL) 266 return llvm::StringRef(); 267 268 switch (T->getTypeClass()) { 269 case clang::Type::Builtin: { 270 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T); 271 272 switch (BT->getKind()) { 273#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 274 case builtin_type: \ 275 return cname; \ 276 break; 277#include "RSClangBuiltinEnums.inc" 278 default: { 279 assert(false && "Unknown data type of the builtin"); 280 break; 281 } 282 } 283 break; 284 } 285 case clang::Type::Record: { 286 clang::RecordDecl *RD; 287 if (T->isStructureType()) { 288 RD = T->getAsStructureType()->getDecl(); 289 } 290 else { 291 break; 292 } 293 294 llvm::StringRef Name = RD->getName(); 295 if (Name.empty()) { 296 if (RD->getTypedefForAnonDecl() != NULL) 297 Name = RD->getTypedefForAnonDecl()->getName(); 298 299 if (Name.empty()) 300 // Try to find a name from redeclaration (i.e. typedef) 301 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 302 RE = RD->redecls_end(); 303 RI != RE; 304 RI++) { 305 assert(*RI != NULL && "cannot be NULL object"); 306 307 Name = (*RI)->getName(); 308 if (!Name.empty()) 309 break; 310 } 311 } 312 return Name; 313 } 314 case clang::Type::Pointer: { 315 // "*" plus pointee name 316 const clang::Type *PT = GET_POINTEE_TYPE(T); 317 llvm::StringRef PointeeName; 318 if (NormalizeType(PT, PointeeName, NULL, NULL)) { 319 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 320 Name[0] = '*'; 321 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 322 Name[PointeeName.size() + 1] = '\0'; 323 return Name; 324 } 325 break; 326 } 327 case clang::Type::ExtVector: { 328 const clang::ExtVectorType *EVT = 329 UNSAFE_CAST_TYPE(clang::ExtVectorType, T); 330 return RSExportVectorType::GetTypeName(EVT); 331 break; 332 } 333 case clang::Type::ConstantArray : { 334 // Construct name for a constant array is too complicated. 335 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE; 336 } 337 default: { 338 break; 339 } 340 } 341 342 return llvm::StringRef(); 343} 344 345 346RSExportType *RSExportType::Create(RSContext *Context, 347 const clang::Type *T, 348 const llvm::StringRef &TypeName) { 349 // Lookup the context to see whether the type was processed before. 350 // Newly created RSExportType will insert into context 351 // in RSExportType::RSExportType() 352 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 353 354 if (ETI != Context->export_types_end()) 355 return ETI->second; 356 357 RSExportType *ET = NULL; 358 switch (T->getTypeClass()) { 359 case clang::Type::Record: { 360 RSExportPrimitiveType::DataType dt = 361 RSExportPrimitiveType::GetRSSpecificType(TypeName); 362 switch (dt) { 363 case RSExportPrimitiveType::DataTypeUnknown: { 364 // User-defined types 365 ET = RSExportRecordType::Create(Context, 366 T->getAsStructureType(), 367 TypeName); 368 break; 369 } 370 case RSExportPrimitiveType::DataTypeRSMatrix2x2: { 371 // 2 x 2 Matrix type 372 ET = RSExportMatrixType::Create(Context, 373 T->getAsStructureType(), 374 TypeName, 375 2); 376 break; 377 } 378 case RSExportPrimitiveType::DataTypeRSMatrix3x3: { 379 // 3 x 3 Matrix type 380 ET = RSExportMatrixType::Create(Context, 381 T->getAsStructureType(), 382 TypeName, 383 3); 384 break; 385 } 386 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 387 // 4 x 4 Matrix type 388 ET = RSExportMatrixType::Create(Context, 389 T->getAsStructureType(), 390 TypeName, 391 4); 392 break; 393 } 394 default: { 395 // Others are primitive types 396 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 397 break; 398 } 399 } 400 break; 401 } 402 case clang::Type::Builtin: { 403 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 404 break; 405 } 406 case clang::Type::Pointer: { 407 ET = RSExportPointerType::Create(Context, 408 UNSAFE_CAST_TYPE(clang::PointerType, T), 409 TypeName); 410 // FIXME: free the name (allocated in RSExportType::GetTypeName) 411 delete [] TypeName.data(); 412 break; 413 } 414 case clang::Type::ExtVector: { 415 ET = RSExportVectorType::Create(Context, 416 UNSAFE_CAST_TYPE(clang::ExtVectorType, T), 417 TypeName); 418 break; 419 } 420 case clang::Type::ConstantArray: { 421 ET = RSExportConstantArrayType::Create( 422 Context, 423 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T)); 424 break; 425 } 426 default: { 427 // TODO(zonr): warn that type is not exportable. 428 fprintf(stderr, 429 "RSExportType::Create : type '%s' is not exportable\n", 430 T->getTypeClassName()); 431 break; 432 } 433 } 434 435 return ET; 436} 437 438RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 439 llvm::StringRef TypeName; 440 if (NormalizeType(T, TypeName, NULL, NULL)) 441 return Create(Context, T, TypeName); 442 else 443 return NULL; 444} 445 446RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 447 const clang::VarDecl *VD) { 448 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 449} 450 451size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 452 return ET->getRSContext()->getTargetData()->getTypeStoreSize( 453 ET->getLLVMType()); 454} 455 456size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 457 if (ET->getClass() == RSExportType::ExportClassRecord) 458 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 459 else 460 return ET->getRSContext()->getTargetData()->getTypeAllocSize( 461 ET->getLLVMType()); 462} 463 464RSExportType::RSExportType(RSContext *Context, 465 ExportClass Class, 466 const llvm::StringRef &Name) 467 : RSExportable(Context, RSExportable::EX_TYPE), 468 mClass(Class), 469 // Make a copy on Name since memory stored @Name is either allocated in 470 // ASTContext or allocated in GetTypeName which will be destroyed later. 471 mName(Name.data(), Name.size()), 472 mLLVMType(NULL), 473 mSpecType(NULL) { 474 // Don't cache the type whose name start with '<'. Those type failed to 475 // get their name since constructing their name in GetTypeName() requiring 476 // complicated work. 477 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX)) 478 // TODO(zonr): Need to check whether the insertion is successful or not. 479 Context->insertExportType(llvm::StringRef(Name), this); 480 return; 481} 482 483bool RSExportType::keep() { 484 if (!RSExportable::keep()) 485 return false; 486 // Invalidate converted LLVM type. 487 mLLVMType = NULL; 488 return true; 489} 490 491bool RSExportType::equals(const RSExportable *E) const { 492 CHECK_PARENT_EQUALITY(RSExportable, E); 493 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 494} 495 496RSExportType::~RSExportType() { 497 delete mSpecType; 498} 499 500/************************** RSExportPrimitiveType **************************/ 501llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 502RSExportPrimitiveType::RSSpecificTypeMap; 503 504llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 505 506bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 507 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 508 return true; 509 else 510 return false; 511} 512 513RSExportPrimitiveType::DataType 514RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 515 if (TypeName.empty()) 516 return DataTypeUnknown; 517 518 if (RSSpecificTypeMap->empty()) { 519#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \ 520 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 521#include "RSMatrixTypeEnums.inc" 522#define ENUM_RS_OBJECT_TYPE(type, cname) \ 523 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 524#include "RSObjectTypeEnums.inc" 525 } 526 527 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 528 if (I == RSSpecificTypeMap->end()) 529 return DataTypeUnknown; 530 else 531 return I->getValue(); 532} 533 534RSExportPrimitiveType::DataType 535RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 536 T = GET_CANONICAL_TYPE(T); 537 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 538 return DataTypeUnknown; 539 540 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 541} 542 543bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 544 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType)); 545} 546 547bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 548 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType)); 549} 550 551const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = { 552#define ENUM_RS_DATA_TYPE(type, cname, bits) \ 553 bits, 554#include "RSDataTypeEnums.inc" 555 0 // DataTypeMax 556}; 557 558size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 559 assert(((EPT->getType() > DataTypeUnknown) && 560 (EPT->getType() < DataTypeMax)) && 561 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 562 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ]; 563} 564 565RSExportPrimitiveType::DataType 566RSExportPrimitiveType::GetDataType(const clang::Type *T) { 567 if (T == NULL) 568 return DataTypeUnknown; 569 570 switch (T->getTypeClass()) { 571 case clang::Type::Builtin: { 572 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T); 573 switch (BT->getKind()) { 574#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 575 case builtin_type: { \ 576 return DataType ## type; \ 577 } 578#include "RSClangBuiltinEnums.inc" 579 // The size of type WChar depend on platform so we abandon the support 580 // to them. 581 default: { 582 fprintf(stderr, "RSExportPrimitiveType::GetDataType : unsupported " 583 "built-in type '%s'\n.", T->getTypeClassName()); 584 break; 585 } 586 } 587 break; 588 } 589 case clang::Type::Record: { 590 // must be RS object type 591 return RSExportPrimitiveType::GetRSSpecificType(T); 592 } 593 default: { 594 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not " 595 "supported primitive type\n", T->getTypeClassName()); 596 break; 597 } 598 } 599 600 return DataTypeUnknown; 601} 602 603RSExportPrimitiveType 604*RSExportPrimitiveType::Create(RSContext *Context, 605 const clang::Type *T, 606 const llvm::StringRef &TypeName, 607 DataKind DK, 608 bool Normalized) { 609 DataType DT = GetDataType(T); 610 611 if ((DT == DataTypeUnknown) || TypeName.empty()) 612 return NULL; 613 else 614 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 615 DT, DK, Normalized); 616} 617 618RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 619 const clang::Type *T, 620 DataKind DK) { 621 llvm::StringRef TypeName; 622 if (RSExportType::NormalizeType(T, TypeName, NULL, NULL) && 623 IsPrimitiveType(T)) { 624 return Create(Context, T, TypeName, DK); 625 } else { 626 return NULL; 627 } 628} 629 630const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 631 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 632 633 if (isRSObjectType()) { 634 // struct { 635 // int *p; 636 // } __attribute__((packed, aligned(pointer_size))) 637 // 638 // which is 639 // 640 // <{ [1 x i32] }> in LLVM 641 // 642 if (RSObjectLLVMType == NULL) { 643 std::vector<const llvm::Type *> Elements; 644 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 645 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 646 } 647 return RSObjectLLVMType; 648 } 649 650 switch (mType) { 651 case DataTypeFloat32: { 652 return llvm::Type::getFloatTy(C); 653 break; 654 } 655 case DataTypeFloat64: { 656 return llvm::Type::getDoubleTy(C); 657 break; 658 } 659 case DataTypeBoolean: { 660 return llvm::Type::getInt1Ty(C); 661 break; 662 } 663 case DataTypeSigned8: 664 case DataTypeUnsigned8: { 665 return llvm::Type::getInt8Ty(C); 666 break; 667 } 668 case DataTypeSigned16: 669 case DataTypeUnsigned16: 670 case DataTypeUnsigned565: 671 case DataTypeUnsigned5551: 672 case DataTypeUnsigned4444: { 673 return llvm::Type::getInt16Ty(C); 674 break; 675 } 676 case DataTypeSigned32: 677 case DataTypeUnsigned32: { 678 return llvm::Type::getInt32Ty(C); 679 break; 680 } 681 case DataTypeSigned64: 682 case DataTypeUnsigned64: { 683 return llvm::Type::getInt64Ty(C); 684 break; 685 } 686 default: { 687 assert(false && "Unknown data type"); 688 } 689 } 690 691 return NULL; 692} 693 694union RSType *RSExportPrimitiveType::convertToSpecType() const { 695 llvm::OwningPtr<union RSType> ST(new union RSType); 696 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive); 697 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in 698 // slang_rs_type_spec.h 699 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType()); 700 return ST.take(); 701} 702 703bool RSExportPrimitiveType::equals(const RSExportable *E) const { 704 CHECK_PARENT_EQUALITY(RSExportType, E); 705 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 706} 707 708/**************************** RSExportPointerType ****************************/ 709 710const clang::Type *RSExportPointerType::IntegerType = NULL; 711 712RSExportPointerType 713*RSExportPointerType::Create(RSContext *Context, 714 const clang::PointerType *PT, 715 const llvm::StringRef &TypeName) { 716 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 717 const RSExportType *PointeeET; 718 719 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 720 PointeeET = RSExportType::Create(Context, PointeeType); 721 } else { 722 // Double or higher dimension of pointer, export as int* 723 assert(IntegerType != NULL && "Built-in integer type is not set"); 724 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType); 725 } 726 727 if (PointeeET == NULL) { 728 fprintf(stderr, "Failed to create type for pointee"); 729 return NULL; 730 } 731 732 return new RSExportPointerType(Context, TypeName, PointeeET); 733} 734 735const llvm::Type *RSExportPointerType::convertToLLVMType() const { 736 const llvm::Type *PointeeType = mPointeeType->getLLVMType(); 737 return llvm::PointerType::getUnqual(PointeeType); 738} 739 740union RSType *RSExportPointerType::convertToSpecType() const { 741 llvm::OwningPtr<union RSType> ST(new union RSType); 742 743 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer); 744 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType()); 745 746 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL) 747 return ST.take(); 748 else 749 return NULL; 750} 751 752bool RSExportPointerType::keep() { 753 if (!RSExportType::keep()) 754 return false; 755 const_cast<RSExportType*>(mPointeeType)->keep(); 756 return true; 757} 758 759bool RSExportPointerType::equals(const RSExportable *E) const { 760 CHECK_PARENT_EQUALITY(RSExportType, E); 761 return (static_cast<const RSExportPointerType*>(E) 762 ->getPointeeType()->equals(getPointeeType())); 763} 764 765/***************************** RSExportVectorType *****************************/ 766llvm::StringRef 767RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 768 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 769 770 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 771 return llvm::StringRef(); 772 773 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, 774 ElementType); 775 if ((EVT->getNumElements() < 1) || 776 (EVT->getNumElements() > 4)) 777 return llvm::StringRef(); 778 779 switch (BT->getKind()) { 780 // Compiler is smart enough to optimize following *big if branches* since 781 // they all become "constant comparison" after macro expansion 782#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 783 case builtin_type: { \ 784 const char *Name[] = { cname"2", cname"3", cname"4" }; \ 785 return Name[EVT->getNumElements() - 2]; \ 786 break; \ 787 } 788#include "RSClangBuiltinEnums.inc" 789 default: { 790 return llvm::StringRef(); 791 } 792 } 793} 794 795RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 796 const clang::ExtVectorType *EVT, 797 const llvm::StringRef &TypeName, 798 DataKind DK, 799 bool Normalized) { 800 assert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 801 802 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 803 RSExportPrimitiveType::DataType DT = 804 RSExportPrimitiveType::GetDataType(ElementType); 805 806 if (DT != RSExportPrimitiveType::DataTypeUnknown) 807 return new RSExportVectorType(Context, 808 TypeName, 809 DT, 810 DK, 811 Normalized, 812 EVT->getNumElements()); 813 else 814 fprintf(stderr, "RSExportVectorType::Create : unsupported base element " 815 "type\n"); 816 return NULL; 817} 818 819const llvm::Type *RSExportVectorType::convertToLLVMType() const { 820 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 821 return llvm::VectorType::get(ElementType, getNumElement()); 822} 823 824union RSType *RSExportVectorType::convertToSpecType() const { 825 llvm::OwningPtr<union RSType> ST(new union RSType); 826 827 RS_TYPE_SET_CLASS(ST, RS_TC_Vector); 828 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType()); 829 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement()); 830 831 return ST.take(); 832} 833 834bool RSExportVectorType::equals(const RSExportable *E) const { 835 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 836 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 837 == getNumElement()); 838} 839 840/***************************** RSExportMatrixType *****************************/ 841RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 842 const clang::RecordType *RT, 843 const llvm::StringRef &TypeName, 844 unsigned Dim) { 845 assert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 846 assert((Dim > 1) && "Invalid dimension of matrix"); 847 848 // Check whether the struct rs_matrix is in our expected form (but assume it's 849 // correct if we're not sure whether it's correct or not) 850 const clang::RecordDecl* RD = RT->getDecl(); 851 RD = RD->getDefinition(); 852 if (RD != NULL) { 853 // Find definition, perform further examination 854 if (RD->field_empty()) { 855 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: " 856 "must have 1 field for saving values", TypeName.data()); 857 return NULL; 858 } 859 860 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 861 const clang::FieldDecl *FD = *FIT; 862 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 863 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 864 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: " 865 "first field should be an array with constant size", 866 TypeName.data()); 867 return NULL; 868 } 869 const clang::ConstantArrayType *CAT = 870 static_cast<const clang::ConstantArrayType *>(FT); 871 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 872 if ((ElementType == NULL) || 873 (ElementType->getTypeClass() != clang::Type::Builtin) || 874 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() 875 != clang::BuiltinType::Float)) { 876 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: " 877 "first field should be a float array", TypeName.data()); 878 return NULL; 879 } 880 881 if (CAT->getSize() != Dim * Dim) { 882 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: " 883 "first field should be an array with size %d", 884 TypeName.data(), Dim * Dim); 885 return NULL; 886 } 887 888 FIT++; 889 if (FIT != RD->field_end()) { 890 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: " 891 "must have exactly 1 field", TypeName.data()); 892 return NULL; 893 } 894 } 895 896 return new RSExportMatrixType(Context, TypeName, Dim); 897} 898 899const llvm::Type *RSExportMatrixType::convertToLLVMType() const { 900 // Construct LLVM type: 901 // struct { 902 // float X[mDim * mDim]; 903 // } 904 905 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 906 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 907 mDim * mDim); 908 return llvm::StructType::get(C, X, NULL); 909} 910 911union RSType *RSExportMatrixType::convertToSpecType() const { 912 llvm::OwningPtr<union RSType> ST(new union RSType); 913 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix); 914 switch (getDim()) { 915 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break; 916 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break; 917 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break; 918 default: assert(false && "Matrix type with unsupported dimension."); 919 } 920 return ST.take(); 921} 922 923bool RSExportMatrixType::equals(const RSExportable *E) const { 924 CHECK_PARENT_EQUALITY(RSExportType, E); 925 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 926} 927 928/************************* RSExportConstantArrayType *************************/ 929RSExportConstantArrayType 930*RSExportConstantArrayType::Create(RSContext *Context, 931 const clang::ConstantArrayType *CAT) { 932 assert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 933 934 assert((CAT->getSize().getActiveBits() < 32) && "array too large"); 935 936 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 937 assert((Size > 0) && "Constant array should have size greater than 0"); 938 939 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 940 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 941 942 if (ElementET == NULL) { 943 fprintf(stderr, "RSExportConstantArrayType::Create : failed to create " 944 "RSExportType for array element.\n"); 945 return NULL; 946 } 947 948 return new RSExportConstantArrayType(Context, 949 ElementET, 950 Size); 951} 952 953const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 954 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 955} 956 957union RSType *RSExportConstantArrayType::convertToSpecType() const { 958 llvm::OwningPtr<union RSType> ST(new union RSType); 959 960 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray); 961 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE( 962 ST, getElementType()->getSpecType()); 963 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize()); 964 965 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL) 966 return ST.take(); 967 else 968 return NULL; 969} 970 971bool RSExportConstantArrayType::keep() { 972 if (!RSExportType::keep()) 973 return false; 974 const_cast<RSExportType*>(mElementType)->keep(); 975 return true; 976} 977 978bool RSExportConstantArrayType::equals(const RSExportable *E) const { 979 CHECK_PARENT_EQUALITY(RSExportType, E); 980 const RSExportConstantArrayType *RHS = 981 static_cast<const RSExportConstantArrayType*>(E); 982 return ((getSize() == RHS->getSize()) && 983 (getElementType()->equals(RHS->getElementType()))); 984} 985 986/**************************** RSExportRecordType ****************************/ 987RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 988 const clang::RecordType *RT, 989 const llvm::StringRef &TypeName, 990 bool mIsArtificial) { 991 assert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 992 993 const clang::RecordDecl *RD = RT->getDecl(); 994 assert(RD->isStruct()); 995 996 RD = RD->getDefinition(); 997 if (RD == NULL) { 998 // TODO(zonr): warn that actual struct definition isn't declared in this 999 // moudle. 1000 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined " 1001 "in this module."); 1002 return NULL; 1003 } 1004 1005 // Struct layout construct by clang. We rely on this for obtaining the 1006 // alloc size of a struct and offset of every field in that struct. 1007 const clang::ASTRecordLayout *RL = 1008 &Context->getASTContext().getASTRecordLayout(RD); 1009 assert((RL != NULL) && "Failed to retrieve the struct layout from Clang."); 1010 1011 RSExportRecordType *ERT = 1012 new RSExportRecordType(Context, 1013 TypeName, 1014 RD->hasAttr<clang::PackedAttr>(), 1015 mIsArtificial, 1016 (RL->getSize() >> 3)); 1017 unsigned int Index = 0; 1018 1019 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1020 FE = RD->field_end(); 1021 FI != FE; 1022 FI++, Index++) { 1023#define FAILED_CREATE_FIELD(err) do { \ 1024 if (*err) \ 1025 fprintf(stderr, \ 1026 "RSExportRecordType::Create : failed to create field (%s)\n", \ 1027 err); \ 1028 delete ERT; \ 1029 return NULL; \ 1030 } while (false) 1031 1032 // FIXME: All fields should be primitive type 1033 assert((*FI)->getKind() == clang::Decl::Field); 1034 clang::FieldDecl *FD = *FI; 1035 1036 // We don't support bit field 1037 // 1038 // TODO(zonr): allow bitfield with size 8, 16, 32 1039 if (FD->isBitField()) 1040 FAILED_CREATE_FIELD("bit field is not supported"); 1041 1042 // Type 1043 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1044 1045 if (ET != NULL) 1046 ERT->mFields.push_back( 1047 new Field(ET, FD->getName(), ERT, 1048 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1049 else 1050 FAILED_CREATE_FIELD(FD->getName().str().c_str()); 1051#undef FAILED_CREATE_FIELD 1052 } 1053 1054 return ERT; 1055} 1056 1057const llvm::Type *RSExportRecordType::convertToLLVMType() const { 1058 // Create an opaque type since struct may reference itself recursively. 1059 llvm::PATypeHolder ResultHolder = 1060 llvm::OpaqueType::get(getRSContext()->getLLVMContext()); 1061 setAbstractLLVMType(ResultHolder.get()); 1062 1063 std::vector<const llvm::Type*> FieldTypes; 1064 1065 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1066 FI != FE; 1067 FI++) { 1068 const Field *F = *FI; 1069 const RSExportType *FET = F->getType(); 1070 1071 FieldTypes.push_back(FET->getLLVMType()); 1072 } 1073 1074 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1075 FieldTypes, 1076 mIsPacked); 1077 if (ST != NULL) 1078 static_cast<llvm::OpaqueType*>(ResultHolder.get()) 1079 ->refineAbstractTypeTo(ST); 1080 else 1081 return NULL; 1082 return ResultHolder.get(); 1083} 1084 1085union RSType *RSExportRecordType::convertToSpecType() const { 1086 unsigned NumFields = getFields().size(); 1087 unsigned AllocSize = sizeof(union RSType) + 1088 sizeof(struct RSRecordField) * NumFields; 1089 llvm::OwningPtr<union RSType> ST( 1090 reinterpret_cast<union RSType*>(operator new(AllocSize))); 1091 1092 ::memset(ST.get(), 0, AllocSize); 1093 1094 RS_TYPE_SET_CLASS(ST, RS_TC_Record); 1095 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str()); 1096 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields); 1097 1098 setSpecTypeTemporarily(ST.get()); 1099 1100 unsigned FieldIdx = 0; 1101 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1102 FI != FE; 1103 FI++, FieldIdx++) { 1104 const Field *F = *FI; 1105 1106 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str()); 1107 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType()); 1108 1109 enum RSDataKind DK = RS_DK_User; 1110 if ((F->getType()->getClass() == ExportClassPrimitive) || 1111 (F->getType()->getClass() == ExportClassVector)) { 1112 const RSExportPrimitiveType *EPT = 1113 static_cast<const RSExportPrimitiveType*>(F->getType()); 1114 // enum RSExportPrimitiveType::DataKind is synced with enum RSDataKind in 1115 // slang_rs_type_spec.h 1116 DK = static_cast<enum RSDataKind>(EPT->getKind()); 1117 } 1118 RS_RECORD_TYPE_SET_FIELD_DATA_KIND(ST, FieldIdx, DK); 1119 } 1120 1121 // TODO(slang): Check whether all fields were created normally. 1122 1123 return ST.take(); 1124} 1125 1126bool RSExportRecordType::keep() { 1127 if (!RSExportType::keep()) 1128 return false; 1129 for (std::list<const Field*>::iterator I = mFields.begin(), 1130 E = mFields.end(); 1131 I != E; 1132 I++) { 1133 const_cast<RSExportType*>((*I)->getType())->keep(); 1134 } 1135 return true; 1136} 1137 1138bool RSExportRecordType::equals(const RSExportable *E) const { 1139 CHECK_PARENT_EQUALITY(RSExportType, E); 1140 1141 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1142 1143 if (ERT->getFields().size() != getFields().size()) 1144 return false; 1145 1146 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1147 1148 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1149 if (!(*AI)->getType()->equals((*BI)->getType())) 1150 return false; 1151 AI++; 1152 BI++; 1153 } 1154 1155 return true; 1156} 1157 1158} // namespace slang 1159