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