blob: 147a6ad9d5d17101d3a9af371cf1daddb17ae86e [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())
Shih-wei Liaof8149d92010-08-22 05:32:02 -070028 /* TODO: warning the user: the type is unnamed */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070029 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 }
Shih-wei Liaocecd11d2010-09-21 08:07:58 -070042 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070043}
44
45llvm::StringRef RSExportType::GetTypeName(const Type* T) {
46 T = GET_CANONICAL_TYPE(T);
47 if(T == NULL)
48 return llvm::StringRef();
49
50 switch(T->getTypeClass()) {
51 case Type::Builtin:
52 {
53 const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
54
55 switch(BT->getKind()) {
56#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
57 case builtin_type: \
58 /* Compiler is smart enough to optimize following *big if branches* since they all become "constant comparison" after macro expansion */ \
59 if(type == RSExportPrimitiveType::DataTypeFloat32) return "float"; \
60 else if(type == RSExportPrimitiveType::DataTypeUnsigned8) return "uchar"; \
61 else if(type == RSExportPrimitiveType::DataTypeUnsigned16) return "ushort"; \
62 else if(type == RSExportPrimitiveType::DataTypeUnsigned32) return "uint"; \
63 else if(type == RSExportPrimitiveType::DataTypeSigned8) return "char"; \
64 else if(type == RSExportPrimitiveType::DataTypeSigned16) return "short"; \
65 else if(type == RSExportPrimitiveType::DataTypeSigned32) return "int"; \
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -070066 else if(type == RSExportPrimitiveType::DataTypeBool) return "bool"; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -070067 else assert(false && "Unknow data type of supported builtin"); \
68 break;
69#include "slang_rs_export_type_support.inc"
70
71 default: assert(false && "Unknow data type of the builtin"); break;
72 }
73 }
74 break;
75
76 case Type::Record:
77 {
78 const RecordDecl* RD = T->getAsStructureType()->getDecl();
79 llvm::StringRef Name = RD->getName();
80 if(Name.empty()) {
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -070081 if(RD->getTypedefForAnonDecl() != NULL)
Shih-wei Liao462aefd2010-06-04 15:32:04 -070082 Name = RD->getTypedefForAnonDecl()->getName();
83
84 if(Name.empty())
85 /* Try to find a name from redeclaration (i.e. typedef) */
86 for(TagDecl::redecl_iterator RI = RD->redecls_begin();
87 RI != RD->redecls_end();
88 RI++)
89 {
90 assert(*RI != NULL && "cannot be NULL object");
91
92 Name = (*RI)->getName();
93 if(!Name.empty())
94 break;
95 }
96 }
97 return Name;
98 }
99 break;
100
101 case Type::Pointer:
102 {
103 /* "*" plus pointee name */
104 const Type* PT = GET_POINTEE_TYPE(T);
105 llvm::StringRef PointeeName;
106 if(NormalizeType(PT, PointeeName)) {
Shih-wei Liao4d7dc592010-08-20 05:11:09 -0700107 char* Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700108 Name[0] = '*';
109 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
Shih-wei Liao4d7dc592010-08-20 05:11:09 -0700110 Name[PointeeName.size() + 1] = '\0';
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700111 return Name;
112 }
113 }
114 break;
115
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700116 case Type::ConstantArray:
117 {
118 const ConstantArrayType* ECT = UNSAFE_CAST_TYPE(ConstantArrayType, T);
119 return RSExportConstantArrayType::GetTypeName(ECT);
120 }
121 break;
122
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700123 case Type::ExtVector:
124 {
125 const ExtVectorType* EVT = UNSAFE_CAST_TYPE(ExtVectorType, T);
126 return RSExportVectorType::GetTypeName(EVT);
127 }
128 break;
129
130 default:
131 break;
132 }
133
134 return llvm::StringRef();
135}
136
137const Type* RSExportType::TypeExportable(const Type* T, llvm::SmallPtrSet<const Type*, 8>& SPS) {
138 /* Normailize first */
139 if((T = GET_CANONICAL_TYPE(T)) == NULL)
140 return NULL;
141
142 if(SPS.count(T))
143 return T;
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700144
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700145 switch(T->getTypeClass()) {
146 case Type::Builtin:
147 {
148 const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
149
150 switch(BT->getKind()) {
151#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
152 case builtin_type:
153#include "slang_rs_export_type_support.inc"
154 return T;
155 break;
156
157 default:
158 return NULL;
159 break;
160 }
161 }
162 break;
163
164 case Type::Record:
165 {
166 if(RSExportPrimitiveType::GetRSObjectType(T) != RSExportPrimitiveType::DataTypeUnknown)
167 return T; /* RS object type, no further checks are needed */
168
169 /* Check internal struct */
170 const RecordDecl* RD = T->getAsStructureType()->getDecl();
171 if(RD != NULL)
172 RD = RD->getDefinition();
173
174 /* Fast check */
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700175 if(RD->hasFlexibleArrayMember() || RD->hasObjectMember())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700176 return NULL;
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700177
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700178 /* Insert myself into checking set */
179 SPS.insert(T);
180
181 /* Check all element */
182 for(RecordDecl::field_iterator F = RD->field_begin();
183 F != RD->field_end();
184 F++)
185 {
186 const Type* FT = GetTypeOfDecl(*F);
187 FT = GET_CANONICAL_TYPE(FT);
188
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700189 if(!TypeExportable(FT, SPS))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700190 /* TODO: warning: unsupported field type */
191 return NULL;
192 }
193
194 return T;
195 }
196 break;
197
198 case Type::Pointer:
199 {
200 const PointerType* PT = UNSAFE_CAST_TYPE(PointerType, T);
201 const Type* PointeeType = GET_POINTEE_TYPE(PT);
202
203 if((PointeeType->getTypeClass() != Type::Pointer) && (TypeExportable(PointeeType, SPS) == NULL) )
204 return NULL;
205 return T;
206 }
207 break;
208
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700209 case Type::ConstantArray:
210 {
211 const ConstantArrayType* ECT = UNSAFE_CAST_TYPE(ConstantArrayType, T);
212 /* Check element numbers */
213 // if (ECT->getNumElements() != 4 && ECT->getNumElements() != 9 && ECT->getNumElements() != 16) { /* only support 2x2, 3x3, 4x4 arrays */
214 // return NULL;
215
216 /* Check base element type */
217 const Type* ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(ECT);
218
219 if((ElementType->getTypeClass() != Type::Builtin) || (TypeExportable(ElementType, SPS) == NULL))
220 return NULL;
221 return T;
222 }
223 break;
224
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700225 case Type::ExtVector:
226 {
227 const ExtVectorType* EVT = UNSAFE_CAST_TYPE(ExtVectorType, T);
228 /* Check element numbers */
229 if(EVT->getNumElements() < 2 || EVT->getNumElements() > 4) /* only support vector with size 2, 3 and 4 */
230 return NULL;
231
232 /* Check base element type */
233 const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
234
235 if((ElementType->getTypeClass() != Type::Builtin) || (TypeExportable(ElementType, SPS) == NULL))
236 return NULL;
237 return T;
238 }
239 break;
240
241 default:
242 return NULL;
243 break;
244 }
245}
246
247RSExportType* RSExportType::Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName) {
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700248 /*
249 * Lookup the context to see whether the type was processed before.
250 * Newly create RSExportType will insert into context in RSExportType::RSExportType()
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700251 */
252 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
253
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700254 if(ETI != Context->export_types_end())
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700255 return ETI->second;
256
257 RSExportType* ET = NULL;
258 switch(T->getTypeClass()) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700259 case Type::Record: {
260 RSExportPrimitiveType::DataType dt = RSExportPrimitiveType::GetRSObjectType(TypeName);
261 switch (dt) {
262 case RSExportPrimitiveType::DataTypeUnknown: // User-defined types
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263 ET = RSExportRecordType::Create(Context, T->getAsStructureType(), TypeName);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700264 break;
265 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
266 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
267 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
268 const clang::RecordType* RT = static_cast<const RecordType*> (T);
269 const RecordDecl* RD = RT->getDecl();
270 RD = RD->getDefinition();
271 RecordDecl::field_iterator fit = RD->field_begin();
272 FieldDecl* FD = *fit;
273 const Type* FT = RSExportType::GetTypeOfDecl(FD);
274 ET = RSExportConstantArrayType::Create(Context, static_cast<const ConstantArrayType*> (FT), TypeName);
275 break;
276 }
277 default:
278 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
279 break;
280 }
281 break;
282 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700283 case Type::Builtin:
284 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700285 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700286
287 case Type::Pointer:
288 ET = RSExportPointerType::Create(Context, UNSAFE_CAST_TYPE(PointerType, T), TypeName);
289 /* free the name (allocated in RSExportType::GetTypeName) */
290 delete [] TypeName.data();
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700291 break;
292
293 case Type::ConstantArray:
294 ET = RSExportConstantArrayType::Create(Context, UNSAFE_CAST_TYPE(ConstantArrayType, T), TypeName);
295 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700296
297 case Type::ExtVector:
298 ET = RSExportVectorType::Create(Context, UNSAFE_CAST_TYPE(ExtVectorType, T), TypeName);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700299 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700300
301 default:
302 /* TODO: warning: type is not exportable */
303 printf("RSExportType::Create : type '%s' is not exportable\n", T->getTypeClassName());
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700304 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700305 }
306
307 return ET;
308}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700309
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700310RSExportType* RSExportType::Create(RSContext* Context, const Type* T) {
311 llvm::StringRef TypeName;
312 if(NormalizeType(T, TypeName))
313 return Create(Context, T, TypeName);
314 else
315 return NULL;
316}
317
318RSExportType* RSExportType::CreateFromDecl(RSContext* Context, const VarDecl* VD) {
319 return RSExportType::Create(Context, GetTypeOfDecl(VD));
320}
321
322size_t RSExportType::GetTypeStoreSize(const RSExportType* ET) {
323 return ET->getRSContext()->getTargetData()->getTypeStoreSize(ET->getLLVMType());
324}
325
326size_t RSExportType::GetTypeAllocSize(const RSExportType* ET) {
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -0700327 if(ET->getClass() == RSExportType::ExportClassRecord)
328 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
329 else
330 return ET->getRSContext()->getTargetData()->getTypeAllocSize(ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700331}
332
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700333RSExportType::RSExportType(RSContext* Context, const llvm::StringRef& Name) :
334 mContext(Context),
335 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 -0700336 mLLVMType(NULL)
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700337{
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700338 /* TODO: need to check whether the insertion is successful or not */
339 Context->insertExportType(Name, this);
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700340 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700341}
342
343/****************************** RSExportPrimitiveType ******************************/
344RSExportPrimitiveType::RSObjectTypeMapTy* RSExportPrimitiveType::RSObjectTypeMap = NULL;
345llvm::Type* RSExportPrimitiveType::RSObjectLLVMType = NULL;
346
347bool RSExportPrimitiveType::IsPrimitiveType(const Type* T) {
348 if((T != NULL) && (T->getTypeClass() == Type::Builtin))
349 return true;
350 else
351 return false;
352}
353
354RSExportPrimitiveType::DataType RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef& TypeName) {
355 if(TypeName.empty())
356 return DataTypeUnknown;
357
358 if(RSObjectTypeMap == NULL) {
359 RSObjectTypeMap = new RSObjectTypeMapTy(16);
360
361#define USE_ELEMENT_DATA_TYPE
362#define DEF_RS_OBJECT_TYPE(type, name) \
363 RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type));
364#include "slang_rs_export_element_support.inc"
365 }
366
367 RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
368 if(I == RSObjectTypeMap->end())
369 return DataTypeUnknown;
370 else
371 return I->getValue();
372}
373
374RSExportPrimitiveType::DataType RSExportPrimitiveType::GetRSObjectType(const Type* T) {
375 T = GET_CANONICAL_TYPE(T);
376 if((T == NULL) || (T->getTypeClass() != Type::Record))
377 return DataTypeUnknown;
378
379 return GetRSObjectType( RSExportType::GetTypeName(T) );
380}
381
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700382const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[RSExportPrimitiveType::DataTypeMax + 1] = {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700383 0,
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700384 16, /* DataTypeFloat16 */
385 32, /* DataTypeFloat32 */
386 64, /* DataTypeFloat64 */
387 8, /* DataTypeSigned8 */
388 16, /* DataTypeSigned16 */
389 32, /* DataTypeSigned32 */
390 64, /* DataTypeSigned64 */
391 8, /* DataTypeUnsigned8 */
392 16, /* DataTypeUnsigned16 */
393 32, /* DataTypeUnsigned32 */
394 64, /* DataTypeUnSigned64 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700395
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700396 16, /* DataTypeUnsigned565 */
397 16, /* DataTypeUnsigned5551 */
398 16, /* DataTypeUnsigned4444 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700399
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700400 1, /* DataTypeBool */
401
402 32, /* DataTypeRSElement */
403 32, /* DataTypeRSType */
404 32, /* DataTypeRSAllocation */
405 32, /* DataTypeRSSampler */
406 32, /* DataTypeRSScript */
407 32, /* DataTypeRSMesh */
408 32, /* DataTypeRSProgramFragment */
409 32, /* DataTypeRSProgramVertex */
410 32, /* DataTypeRSProgramRaster */
411 32, /* DataTypeRSProgramStore */
412 32, /* DataTypeRSFont */
Shih-wei Liao116d3d22010-08-19 18:19:09 -0700413 128, /* DataTypeRSMatrix2x2 */
414 288, /* DataTypeRSMatrix3x3 */
415 512, /* DataTypeRSMatrix4x4 */
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700416 0
417};
418
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700419size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType* EPT) {
420 assert(((EPT->getType() >= DataTypeFloat32) && (EPT->getType() < DataTypeMax)) && "RSExportPrimitiveType::GetSizeInBits : unknown data type");
421 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700422}
423
424RSExportPrimitiveType::DataType RSExportPrimitiveType::GetDataType(const Type* T) {
425 if(T == NULL)
426 return DataTypeUnknown;
427
428 switch(T->getTypeClass()) {
429 case Type::Builtin:
430 {
431 const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, T);
432 switch(BT->getKind()) {
433#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
434 case builtin_type: \
435 return type; \
436 break;
437#include "slang_rs_export_type_support.inc"
438
439 /* The size of types Long, ULong and WChar depend on platform so we abandon the support to them */
440 /* Type of its size exceeds 32 bits (e.g. int64_t, double, etc.) does not support */
441
442 default:
443 /* TODO: warning the user: unsupported type */
444 printf("RSExportPrimitiveType::GetDataType : built-in type has no corresponding data type for built-in type");
445 break;
446 }
447 }
448 break;
449
450 case Type::Record:
451 /* must be RS object type */
452 return RSExportPrimitiveType::GetRSObjectType(T);
453 break;
454
455 default:
456 printf("RSExportPrimitiveType::GetDataType : type '%s' is not supported primitive type", T->getTypeClassName());
457 break;
458 }
459
460 return DataTypeUnknown;
461}
462
463RSExportPrimitiveType* RSExportPrimitiveType::Create(RSContext* Context, const Type* T, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
464 DataType DT = GetDataType(T);
465
466 if((DT == DataTypeUnknown) || TypeName.empty())
467 return NULL;
468 else
469 return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
470}
471
472RSExportPrimitiveType* RSExportPrimitiveType::Create(RSContext* Context, const Type* T, DataKind DK) {
473 llvm::StringRef TypeName;
474 if(RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
475 return Create(Context, T, TypeName, DK);
476 else
477 return NULL;
478}
479
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700480RSExportType::ExportClass RSExportPrimitiveType::getClass() const {
481 return RSExportType::ExportClassPrimitive;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700482}
483
484const llvm::Type* RSExportPrimitiveType::convertToLLVMType() const {
485 llvm::LLVMContext& C = getRSContext()->getLLVMContext();
486
487 if(isRSObjectType()) {
488 /* struct { int* p; } __attribute__((packed, aligned(pointer_size))) which is <{ [1 x i32] }> in LLVM */
489 if(RSObjectLLVMType == NULL) {
490 std::vector<const llvm::Type*> Elements;
491 Elements.push_back( llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1) );
492 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
493 }
494 return RSObjectLLVMType;
495 }
496
497 switch(mType) {
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700498 case DataTypeFloat32:
499 return llvm::Type::getFloatTy(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700500 break;
501
502 case DataTypeSigned8:
503 case DataTypeUnsigned8:
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700504 return llvm::Type::getInt8Ty(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700505 break;
506
507 case DataTypeSigned16:
508 case DataTypeUnsigned16:
509 case DataTypeUnsigned565:
510 case DataTypeUnsigned5551:
511 case DataTypeUnsigned4444:
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700512 return llvm::Type::getInt16Ty(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700513 break;
514
515 case DataTypeSigned32:
516 case DataTypeUnsigned32:
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700517 return llvm::Type::getInt32Ty(C);
518 break;
519
520 case DataTypeBool:
521 return llvm::Type::getInt1Ty(C);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700522 break;
523
524 default:
525 assert(false && "Unknown data type");
526 break;
527 }
528
529 return NULL;
530}
531
532/****************************** RSExportPointerType ******************************/
533
534const Type* RSExportPointerType::IntegerType = NULL;
535
536RSExportPointerType* RSExportPointerType::Create(RSContext* Context, const PointerType* PT, const llvm::StringRef& TypeName) {
537 const Type* PointeeType = GET_POINTEE_TYPE(PT);
538 const RSExportType* PointeeET;
539
540 if(PointeeType->getTypeClass() != Type::Pointer) {
541 PointeeET = RSExportType::Create(Context, PointeeType);
542 } else {
543 /* Double or higher dimension of pointer, export as int* */
544 assert(IntegerType != NULL && "Built-in integer type is not set");
545 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
546 }
547
548 if(PointeeET == NULL) {
549 printf("Failed to create type for pointee");
550 return NULL;
551 }
552
553 return new RSExportPointerType(Context, TypeName, PointeeET);
554}
555
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700556RSExportType::ExportClass RSExportPointerType::getClass() const {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700557 return RSExportType::ExportClassPointer;
558}
559
560const llvm::Type* RSExportPointerType::convertToLLVMType() const {
561 const llvm::Type* PointeeType = mPointeeType->getLLVMType();
562 return llvm::PointerType::getUnqual(PointeeType);
563}
564
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700565/****************************** RSExportConstantArrayType ******************************/
566llvm::StringRef RSExportConstantArrayType::GetTypeName(const ConstantArrayType* CT) {
567 llvm::APInt i = CT->getSize();
568 if (i == 4) {
569 return llvm::StringRef("rs_matrix2x2");
570 } else if (i == 9) {
571 return llvm::StringRef("rs_matrix3x3");
572 } else if (i == 16) {
573 return llvm::StringRef("rs_matrix4x4");
574 }
575 return llvm::StringRef();
576}
577
578RSExportConstantArrayType* RSExportConstantArrayType::Create(RSContext* Context, const ConstantArrayType* CT, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
579 assert(CT != NULL && CT->getTypeClass() == Type::ConstantArray);
580
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700581 int64_t Size = CT->getSize().getSExtValue();
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700582 RSExportPrimitiveType::DataType DT;
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700583 if (Size == 4) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700584 DT = RSExportPrimitiveType::DataTypeRSMatrix2x2;
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700585 } else if (Size == 9) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700586 DT = RSExportPrimitiveType::DataTypeRSMatrix3x3;
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700587 } else if (Size == 16) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700588 DT = RSExportPrimitiveType::DataTypeRSMatrix4x4;
589 } else {
590 printf("RSExportConstantArrayType::Create : unsupported base element type\n");
591 }
592
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700593 return new RSExportConstantArrayType(Context, TypeName, DT, DK, Normalized, Size);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700594}
595
596RSExportType::ExportClass RSExportConstantArrayType::getClass() const {
597 return RSExportType::ExportClassConstantArray;
598}
599
600const llvm::Type* RSExportConstantArrayType::convertToLLVMType() const {
601 llvm::LLVMContext& C = getRSContext()->getLLVMContext();
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700602 const llvm::Type *typ;
603 switch (getType()) {
604 case DataTypeFloat32:
605 case DataTypeRSMatrix2x2:
606 case DataTypeRSMatrix3x3:
607 case DataTypeRSMatrix4x4:
608 typ = llvm::Type::getFloatTy(C);
609 break;
610
611 case DataTypeSigned8:
612 case DataTypeUnsigned8:
613 typ = llvm::Type::getInt8Ty(C);
614 break;
615
616 case DataTypeSigned16:
617 case DataTypeUnsigned16:
618 case DataTypeUnsigned565:
619 case DataTypeUnsigned5551:
620 case DataTypeUnsigned4444:
621 typ = llvm::Type::getInt16Ty(C);
622 break;
623
624 case DataTypeSigned32:
625 case DataTypeUnsigned32:
626 typ = llvm::Type::getInt32Ty(C);
627 break;
628
629 case DataTypeBool:
630 typ = llvm::Type::getInt1Ty(C);
631 break;
632
633 default:
634 assert(false && "Unknown data type");
635 break;
636 }
637 return llvm::ArrayType::get(typ, mNumElement);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700638}
639
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700640/****************************** RSExportVectorType ******************************/
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700641const char* RSExportVectorType::VectorTypeNameStore[][3] = {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700642 /* 0 */ { "char2", "char3", "char4" },
643 /* 1 */ { "uchar2", "uchar3", "uchar4" },
644 /* 2 */ { "short2", "short3", "short4" },
645 /* 3 */ { "ushort2", "ushort3", "ushort4" },
646 /* 4 */ { "int2", "int3", "int4" },
647 /* 5 */ { "uint2", "uint3", "uint4" },
648 /* 6 */ { "float2", "float3", "float4" },
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700649};
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700650
651llvm::StringRef RSExportVectorType::GetTypeName(const ExtVectorType* EVT) {
652 const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
653
654 if((ElementType->getTypeClass() != Type::Builtin))
655 return llvm::StringRef();
656
657 const BuiltinType* BT = UNSAFE_CAST_TYPE(BuiltinType, ElementType);
658 const char** BaseElement = NULL;
659
660 switch(BT->getKind()) {
661#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
662 case builtin_type: \
663 /* Compiler is smart enough to optimize following *big if branches* since they all become "constant comparison" after macro expansion */ \
664 if(type == RSExportPrimitiveType::DataTypeSigned8) BaseElement = VectorTypeNameStore[0]; \
665 else if(type == RSExportPrimitiveType::DataTypeUnsigned8) BaseElement = VectorTypeNameStore[1]; \
666 else if(type == RSExportPrimitiveType::DataTypeSigned16) BaseElement = VectorTypeNameStore[2]; \
667 else if(type == RSExportPrimitiveType::DataTypeUnsigned16) BaseElement = VectorTypeNameStore[3]; \
668 else if(type == RSExportPrimitiveType::DataTypeSigned32) BaseElement = VectorTypeNameStore[4]; \
669 else if(type == RSExportPrimitiveType::DataTypeUnsigned32) BaseElement = VectorTypeNameStore[5]; \
670 else if(type == RSExportPrimitiveType::DataTypeFloat32) BaseElement = VectorTypeNameStore[6]; \
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700671 else if(type == RSExportPrimitiveType::DataTypeBool) BaseElement = VectorTypeNameStore[0]; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700672 break;
673#include "slang_rs_export_type_support.inc"
674
675 default: return llvm::StringRef(); break;
676 }
677
678 if((BaseElement != NULL) && (EVT->getNumElements() > 1) && (EVT->getNumElements() <= 4))
679 return BaseElement[EVT->getNumElements() - 2];
680 else
681 return llvm::StringRef();
682}
683
684RSExportVectorType* RSExportVectorType::Create(RSContext* Context, const ExtVectorType* EVT, const llvm::StringRef& TypeName, DataKind DK, bool Normalized) {
685 assert(EVT != NULL && EVT->getTypeClass() == Type::ExtVector);
686
687 const Type* ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
688 RSExportPrimitiveType::DataType DT = RSExportPrimitiveType::GetDataType(ElementType);
689
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700690 if(DT != RSExportPrimitiveType::DataTypeUnknown)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700691 return new RSExportVectorType(Context, TypeName, DT, DK, Normalized, EVT->getNumElements());
692 else
693 printf("RSExportVectorType::Create : unsupported base element type\n");
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700694 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700695}
696
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700697RSExportType::ExportClass RSExportVectorType::getClass() const {
698 return RSExportType::ExportClassVector;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700699}
700
701const llvm::Type* RSExportVectorType::convertToLLVMType() const {
702 const llvm::Type* ElementType = RSExportPrimitiveType::convertToLLVMType();
703 return llvm::VectorType::get(ElementType, getNumElement());
704}
705
706/****************************** RSExportRecordType ******************************/
707RSExportRecordType* RSExportRecordType::Create(RSContext* Context, const RecordType* RT, const llvm::StringRef& TypeName, bool mIsArtificial) {
708 assert(RT != NULL && RT->getTypeClass() == Type::Record);
709
710 const RecordDecl* RD = RT->getDecl();
711 assert(RD->isStruct());
712
713 RD = RD->getDefinition();
714 if(RD == NULL) {
715 /* TODO: warning: actual struct definition isn't declared in this moudle */
716 printf("RSExportRecordType::Create : this struct is not defined in this module.");
717 return NULL;
718 }
719
720 RSExportRecordType* ERT = new RSExportRecordType(Context, TypeName, RD->hasAttr<PackedAttr>(), mIsArtificial);
721 unsigned int Index = 0;
722
723 for(RecordDecl::field_iterator fit = RD->field_begin();
724 fit != RD->field_end();
725 fit++, Index++)
726 {
727#define FAILED_CREATE_FIELD(err) do { \
728 if(*err) \
729 printf("RSExportRecordType::Create : failed to create field (%s)\n", err); \
730 delete ERT; \
731 return NULL; \
732 } while(false)
733 /* FIXME: All fields should be primitive type */
734 assert((*fit)->getKind() == Decl::Field);
735 FieldDecl* FD = *fit;
736
737 /* We don't support bit field TODO: allow bitfield with size 8, 16, 32 */
738 if(FD->isBitField())
739 FAILED_CREATE_FIELD("bit field is not supported");
740
741 /* Type */
742 RSExportType* ET = RSExportElement::CreateFromDecl(Context, FD);
743
744 if(ET != NULL)
745 ERT->mFields.push_back( new Field(ET, FD->getName(), ERT, Index) );
746 else
747 FAILED_CREATE_FIELD(FD->getName().str().c_str());
748#undef FAILED_CREATE_FIELD
749 }
750
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -0700751
752 const ASTRecordLayout &ASTRL = Context->getASTContext()->getASTRecordLayout(RD);
753 ERT->AllocSize = (ASTRL.getSize() > ASTRL.getDataSize()) ? (ASTRL.getSize() >> 3) : (ASTRL.getDataSize() >> 3);
754
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700755 return ERT;
756}
757
758RSExportType::ExportClass RSExportRecordType::getClass() const {
759 return RSExportType::ExportClassRecord;
760}
761
762const llvm::Type* RSExportRecordType::convertToLLVMType() const {
763 std::vector<const llvm::Type*> FieldTypes;
764
765 for(const_field_iterator FI = fields_begin();
766 FI != fields_end();
767 FI++)
768 {
769 const Field* F = *FI;
770 const RSExportType* FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700771
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700772 FieldTypes.push_back(FET->getLLVMType());
773 }
774
775 return llvm::StructType::get(getRSContext()->getLLVMContext(), FieldTypes, mIsPacked);
776}
777
778/****************************** RSExportRecordType::Field ******************************/
779size_t RSExportRecordType::Field::getOffsetInParent() const {
780 /* Struct layout obtains below will be cached by LLVM */
781 const llvm::StructLayout* SL = mParent->getRSContext()->getTargetData()->getStructLayout(static_cast<const llvm::StructType*>(mParent->getLLVMType()));
782 return SL->getElementOffset(mIndex);
783}
784
785} /* namespace slang */