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