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