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