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