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