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