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