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