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