slang_rs_export_type.cpp revision 6315f76e3cc6ff2d012d1183a0b030d4ff0dc808
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: { // User-defined types 279 ET = RSExportRecordType::Create(Context, 280 T->getAsStructureType(), 281 TypeName); 282 break; 283 } 284 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 285 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 286 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 287 const clang::RecordType *RT = 288 static_cast<const clang::RecordType*> (T); 289 const clang::RecordDecl *RD = RT->getDecl(); 290 RD = RD->getDefinition(); 291 clang::RecordDecl::field_iterator FI = RD->field_begin(); 292 clang::FieldDecl *FD = *FI; 293 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 294 ET = RSExportConstantArrayType::Create( 295 Context, 296 static_cast<const clang::ConstantArrayType*> (FT), 297 TypeName); 298 break; 299 } 300 default: { 301 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 302 break; 303 } 304 } 305 break; 306 } 307 case clang::Type::Builtin: { 308 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 309 break; 310 } 311 case clang::Type::Pointer: { 312 ET = RSExportPointerType::Create(Context, 313 UNSAFE_CAST_TYPE(clang::PointerType, T), 314 TypeName); 315 // Free the name (allocated in RSExportType::GetTypeName) 316 delete [] TypeName.data(); 317 break; 318 } 319 case clang::Type::ConstantArray: { 320 ET = RSExportConstantArrayType::Create( 321 Context, 322 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T), 323 TypeName); 324 break; 325 } 326 case clang::Type::ExtVector: { 327 ET = RSExportVectorType::Create(Context, 328 UNSAFE_CAST_TYPE(clang::ExtVectorType, T), 329 TypeName); 330 break; 331 } 332 default: { 333 // TODO(zonr): warn that type is not exportable. 334 fprintf(stderr, 335 "RSExportType::Create : type '%s' is not exportable\n", 336 T->getTypeClassName()); 337 break; 338 } 339 } 340 341 return ET; 342} 343 344RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 345 llvm::StringRef TypeName; 346 if (NormalizeType(T, TypeName)) 347 return Create(Context, T, TypeName); 348 else 349 return NULL; 350} 351 352RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 353 const clang::VarDecl *VD) { 354 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 355} 356 357size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 358 return ET->getRSContext()->getTargetData()->getTypeStoreSize( 359 ET->getLLVMType()); 360} 361 362size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 363 if (ET->getClass() == RSExportType::ExportClassRecord) 364 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 365 else 366 return ET->getRSContext()->getTargetData()->getTypeAllocSize( 367 ET->getLLVMType()); 368} 369 370RSExportType::RSExportType(RSContext *Context, const llvm::StringRef &Name) 371 : mContext(Context), 372 // Make a copy on Name since data of @Name which is stored in ASTContext 373 // will be destroyed later 374 mName(Name.data(), Name.size()), 375 mLLVMType(NULL) { 376 // TODO(zonr): Need to check whether the insertion is successful or not. 377 Context->insertExportType(Name, this); 378 return; 379} 380 381/************************** RSExportPrimitiveType **************************/ 382RSExportPrimitiveType::RSObjectTypeMapTy 383*RSExportPrimitiveType::RSObjectTypeMap = NULL; 384 385llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 386 387bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 388 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 389 return true; 390 else 391 return false; 392} 393 394RSExportPrimitiveType::DataType 395RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef &TypeName) { 396 if (TypeName.empty()) 397 return DataTypeUnknown; 398 399 if (RSObjectTypeMap == NULL) { 400 RSObjectTypeMap = new RSObjectTypeMapTy(16); 401 402#define USE_ELEMENT_DATA_TYPE 403#define DEF_RS_OBJECT_TYPE(type, name) \ 404 RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type)); 405#include "slang_rs_export_element_support.inc" 406 } 407 408 RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName); 409 if (I == RSObjectTypeMap->end()) 410 return DataTypeUnknown; 411 else 412 return I->getValue(); 413} 414 415RSExportPrimitiveType::DataType 416RSExportPrimitiveType::GetRSObjectType(const clang::Type *T) { 417 T = GET_CANONICAL_TYPE(T); 418 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 419 return DataTypeUnknown; 420 421 return GetRSObjectType( RSExportType::GetTypeName(T) ); 422} 423 424const size_t 425RSExportPrimitiveType::SizeOfDataTypeInBits[ 426 RSExportPrimitiveType::DataTypeMax + 1] = { 427 16, // DataTypeFloat16 428 32, // DataTypeFloat32 429 64, // DataTypeFloat64 430 8, // DataTypeSigned8 431 16, // DataTypeSigned16 432 32, // DataTypeSigned32 433 64, // DataTypeSigned64 434 8, // DataTypeUnsigned8 435 16, // DataTypeUnsigned16 436 32, // DataTypeUnsigned32 437 64, // DataTypeUnSigned64 438 1, // DataTypeBoolean 439 440 16, // DataTypeUnsigned565 441 16, // DataTypeUnsigned5551 442 16, // DataTypeUnsigned4444 443 444 128, // DataTypeRSMatrix2x2 445 288, // DataTypeRSMatrix3x3 446 512, // DataTypeRSMatrix4x4 447 448 32, // DataTypeRSElement 449 32, // DataTypeRSType 450 32, // DataTypeRSAllocation 451 32, // DataTypeRSSampler 452 32, // DataTypeRSScript 453 32, // DataTypeRSMesh 454 32, // DataTypeRSProgramFragment 455 32, // DataTypeRSProgramVertex 456 32, // DataTypeRSProgramRaster 457 32, // DataTypeRSProgramStore 458 32, // DataTypeRSFont 459 0 460}; 461 462size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 463 assert(((EPT->getType() >= DataTypeFloat32) && 464 (EPT->getType() < DataTypeMax)) && 465 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 466 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ]; 467} 468 469RSExportPrimitiveType::DataType 470RSExportPrimitiveType::GetDataType(const clang::Type *T) { 471 if (T == NULL) 472 return DataTypeUnknown; 473 474 switch (T->getTypeClass()) { 475 case clang::Type::Builtin: { 476 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T); 477 switch (BT->getKind()) { 478#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \ 479 case builtin_type: { \ 480 return type; \ 481 break; \ 482 } 483#include "slang_rs_export_type_support.inc" 484 485 // The size of types Long, ULong and WChar depend on platform so we 486 // abandon the support to them. Type of its size exceeds 32 bits (e.g. 487 // int64_t, double, etc.): no support 488 489 default: { 490 // TODO(zonr): warn that the type is unsupported 491 fprintf(stderr, "RSExportPrimitiveType::GetDataType : built-in type " 492 "has no corresponding data type for built-in type"); 493 break; 494 } 495 } 496 break; 497 } 498 499 case clang::Type::Record: { 500 // must be RS object type 501 return RSExportPrimitiveType::GetRSObjectType(T); 502 break; 503 } 504 505 default: { 506 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not " 507 "supported primitive type", T->getTypeClassName()); 508 break; 509 } 510 } 511 512 return DataTypeUnknown; 513} 514 515RSExportPrimitiveType 516*RSExportPrimitiveType::Create(RSContext *Context, 517 const clang::Type *T, 518 const llvm::StringRef &TypeName, 519 DataKind DK, 520 bool Normalized) { 521 DataType DT = GetDataType(T); 522 523 if ((DT == DataTypeUnknown) || TypeName.empty()) 524 return NULL; 525 else 526 return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized); 527} 528 529RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 530 const clang::Type *T, 531 DataKind DK) { 532 llvm::StringRef TypeName; 533 if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T)) 534 return Create(Context, T, TypeName, DK); 535 else 536 return NULL; 537} 538 539RSExportType::ExportClass RSExportPrimitiveType::getClass() const { 540 return RSExportType::ExportClassPrimitive; 541} 542 543const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 544 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 545 546 if (isRSObjectType()) { 547 // struct { 548 // int *p; 549 // } __attribute__((packed, aligned(pointer_size))) 550 // 551 // which is 552 // 553 // <{ [1 x i32] }> in LLVM 554 // 555 if (RSObjectLLVMType == NULL) { 556 std::vector<const llvm::Type *> Elements; 557 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 558 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 559 } 560 return RSObjectLLVMType; 561 } 562 563 switch (mType) { 564 case DataTypeFloat32: { 565 return llvm::Type::getFloatTy(C); 566 break; 567 } 568 case DataTypeFloat64: { 569 return llvm::Type::getDoubleTy(C); 570 break; 571 } 572 case DataTypeBoolean: { 573 return llvm::Type::getInt1Ty(C); 574 break; 575 } 576 case DataTypeSigned8: 577 case DataTypeUnsigned8: { 578 return llvm::Type::getInt8Ty(C); 579 break; 580 } 581 case DataTypeSigned16: 582 case DataTypeUnsigned16: 583 case DataTypeUnsigned565: 584 case DataTypeUnsigned5551: 585 case DataTypeUnsigned4444: { 586 return llvm::Type::getInt16Ty(C); 587 break; 588 } 589 case DataTypeSigned32: 590 case DataTypeUnsigned32: { 591 return llvm::Type::getInt32Ty(C); 592 break; 593 } 594 case DataTypeSigned64: { 595 // case DataTypeUnsigned64: 596 return llvm::Type::getInt64Ty(C); 597 break; 598 } 599 default: { 600 assert(false && "Unknown data type"); 601 } 602 } 603 604 return NULL; 605} 606 607/**************************** RSExportPointerType ****************************/ 608 609const clang::Type *RSExportPointerType::IntegerType = NULL; 610 611RSExportPointerType 612*RSExportPointerType::Create(RSContext *Context, 613 const clang::PointerType *PT, 614 const llvm::StringRef &TypeName) { 615 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 616 const RSExportType *PointeeET; 617 618 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 619 PointeeET = RSExportType::Create(Context, PointeeType); 620 } else { 621 // Double or higher dimension of pointer, export as int* 622 assert(IntegerType != NULL && "Built-in integer type is not set"); 623 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType); 624 } 625 626 if (PointeeET == NULL) { 627 fprintf(stderr, "Failed to create type for pointee"); 628 return NULL; 629 } 630 631 return new RSExportPointerType(Context, TypeName, PointeeET); 632} 633 634RSExportType::ExportClass RSExportPointerType::getClass() const { 635 return RSExportType::ExportClassPointer; 636} 637 638const llvm::Type *RSExportPointerType::convertToLLVMType() const { 639 const llvm::Type *PointeeType = mPointeeType->getLLVMType(); 640 return llvm::PointerType::getUnqual(PointeeType); 641} 642 643/************************* RSExportConstantArrayType *************************/ 644llvm::StringRef 645RSExportConstantArrayType::GetTypeName(const clang::ConstantArrayType *CT) { 646 llvm::APInt i = CT->getSize(); 647 if (i == 4) { 648 return llvm::StringRef("rs_matrix2x2"); 649 } else if (i == 9) { 650 return llvm::StringRef("rs_matrix3x3"); 651 } else if (i == 16) { 652 return llvm::StringRef("rs_matrix4x4"); 653 } 654 return llvm::StringRef(); 655} 656 657RSExportConstantArrayType 658*RSExportConstantArrayType::Create(RSContext *Context, 659 const clang::ConstantArrayType *CT, 660 const llvm::StringRef &TypeName, 661 DataKind DK, 662 bool Normalized) { 663 assert(CT != NULL && CT->getTypeClass() == clang::Type::ConstantArray); 664 665 int64_t Size = CT->getSize().getSExtValue(); 666 RSExportPrimitiveType::DataType DT; 667 if (Size == 4) { 668 DT = RSExportPrimitiveType::DataTypeRSMatrix2x2; 669 } else if (Size == 9) { 670 DT = RSExportPrimitiveType::DataTypeRSMatrix3x3; 671 } else if (Size == 16) { 672 DT = RSExportPrimitiveType::DataTypeRSMatrix4x4; 673 } else { 674 fprintf(stderr, "RSExportConstantArrayType::Create : unsupported base " 675 "element type\n"); 676 return NULL; 677 } 678 679 return new RSExportConstantArrayType(Context, 680 TypeName, 681 DT, 682 DK, 683 Normalized, 684 Size); 685} 686 687RSExportType::ExportClass RSExportConstantArrayType::getClass() const { 688 return RSExportType::ExportClassConstantArray; 689} 690 691const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 692 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 693 const llvm::Type *typ; 694 switch (getType()) { 695 case DataTypeFloat32: 696 case DataTypeRSMatrix2x2: 697 case DataTypeRSMatrix3x3: 698 case DataTypeRSMatrix4x4: { 699 typ = llvm::Type::getFloatTy(C); 700 break; 701 } 702 case DataTypeFloat64: { 703 typ = llvm::Type::getDoubleTy(C); 704 break; 705 } 706 case DataTypeBoolean: { 707 typ = llvm::Type::getInt1Ty(C); 708 break; 709 } 710 case DataTypeSigned8: 711 case DataTypeUnsigned8: { 712 typ = llvm::Type::getInt8Ty(C); 713 break; 714 } 715 case DataTypeSigned16: 716 case DataTypeUnsigned16: 717 case DataTypeUnsigned565: 718 case DataTypeUnsigned5551: 719 case DataTypeUnsigned4444: { 720 typ = llvm::Type::getInt16Ty(C); 721 break; 722 } 723 case DataTypeSigned32: 724 case DataTypeUnsigned32: { 725 typ = llvm::Type::getInt32Ty(C); 726 break; 727 } 728 case DataTypeSigned64: { 729 //case DataTypeUnsigned64: 730 typ = llvm::Type::getInt64Ty(C); 731 break; 732 } 733 default: { 734 assert(false && "Unknown data type"); 735 break; 736 } 737 } 738 return llvm::ArrayType::get(typ, mNumElement); 739} 740 741/***************************** RSExportVectorType *****************************/ 742const char* RSExportVectorType::VectorTypeNameStore[][3] = { 743 /* 0 */ { "char2", "char3", "char4" }, 744 /* 1 */ { "uchar2", "uchar3", "uchar4" }, 745 /* 2 */ { "short2", "short3", "short4" }, 746 /* 3 */ { "ushort2", "ushort3", "ushort4" }, 747 /* 4 */ { "int2", "int3", "int4" }, 748 /* 5 */ { "uint2", "uint3", "uint4" }, 749 /* 6 */ { "float2", "float3", "float4" }, 750 /* 7 */ { "double2", "double3", "double4" }, 751 /* 8 */ { "long2", "long3", "long4" }, 752}; 753 754llvm::StringRef 755RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 756 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 757 758 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 759 return llvm::StringRef(); 760 761 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, 762 ElementType); 763 const char **BaseElement = NULL; 764 765 switch (BT->getKind()) { 766 // Compiler is smart enough to optimize following *big if branches* since 767 // they all become "constant comparison" after macro expansion 768#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \ 769 case builtin_type: { \ 770 if (type == RSExportPrimitiveType::DataTypeSigned8) \ 771 BaseElement = VectorTypeNameStore[0]; \ 772 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \ 773 BaseElement = VectorTypeNameStore[1]; \ 774 else if (type == RSExportPrimitiveType::DataTypeSigned16) \ 775 BaseElement = VectorTypeNameStore[2]; \ 776 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \ 777 BaseElement = VectorTypeNameStore[3]; \ 778 else if (type == RSExportPrimitiveType::DataTypeSigned32) \ 779 BaseElement = VectorTypeNameStore[4]; \ 780 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \ 781 BaseElement = VectorTypeNameStore[5]; \ 782 else if (type == RSExportPrimitiveType::DataTypeFloat32) \ 783 BaseElement = VectorTypeNameStore[6]; \ 784 else if (type == RSExportPrimitiveType::DataTypeFloat64) \ 785 BaseElement = VectorTypeNameStore[7]; \ 786 else if (type == RSExportPrimitiveType::DataTypeSigned64) \ 787 BaseElement = VectorTypeNameStore[8]; \ 788 else if (type == RSExportPrimitiveType::DataTypeBoolean) \ 789 BaseElement = VectorTypeNameStore[0]; \ 790 break; \ 791 } 792#include "slang_rs_export_type_support.inc" 793 default: { 794 return llvm::StringRef(); 795 } 796 } 797 798 if ((BaseElement != NULL) && 799 (EVT->getNumElements() > 1) && 800 (EVT->getNumElements() <= 4)) 801 return BaseElement[EVT->getNumElements() - 2]; 802 else 803 return llvm::StringRef(); 804} 805 806RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 807 const clang::ExtVectorType *EVT, 808 const llvm::StringRef &TypeName, 809 DataKind DK, 810 bool Normalized) { 811 assert(EVT != NULL && EVT->getTypeClass() == Type::ExtVector); 812 813 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 814 RSExportPrimitiveType::DataType DT = 815 RSExportPrimitiveType::GetDataType(ElementType); 816 817 if (DT != RSExportPrimitiveType::DataTypeUnknown) 818 return new RSExportVectorType(Context, 819 TypeName, 820 DT, 821 DK, 822 Normalized, 823 EVT->getNumElements()); 824 else 825 fprintf(stderr, "RSExportVectorType::Create : unsupported base element " 826 "type\n"); 827 return NULL; 828} 829 830RSExportType::ExportClass RSExportVectorType::getClass() const { 831 return RSExportType::ExportClassVector; 832} 833 834const llvm::Type *RSExportVectorType::convertToLLVMType() const { 835 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 836 return llvm::VectorType::get(ElementType, getNumElement()); 837} 838 839/**************************** RSExportRecordType ****************************/ 840RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 841 const clang::RecordType *RT, 842 const llvm::StringRef &TypeName, 843 bool mIsArtificial) { 844 assert(RT != NULL && RT->getTypeClass() == Type::Record); 845 846 const clang::RecordDecl *RD = RT->getDecl(); 847 assert(RD->isStruct()); 848 849 RD = RD->getDefinition(); 850 if (RD == NULL) { 851 // TODO(zonr): warn that actual struct definition isn't declared in this 852 // moudle. 853 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined " 854 "in this module."); 855 return NULL; 856 } 857 858 RSExportRecordType *ERT = new RSExportRecordType(Context, 859 TypeName, 860 RD-> 861 hasAttr<clang::PackedAttr>(), 862 mIsArtificial); 863 unsigned int Index = 0; 864 865 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 866 FE = RD->field_end(); 867 FI != FE; 868 FI++, Index++) { 869#define FAILED_CREATE_FIELD(err) do { \ 870 if (*err) \ 871 fprintf(stderr, \ 872 "RSExportRecordType::Create : failed to create field (%s)\n", \ 873 err); \ 874 delete ERT; \ 875 return NULL; \ 876 } while (false) 877 878 // FIXME: All fields should be primitive type 879 assert((*FI)->getKind() == clang::Decl::Field); 880 clang::FieldDecl *FD = *FI; 881 882 // We don't support bit field 883 // 884 // TODO(zonr): allow bitfield with size 8, 16, 32 885 if (FD->isBitField()) 886 FAILED_CREATE_FIELD("bit field is not supported"); 887 888 // Type 889 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 890 891 if (ET != NULL) 892 ERT->mFields.push_back(new Field(ET, FD->getName(), ERT, Index)); 893 else 894 FAILED_CREATE_FIELD(FD->getName().str().c_str()); 895#undef FAILED_CREATE_FIELD 896 } 897 898 const clang::ASTRecordLayout &ASTRL = 899 Context->getASTContext()->getASTRecordLayout(RD); 900 ERT->AllocSize = 901 (ASTRL.getSize() > ASTRL.getDataSize()) ? 902 (ASTRL.getSize() >> 3) : 903 (ASTRL.getDataSize() >> 3); 904 905 return ERT; 906} 907 908RSExportType::ExportClass RSExportRecordType::getClass() const { 909 return RSExportType::ExportClassRecord; 910} 911 912const llvm::Type *RSExportRecordType::convertToLLVMType() const { 913 std::vector<const llvm::Type*> FieldTypes; 914 915 for (const_field_iterator FI = fields_begin(), 916 FE = fields_end(); 917 FI != FE; 918 FI++) { 919 const Field *F = *FI; 920 const RSExportType *FET = F->getType(); 921 922 FieldTypes.push_back(FET->getLLVMType()); 923 } 924 925 return llvm::StructType::get(getRSContext()->getLLVMContext(), 926 FieldTypes, 927 mIsPacked); 928} 929 930/************************* RSExportRecordType::Field *************************/ 931size_t RSExportRecordType::Field::getOffsetInParent() const { 932 // Struct layout obtains below will be cached by LLVM 933 const llvm::StructLayout *SL = 934 mParent->getRSContext()->getTargetData()->getStructLayout( 935 static_cast<const llvm::StructType*>(mParent->getLLVMType())); 936 return SL->getElementOffset(mIndex); 937} 938