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