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