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