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