blob: c843856562ebe540a607dc90943f795ee9c8367c [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
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070013#include "clang/AST/RecordLayout.h"
14
Shih-wei Liao462aefd2010-06-04 15:32:04 -070015namespace 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
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -070021 if((T = RSExportType::TypeExportable(T, SPS)) == NULL)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070022 /* 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"; \
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -070065 else if(type == RSExportPrimitiveType::DataTypeBool) return "bool"; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -070066 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()) {
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -070080 if(RD->getTypedefForAnonDecl() != NULL)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070081 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;
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700135
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700136 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 */
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700166 if(RD->hasFlexibleArrayMember() || RD->hasObjectMember())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700167 return NULL;
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700168
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700169 /* 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
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700180 if(!TypeExportable(FT, SPS))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700181 /* 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) {
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700223 /*
224 * Lookup the context to see whether the type was processed before.
225 * Newly create RSExportType will insert into context in RSExportType::RSExportType()
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700226 */
227 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
228
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700229 if(ETI != Context->export_types_end())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700230 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}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700263
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700264RSExportType* 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) {
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -0700281 if(ET->getClass() == RSExportType::ExportClassRecord)
282 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
283 else
284 return ET->getRSContext()->getTargetData()->getTypeAllocSize(ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700285}
286
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700287RSExportType::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 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290 mLLVMType(NULL)
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700291{
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700292 /* TODO: need to check whether the insertion is successful or not */
293 Context->insertExportType(Name, this);
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700294 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700295}
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
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700336const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[RSExportPrimitiveType::DataTypeMax + 1] = {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700337 0,
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700338 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 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700349
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700350 16, /* DataTypeUnsigned565 */
351 16, /* DataTypeUnsigned5551 */
352 16, /* DataTypeUnsigned4444 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700353
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700354 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 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700367 0
368};
369
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700370size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType* EPT) {
371 assert(((EPT->getType() >= DataTypeFloat32) && (EPT->getType() < DataTypeMax)) && "RSExportPrimitiveType::GetSizeInBits : unknown data type");
372 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700373}
374
375RSExportPrimitiveType::DataType RSExportPrimitiveType::GetDataType(const Type* T) {
376 if(T == NULL)
377 return DataTypeUnknown;
378
379 switch(T->getTypeClass()) {
380 case Type::Builtin:
381 {
382 const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
383 switch(BT->getKind()) {
384#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
385 case builtin_type: \
386 return type; \
387 break;
388#include "slang_rs_export_type_support.inc"
389
390 /* The size of types Long, ULong and WChar depend on platform so we abandon the support to them */
391 /* Type of its size exceeds 32 bits (e.g. int64_t, double, etc.) does not support */
392
393 default:
394 /* TODO: warning the user: unsupported type */
395 printf("RSExportPrimitiveType::GetDataType : built-in type has no corresponding data type for built-in type");
396 break;
397 }
398 }
399 break;
400
401 case Type::Record:
402 /* must be RS object type */
403 return RSExportPrimitiveType::GetRSObjectType(T);
404 break;
405
406 default:
407 printf("RSExportPrimitiveType::GetDataType : type '%s' is not supported primitive type", T->getTypeClassName());
408 break;
409 }
410
411 return DataTypeUnknown;
412}
413
414RSExportPrimitiveType* RSExportPrimitiveType::Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
415 DataType DT = GetDataType(T);
416
417 if((DT == DataTypeUnknown) || TypeName.empty())
418 return NULL;
419 else
420 return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
421}
422
423RSExportPrimitiveType* RSExportPrimitiveType::Create(RSContext* Context, const Type* T, DataKind DK) {
424 llvm::StringRef TypeName;
425 if(RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
426 return Create(Context, T, TypeName, DK);
427 else
428 return NULL;
429}
430
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700431RSExportType::ExportClass RSExportPrimitiveType::getClass() const {
432 return RSExportType::ExportClassPrimitive;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700433}
434
435const llvm::Type* RSExportPrimitiveType::convertToLLVMType() const {
436 llvm::LLVMContext& C = getRSContext()->getLLVMContext();
437
438 if(isRSObjectType()) {
439 /* struct { int* p; } __attribute__((packed, aligned(pointer_size))) which is <{ [1 x i32] }> in LLVM */
440 if(RSObjectLLVMType == NULL) {
441 std::vector<const llvm::Type*> Elements;
442 Elements.push_back( llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1) );
443 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
444 }
445 return RSObjectLLVMType;
446 }
447
448 switch(mType) {
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700449 case DataTypeFloat32:
450 return llvm::Type::getFloatTy(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700451 break;
452
453 case DataTypeSigned8:
454 case DataTypeUnsigned8:
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700455 return llvm::Type::getInt8Ty(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700456 break;
457
458 case DataTypeSigned16:
459 case DataTypeUnsigned16:
460 case DataTypeUnsigned565:
461 case DataTypeUnsigned5551:
462 case DataTypeUnsigned4444:
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700463 return llvm::Type::getInt16Ty(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700464 break;
465
466 case DataTypeSigned32:
467 case DataTypeUnsigned32:
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700468 return llvm::Type::getInt32Ty(C);
469 break;
470
471 case DataTypeBool:
472 return llvm::Type::getInt1Ty(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700473 break;
474
475 default:
476 assert(false && "Unknown data type");
477 break;
478 }
479
480 return NULL;
481}
482
483/****************************** RSExportPointerType ******************************/
484
485const Type* RSExportPointerType::IntegerType = NULL;
486
487RSExportPointerType* RSExportPointerType::Create(RSContext* Context, const PointerType* PT, const llvm::StringRef& TypeName) {
488 const Type* PointeeType = GET_POINTEE_TYPE(PT);
489 const RSExportType* PointeeET;
490
491 if(PointeeType->getTypeClass() != Type::Pointer) {
492 PointeeET = RSExportType::Create(Context, PointeeType);
493 } else {
494 /* Double or higher dimension of pointer, export as int* */
495 assert(IntegerType != NULL && "Built-in integer type is not set");
496 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
497 }
498
499 if(PointeeET == NULL) {
500 printf("Failed to create type for pointee");
501 return NULL;
502 }
503
504 return new RSExportPointerType(Context, TypeName, PointeeET);
505}
506
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700507RSExportType::ExportClass RSExportPointerType::getClass() const {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700508 return RSExportType::ExportClassPointer;
509}
510
511const llvm::Type* RSExportPointerType::convertToLLVMType() const {
512 const llvm::Type* PointeeType = mPointeeType->getLLVMType();
513 return llvm::PointerType::getUnqual(PointeeType);
514}
515
516/****************************** RSExportVectorType ******************************/
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700517const char* RSExportVectorType::VectorTypeNameStore[][3] = {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700518 /* 0 */ { "char2", "char3", "char4" },
519 /* 1 */ { "uchar2", "uchar3", "uchar4" },
520 /* 2 */ { "short2", "short3", "short4" },
521 /* 3 */ { "ushort2", "ushort3", "ushort4" },
522 /* 4 */ { "int2", "int3", "int4" },
523 /* 5 */ { "uint2", "uint3", "uint4" },
524 /* 6 */ { "float2", "float3", "float4" },
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700525};
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700526
527llvm::StringRef RSExportVectorType::GetTypeName(const ExtVectorType* EVT) {
528 const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
529
530 if((ElementType->getTypeClass() != Type::Builtin))
531 return llvm::StringRef();
532
533 const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, ElementType);
534 const char** BaseElement = NULL;
535
536 switch(BT->getKind()) {
537#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
538 case builtin_type: \
539 /* Compiler is smart enough to optimize following *big if branches* since they all become "constant comparison" after macro expansion */ \
540 if(type == RSExportPrimitiveType::DataTypeSigned8) BaseElement = VectorTypeNameStore[0]; \
541 else if(type == RSExportPrimitiveType::DataTypeUnsigned8) BaseElement = VectorTypeNameStore[1]; \
542 else if(type == RSExportPrimitiveType::DataTypeSigned16) BaseElement = VectorTypeNameStore[2]; \
543 else if(type == RSExportPrimitiveType::DataTypeUnsigned16) BaseElement = VectorTypeNameStore[3]; \
544 else if(type == RSExportPrimitiveType::DataTypeSigned32) BaseElement = VectorTypeNameStore[4]; \
545 else if(type == RSExportPrimitiveType::DataTypeUnsigned32) BaseElement = VectorTypeNameStore[5]; \
546 else if(type == RSExportPrimitiveType::DataTypeFloat32) BaseElement = VectorTypeNameStore[6]; \
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700547 else if(type == RSExportPrimitiveType::DataTypeBool) BaseElement = VectorTypeNameStore[0]; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700548 break;
549#include "slang_rs_export_type_support.inc"
550
551 default: return llvm::StringRef(); break;
552 }
553
554 if((BaseElement != NULL) && (EVT->getNumElements() > 1) && (EVT->getNumElements() <= 4))
555 return BaseElement[EVT->getNumElements() - 2];
556 else
557 return llvm::StringRef();
558}
559
560RSExportVectorType* RSExportVectorType::Create(RSContext* Context, const ExtVectorType* EVT, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
561 assert(EVT != NULL && EVT->getTypeClass() == Type::ExtVector);
562
563 const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
564 RSExportPrimitiveType::DataType DT = RSExportPrimitiveType::GetDataType(ElementType);
565
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700566 if(DT != RSExportPrimitiveType::DataTypeUnknown)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700567 return new RSExportVectorType(Context, TypeName, DT, DK, Normalized, EVT->getNumElements());
568 else
569 printf("RSExportVectorType::Create : unsupported base element type\n");
570}
571
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700572RSExportType::ExportClass RSExportVectorType::getClass() const {
573 return RSExportType::ExportClassVector;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700574}
575
576const llvm::Type* RSExportVectorType::convertToLLVMType() const {
577 const llvm::Type* ElementType = RSExportPrimitiveType::convertToLLVMType();
578 return llvm::VectorType::get(ElementType, getNumElement());
579}
580
581/****************************** RSExportRecordType ******************************/
582RSExportRecordType* RSExportRecordType::Create(RSContext* Context, const RecordType* RT, const llvm::StringRef& TypeName, bool mIsArtificial) {
583 assert(RT != NULL && RT->getTypeClass() == Type::Record);
584
585 const RecordDecl* RD = RT->getDecl();
586 assert(RD->isStruct());
587
588 RD = RD->getDefinition();
589 if(RD == NULL) {
590 /* TODO: warning: actual struct definition isn't declared in this moudle */
591 printf("RSExportRecordType::Create : this struct is not defined in this module.");
592 return NULL;
593 }
594
595 RSExportRecordType* ERT = new RSExportRecordType(Context, TypeName, RD->hasAttr<PackedAttr>(), mIsArtificial);
596 unsigned int Index = 0;
597
598 for(RecordDecl::field_iterator fit = RD->field_begin();
599 fit != RD->field_end();
600 fit++, Index++)
601 {
602#define FAILED_CREATE_FIELD(err) do { \
603 if(*err) \
604 printf("RSExportRecordType::Create : failed to create field (%s)\n", err); \
605 delete ERT; \
606 return NULL; \
607 } while(false)
608 /* FIXME: All fields should be primitive type */
609 assert((*fit)->getKind() == Decl::Field);
610 FieldDecl* FD = *fit;
611
612 /* We don't support bit field TODO: allow bitfield with size 8, 16, 32 */
613 if(FD->isBitField())
614 FAILED_CREATE_FIELD("bit field is not supported");
615
616 /* Type */
617 RSExportType* ET = RSExportElement::CreateFromDecl(Context, FD);
618
619 if(ET != NULL)
620 ERT->mFields.push_back( new Field(ET, FD->getName(), ERT, Index) );
621 else
622 FAILED_CREATE_FIELD(FD->getName().str().c_str());
623#undef FAILED_CREATE_FIELD
624 }
625
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -0700626
627 const ASTRecordLayout &ASTRL = Context->getASTContext()->getASTRecordLayout(RD);
628 ERT->AllocSize = (ASTRL.getSize() > ASTRL.getDataSize()) ? (ASTRL.getSize() >> 3) : (ASTRL.getDataSize() >> 3);
629
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700630 return ERT;
631}
632
633RSExportType::ExportClass RSExportRecordType::getClass() const {
634 return RSExportType::ExportClassRecord;
635}
636
637const llvm::Type* RSExportRecordType::convertToLLVMType() const {
638 std::vector<const llvm::Type*> FieldTypes;
639
640 for(const_field_iterator FI = fields_begin();
641 FI != fields_end();
642 FI++)
643 {
644 const Field* F = *FI;
645 const RSExportType* FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700646
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700647 FieldTypes.push_back(FET->getLLVMType());
648 }
649
650 return llvm::StructType::get(getRSContext()->getLLVMContext(), FieldTypes, mIsPacked);
651}
652
653/****************************** RSExportRecordType::Field ******************************/
654size_t RSExportRecordType::Field::getOffsetInParent() const {
655 /* Struct layout obtains below will be cached by LLVM */
656 const llvm::StructLayout* SL = mParent->getRSContext()->getTargetData()->getStructLayout(static_cast<const llvm::StructType*>(mParent->getLLVMType()));
657 return SL->getElementOffset(mIndex);
658}
659
660} /* namespace slang */