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