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