blob: 99aaca651ace5fe565a7f82dd4c7a80a4731228b [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#include "slang_rs_context.hpp"
2#include "slang_rs_export_type.hpp"
3#include "slang_rs_export_element.hpp"
4
5#include "llvm/Type.h"
6#include "llvm/DerivedTypes.h"
7
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07008#include "llvm/ADT/StringExtras.h"
9#include "llvm/Target/TargetData.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070010
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070011#include "clang/AST/RecordLayout.h"
12
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070013#include <vector>
14
15using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070016
17/****************************** RSExportType ******************************/
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070018bool RSExportType::NormalizeType(const clang::Type *&T,
19 llvm::StringRef &TypeName) {
20 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
21 llvm::SmallPtrSet<const clang::Type*, 8>();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070022
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070023 if ((T = RSExportType::TypeExportable(T, SPS)) == NULL)
24 // TODO: warning the user: type not exportable
25 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070026
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070027 // Get type name
28 TypeName = RSExportType::GetTypeName(T);
29 if (TypeName.empty())
30 // TODO: warning the user: the type is unnamed
31 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070032
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070033 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070034}
35
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070036const clang::Type
37*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
38 if (DD && DD->getTypeSourceInfo()) {
39 clang::QualType T = DD->getTypeSourceInfo()->getType();
40 if (T.isNull())
41 return NULL;
42 else
43 return T.getTypePtr();
44 }
45 return NULL;
46}
47
48llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
49 T = GET_CANONICAL_TYPE(T);
50 if (T == NULL)
51 return llvm::StringRef();
52
53 switch (T->getTypeClass()) {
54 case clang::Type::Builtin: {
55 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
56
57 switch (BT->getKind()) {
58 // Compiler is smart enough to optimize following *big if branches*
59 // since they all become "constant comparison" after macro expansion
60#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
61 case builtin_type: { \
62 if (type == RSExportPrimitiveType::DataTypeFloat32) \
63 return "float"; \
64 else if (type == RSExportPrimitiveType::DataTypeFloat64) \
65 return "double"; \
66 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
67 return "uchar"; \
68 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
69 return "ushort"; \
70 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
71 return "uint"; \
72 else if (type == RSExportPrimitiveType::DataTypeSigned8) \
73 return "char"; \
74 else if (type == RSExportPrimitiveType::DataTypeSigned16) \
75 return "short"; \
76 else if (type == RSExportPrimitiveType::DataTypeSigned32) \
77 return "int"; \
78 else if(type == RSExportPrimitiveType::DataTypeSigned64) \
79 return "long"; \
Shih-wei Liao91a37832010-10-03 19:11:51 -070080 else if (type == RSExportPrimitiveType::DataTypeBoolean) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070081 return "bool"; \
82 else \
83 assert(false && "Unknow data type of supported builtin"); \
84 break; \
85 }
86#include "slang_rs_export_type_support.inc"
87
88 default: {
89 assert(false && "Unknown data type of the builtin");
90 break;
91 }
92 }
93 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070094 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070095
96 case clang::Type::Record: {
97 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
98 llvm::StringRef Name = RD->getName();
99 if (Name.empty()) {
100 if (RD->getTypedefForAnonDecl() != NULL)
101 Name = RD->getTypedefForAnonDecl()->getName();
102
103 if(Name.empty())
104 // Try to find a name from redeclaration (i.e. typedef)
105 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
106 RE = RD->redecls_end();
107 RI != RE;
108 RI++) {
109 assert(*RI != NULL && "cannot be NULL object");
110
111 Name = (*RI)->getName();
112 if (!Name.empty())
113 break;
114 }
115 }
116 return Name;
117 }
118
119 case clang::Type::Pointer: {
120 // "*" plus pointee name
121 const clang::Type* PT = GET_POINTEE_TYPE(T);
122 llvm::StringRef PointeeName;
123 if (NormalizeType(PT, PointeeName)) {
124 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
125 Name[0] = '*';
126 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
127 Name[PointeeName.size() + 1] = '\0';
128 return Name;
129 }
130 break;
131 }
132
133 case clang::Type::ConstantArray: {
134 const clang::ConstantArrayType *ECT =
135 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
136 return RSExportConstantArrayType::GetTypeName(ECT);
137 break;
138 }
139
140 case clang::Type::ExtVector: {
141 const clang::ExtVectorType *EVT =
142 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
143 return RSExportVectorType::GetTypeName(EVT);
144 break;
145 }
146
147 default: {
148 break;
149 }
150 }
151
152 return llvm::StringRef();
153}
154
155const clang::Type *RSExportType::TypeExportable(
156 const clang::Type *T,
157 llvm::SmallPtrSet<const clang::Type*, 8>& SPS) {
158 // Normalize first
159 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
160 return NULL;
161
162 if (SPS.count(T))
163 return T;
164
165 switch (T->getTypeClass()) {
166 case clang::Type::Builtin: {
167 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
168
169 switch (BT->getKind()) {
170#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
171 case builtin_type:
172#include "slang_rs_export_type_support.inc"
173 {
174 return T;
175 }
176
177 default: {
178 return NULL;
179 }
180 }
181 // Never be here
182 }
183
184
185 case clang::Type::Record: {
186 if (RSExportPrimitiveType::GetRSObjectType(T) !=
187 RSExportPrimitiveType::DataTypeUnknown)
188 return T; // RS object type, no further checks are needed
189
190 // Check internal struct
191 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
192 if (RD != NULL)
193 RD = RD->getDefinition();
194
195 // Fast check
196 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
197 return NULL;
198
199 // Insert myself into checking set
200 SPS.insert(T);
201
202 // Check all element
203 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
204 FE = RD->field_end();
205 FI != FE;
206 FI++) {
207 const clang::Type* FT = GetTypeOfDecl(*FI);
208 FT = GET_CANONICAL_TYPE(FT);
209
210 if (!TypeExportable(FT, SPS))
211 // TODO: warning: unsupported field type
212 return NULL;
213 }
214
215 return T;
216 }
217
218 case clang::Type::Pointer: {
219 const clang::PointerType *PT = UNSAFE_CAST_TYPE(clang::PointerType, T);
220 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
221
222 if ((PointeeType->getTypeClass() != clang::Type::Pointer) &&
223 (TypeExportable(PointeeType, SPS) == NULL) )
224 return NULL;
225 else
226 return T;
227 }
228
229 case clang::Type::ConstantArray: {
230 const clang::ConstantArrayType *ECT =
231 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
232 // No longer only support 2x2, 3x3 and 4x4 arrays
233 // if (ECT->getNumElements() != 4 &&
234 // ECT->getNumElements() != 9 &&
235 // ECT->getNumElements() != 16)
236 // return NULL;
237
238 // Check base element type
239 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(ECT);
240
241 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
242 (TypeExportable(ElementType, SPS) == NULL))
243 return NULL;
244 else
245 return T;
246 }
247
248 case clang::Type::ExtVector: {
249 const clang::ExtVectorType *EVT =
250 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
251 // Only vector with size 2, 3 and 4 are supported.
252 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
253 return NULL;
254
255 // Check base element type
256 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
257
258 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
259 (TypeExportable(ElementType, SPS) == NULL))
260 return NULL;
261 else
262 return T;
263 }
264
265 default: {
266 return NULL;
267 }
268 }
269}
270
271RSExportType *RSExportType::Create(RSContext *Context,
272 const clang::Type *T,
273 const llvm::StringRef &TypeName) {
274 // Lookup the context to see whether the type was processed before.
275 // Newly created RSExportType will insert into context
276 // in RSExportType::RSExportType()
277 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
278
279 if (ETI != Context->export_types_end())
280 return ETI->second;
281
282 RSExportType *ET = NULL;
283 switch (T->getTypeClass()) {
284 case clang::Type::Record: {
285 RSExportPrimitiveType::DataType dt =
286 RSExportPrimitiveType::GetRSObjectType(TypeName);
287 switch (dt) {
288 case RSExportPrimitiveType::DataTypeUnknown: { // User-defined types
289 ET = RSExportRecordType::Create(Context,
290 T->getAsStructureType(),
291 TypeName);
292 break;
293 }
294 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
295 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
296 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
297 const clang::RecordType *RT =
298 static_cast<const clang::RecordType*> (T);
299 const clang::RecordDecl *RD = RT->getDecl();
300 RD = RD->getDefinition();
301 clang::RecordDecl::field_iterator FI = RD->field_begin();
302 clang::FieldDecl *FD = *FI;
303 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
304 ET = RSExportConstantArrayType::Create(
305 Context,
306 static_cast<const clang::ConstantArrayType*> (FT),
307 TypeName);
308 break;
309 }
310 default: {
311 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
312 break;
313 }
314 }
315 break;
316 }
317 case clang::Type::Builtin: {
318 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
319 break;
320 }
321 case clang::Type::Pointer: {
322 ET = RSExportPointerType::Create(Context,
323 UNSAFE_CAST_TYPE(clang::PointerType, T),
324 TypeName);
325 // Free the name (allocated in RSExportType::GetTypeName)
326 delete [] TypeName.data();
327 break;
328 }
329 case clang::Type::ConstantArray: {
330 ET = RSExportConstantArrayType::Create(
331 Context,
332 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T),
333 TypeName);
334 break;
335 }
336 case clang::Type::ExtVector: {
337 ET = RSExportVectorType::Create(Context,
338 UNSAFE_CAST_TYPE(clang::ExtVectorType, T),
339 TypeName);
340 break;
341 }
342 default: {
343 // TODO: warning: type is not exportable
344 fprintf(stderr,
345 "RSExportType::Create : type '%s' is not exportable\n",
346 T->getTypeClassName());
347 break;
348 }
349 }
350
351 return ET;
352}
353
354RSExportType* RSExportType::Create(RSContext *Context, const clang::Type *T) {
355 llvm::StringRef TypeName;
356 if (NormalizeType(T, TypeName))
357 return Create(Context, T, TypeName);
358 else
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700359 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700360}
361
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700362RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
363 const clang::VarDecl *VD) {
364 return RSExportType::Create(Context, GetTypeOfDecl(VD));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700365}
366
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700367size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
368 return ET->getRSContext()->getTargetData()->getTypeStoreSize(
369 ET->getLLVMType()
370 );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700371}
372
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700373size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
374 if (ET->getClass() == RSExportType::ExportClassRecord)
375 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
376 else
377 return ET->getRSContext()->getTargetData()->getTypeAllocSize(
378 ET->getLLVMType()
379 );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700380}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700381
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700382RSExportType::RSExportType(RSContext *Context, const llvm::StringRef &Name) :
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700383 mContext(Context),
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700384 // Make a copy on Name since data of @Name which is stored in ASTContext
385 // will be destroyed later
386 mName(Name.data(), Name.size()),
387 mLLVMType(NULL) {
388 // TODO: need to check whether the insertion is successful or not
389 Context->insertExportType(Name, this);
390 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700391}
392
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700393/************************** RSExportPrimitiveType **************************/
394RSExportPrimitiveType::RSObjectTypeMapTy
395*RSExportPrimitiveType::RSObjectTypeMap = NULL;
396
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700397llvm::Type* RSExportPrimitiveType::RSObjectLLVMType = NULL;
398
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700399bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
400 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
401 return true;
402 else
403 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700404}
405
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700406RSExportPrimitiveType::DataType
407RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef &TypeName) {
408 if (TypeName.empty())
409 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700410
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700411 if (RSObjectTypeMap == NULL) {
412 RSObjectTypeMap = new RSObjectTypeMapTy(16);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700413
414#define USE_ELEMENT_DATA_TYPE
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700415#define DEF_RS_OBJECT_TYPE(type, name) \
416 RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700417#include "slang_rs_export_element_support.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700418 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700419
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700420 RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
421 if (I == RSObjectTypeMap->end())
422 return DataTypeUnknown;
423 else
424 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700425}
426
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700427RSExportPrimitiveType::DataType
428RSExportPrimitiveType::GetRSObjectType(const clang::Type *T) {
429 T = GET_CANONICAL_TYPE(T);
430 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
431 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700432
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700433 return GetRSObjectType( RSExportType::GetTypeName(T) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700434}
435
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700436const size_t
437RSExportPrimitiveType::SizeOfDataTypeInBits[
438 RSExportPrimitiveType::DataTypeMax + 1] = {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700439 16, // DataTypeFloat16
440 32, // DataTypeFloat32
441 64, // DataTypeFloat64
442 8, // DataTypeSigned8
443 16, // DataTypeSigned16
444 32, // DataTypeSigned32
445 64, // DataTypeSigned64
446 8, // DataTypeUnsigned8
447 16, // DataTypeUnsigned16
448 32, // DataTypeUnsigned32
449 64, // DataTypeUnSigned64
Shih-wei Liao91a37832010-10-03 19:11:51 -0700450 1, // DataTypeBoolean
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700451
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700452 16, // DataTypeUnsigned565
453 16, // DataTypeUnsigned5551
454 16, // DataTypeUnsigned4444
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700455
Shih-wei Liao91a37832010-10-03 19:11:51 -0700456 128, // DataTypeRSMatrix2x2
457 288, // DataTypeRSMatrix3x3
458 512, // DataTypeRSMatrix4x4
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700459
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700460 32, // DataTypeRSElement
461 32, // DataTypeRSType
462 32, // DataTypeRSAllocation
463 32, // DataTypeRSSampler
464 32, // DataTypeRSScript
465 32, // DataTypeRSMesh
466 32, // DataTypeRSProgramFragment
467 32, // DataTypeRSProgramVertex
468 32, // DataTypeRSProgramRaster
469 32, // DataTypeRSProgramStore
470 32, // DataTypeRSFont
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700471 0
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700472};
473
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700474size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
475 assert(((EPT->getType() >= DataTypeFloat32) &&
476 (EPT->getType() < DataTypeMax)) &&
477 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
478 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700479}
480
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700481RSExportPrimitiveType::DataType
482RSExportPrimitiveType::GetDataType(const clang::Type* T) {
483 if (T == NULL)
484 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700485
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700486 switch (T->getTypeClass()) {
487 case clang::Type::Builtin: {
488 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
489 switch (BT->getKind()) {
490#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
491 case builtin_type: { \
492 return type; \
493 break; \
494 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700495#include "slang_rs_export_type_support.inc"
496
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700497 // The size of types Long, ULong and WChar depend on platform so we
498 // abandon the support to them. Type of its size exceeds 32 bits (e.g.
499 // int64_t, double, etc.): no support
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700500
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700501 default: {
502 // TODO: warning the user: unsupported type
503 fprintf(stderr, "RSExportPrimitiveType::GetDataType : built-in type "
504 "has no corresponding data type for built-in type");
505 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700506 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700507 }
508 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700509 }
510
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700511 case clang::Type::Record: {
512 // must be RS object type
513 return RSExportPrimitiveType::GetRSObjectType(T);
514 break;
515 }
516
517 default: {
518 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not "
519 "supported primitive type", T->getTypeClassName());
520 break;
521 }
522 }
523
524 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700525}
526
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700527RSExportPrimitiveType
528*RSExportPrimitiveType::Create(RSContext *Context,
529 const clang::Type *T,
530 const llvm::StringRef &TypeName,
531 DataKind DK,
532 bool Normalized) {
533 DataType DT = GetDataType(T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700534
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700535 if ((DT == DataTypeUnknown) || TypeName.empty())
536 return NULL;
537 else
538 return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700539}
540
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700541RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
542 const clang::Type *T,
543 DataKind DK) {
544 llvm::StringRef TypeName;
545 if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
546 return Create(Context, T, TypeName, DK);
547 else
548 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700549}
550
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700551RSExportType::ExportClass RSExportPrimitiveType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700552 return RSExportType::ExportClassPrimitive;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700553}
554
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700555const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
556 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700557
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700558 if (isRSObjectType()) {
559 // struct {
560 // int *p;
561 // } __attribute__((packed, aligned(pointer_size)))
562 //
563 // which is
564 //
565 // <{ [1 x i32] }> in LLVM
566 //
567 if (RSObjectLLVMType == NULL) {
568 std::vector<const llvm::Type *> Elements;
569 Elements.push_back( llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1) );
570 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700571 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700572 return RSObjectLLVMType;
573 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700574
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700575 switch (mType) {
576 case DataTypeFloat32: {
577 return llvm::Type::getFloatTy(C);
578 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700579 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700580 case DataTypeFloat64: {
581 return llvm::Type::getDoubleTy(C);
582 break;
583 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700584 case DataTypeBoolean: {
585 return llvm::Type::getInt1Ty(C);
586 break;
587 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700588 case DataTypeSigned8:
589 case DataTypeUnsigned8: {
590 return llvm::Type::getInt8Ty(C);
591 break;
592 }
593 case DataTypeSigned16:
594 case DataTypeUnsigned16:
595 case DataTypeUnsigned565:
596 case DataTypeUnsigned5551:
597 case DataTypeUnsigned4444: {
598 return llvm::Type::getInt16Ty(C);
599 break;
600 }
601 case DataTypeSigned32:
602 case DataTypeUnsigned32: {
603 return llvm::Type::getInt32Ty(C);
604 break;
605 }
606 case DataTypeSigned64: {
607 // case DataTypeUnsigned64:
608 return llvm::Type::getInt64Ty(C);
609 break;
610 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700611 default: {
612 assert(false && "Unknown data type");
613 }
614 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700615
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700616 return NULL;
617}
618
619/**************************** RSExportPointerType ****************************/
620
621const clang::Type *RSExportPointerType::IntegerType = NULL;
622
623RSExportPointerType
624*RSExportPointerType::Create(RSContext *Context,
625 const clang::PointerType *PT,
626 const llvm::StringRef &TypeName) {
627 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
628 const RSExportType *PointeeET;
629
630 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
631 PointeeET = RSExportType::Create(Context, PointeeType);
632 } else {
633 // Double or higher dimension of pointer, export as int*
634 assert(IntegerType != NULL && "Built-in integer type is not set");
635 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
636 }
637
638 if (PointeeET == NULL) {
639 fprintf(stderr, "Failed to create type for pointee");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700640 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700641 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700642
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700643 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700644}
645
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700646RSExportType::ExportClass RSExportPointerType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700647 return RSExportType::ExportClassPointer;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700648}
649
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700650const llvm::Type *RSExportPointerType::convertToLLVMType() const {
651 const llvm::Type *PointeeType = mPointeeType->getLLVMType();
652 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700653}
654
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700655/************************* RSExportConstantArrayType *************************/
656llvm::StringRef
657RSExportConstantArrayType::GetTypeName(const clang::ConstantArrayType *CT) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700658 llvm::APInt i = CT->getSize();
659 if (i == 4) {
660 return llvm::StringRef("rs_matrix2x2");
661 } else if (i == 9) {
662 return llvm::StringRef("rs_matrix3x3");
663 } else if (i == 16) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700664 return llvm::StringRef("rs_matrix4x4");
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700665 }
666 return llvm::StringRef();
667}
668
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700669RSExportConstantArrayType
670*RSExportConstantArrayType::Create(RSContext *Context,
671 const clang::ConstantArrayType *CT,
672 const llvm::StringRef &TypeName,
673 DataKind DK,
674 bool Normalized) {
675 assert(CT != NULL && CT->getTypeClass() == clang::Type::ConstantArray);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700676
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700677 int64_t Size = CT->getSize().getSExtValue();
678 RSExportPrimitiveType::DataType DT;
679 if (Size == 4) {
680 DT = RSExportPrimitiveType::DataTypeRSMatrix2x2;
681 } else if (Size == 9) {
682 DT = RSExportPrimitiveType::DataTypeRSMatrix3x3;
683 } else if (Size == 16) {
684 DT = RSExportPrimitiveType::DataTypeRSMatrix4x4;
685 } else {
686 fprintf(stderr, "RSExportConstantArrayType::Create : unsupported base "
687 "element type\n");
688 return NULL;
689 }
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700690
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700691 return new RSExportConstantArrayType(Context,
692 TypeName,
693 DT,
694 DK,
695 Normalized,
696 Size);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700697}
698
699RSExportType::ExportClass RSExportConstantArrayType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700700 return RSExportType::ExportClassConstantArray;
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700701}
702
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700703const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
704 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700705 const llvm::Type *typ;
706 switch (getType()) {
707 case DataTypeFloat32:
708 case DataTypeRSMatrix2x2:
709 case DataTypeRSMatrix3x3:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700710 case DataTypeRSMatrix4x4: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700711 typ = llvm::Type::getFloatTy(C);
712 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700713 }
714 case DataTypeFloat64: {
Stephen Hines70842c72010-09-20 17:18:10 -0700715 typ = llvm::Type::getDoubleTy(C);
716 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700717 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700718 case DataTypeBoolean: {
719 typ = llvm::Type::getInt1Ty(C);
720 break;
721 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700722 case DataTypeSigned8:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700723 case DataTypeUnsigned8: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700724 typ = llvm::Type::getInt8Ty(C);
725 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700726 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700727 case DataTypeSigned16:
728 case DataTypeUnsigned16:
729 case DataTypeUnsigned565:
730 case DataTypeUnsigned5551:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700731 case DataTypeUnsigned4444: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700732 typ = llvm::Type::getInt16Ty(C);
733 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700734 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700735 case DataTypeSigned32:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700736 case DataTypeUnsigned32: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700737 typ = llvm::Type::getInt32Ty(C);
738 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700739 }
740 case DataTypeSigned64: {
Stephen Hines8d75dc42010-10-01 15:36:03 -0700741 //case DataTypeUnsigned64:
742 typ = llvm::Type::getInt64Ty(C);
743 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700744 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700745 default: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700746 assert(false && "Unknown data type");
747 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700748 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700749 }
750 return llvm::ArrayType::get(typ, mNumElement);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700751}
752
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700753/****************************** RSExportVectorType ******************************/
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700754const char* RSExportVectorType::VectorTypeNameStore[][3] = {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700755 /* 0 */ { "char2", "char3", "char4" },
756 /* 1 */ { "uchar2", "uchar3", "uchar4" },
757 /* 2 */ { "short2", "short3", "short4" },
758 /* 3 */ { "ushort2", "ushort3", "ushort4" },
759 /* 4 */ { "int2", "int3", "int4" },
760 /* 5 */ { "uint2", "uint3", "uint4" },
761 /* 6 */ { "float2", "float3", "float4" },
762 /* 7 */ { "double2", "double3", "double4" },
763 /* 8 */ { "long2", "long3", "long4" },
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700764};
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700765
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700766llvm::StringRef RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
767 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700768
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700769 if ((ElementType->getTypeClass() != clang::Type::Builtin))
770 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700771
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700772 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType,
773 ElementType);
774 const char **BaseElement = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700775
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700776 switch (BT->getKind()) {
777 // Compiler is smart enough to optimize following *big if branches* since
778 // they all become "constant comparison" after macro expansion
779#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
780 case builtin_type: { \
781 if (type == RSExportPrimitiveType::DataTypeSigned8) \
782 BaseElement = VectorTypeNameStore[0]; \
783 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
784 BaseElement = VectorTypeNameStore[1]; \
785 else if (type == RSExportPrimitiveType::DataTypeSigned16) \
786 BaseElement = VectorTypeNameStore[2]; \
787 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
788 BaseElement = VectorTypeNameStore[3]; \
789 else if (type == RSExportPrimitiveType::DataTypeSigned32) \
790 BaseElement = VectorTypeNameStore[4]; \
791 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
792 BaseElement = VectorTypeNameStore[5]; \
793 else if (type == RSExportPrimitiveType::DataTypeFloat32) \
794 BaseElement = VectorTypeNameStore[6]; \
795 else if (type == RSExportPrimitiveType::DataTypeFloat64) \
796 BaseElement = VectorTypeNameStore[7]; \
797 else if (type == RSExportPrimitiveType::DataTypeSigned64) \
798 BaseElement = VectorTypeNameStore[8]; \
Shih-wei Liao91a37832010-10-03 19:11:51 -0700799 else if (type == RSExportPrimitiveType::DataTypeBoolean) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700800 BaseElement = VectorTypeNameStore[0]; \
801 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700802 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700803#include "slang_rs_export_type_support.inc"
804 default: {
805 return llvm::StringRef();
806 }
807 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700808
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700809 if ((BaseElement != NULL) &&
810 (EVT->getNumElements() > 1) &&
811 (EVT->getNumElements() <= 4))
812 return BaseElement[EVT->getNumElements() - 2];
813 else
814 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700815}
816
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700817RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
818 const clang::ExtVectorType *EVT,
819 const llvm::StringRef &TypeName,
820 DataKind DK,
821 bool Normalized) {
822 assert(EVT != NULL && EVT->getTypeClass() == Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700823
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700824 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
825 RSExportPrimitiveType::DataType DT =
826 RSExportPrimitiveType::GetDataType(ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700827
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700828 if (DT != RSExportPrimitiveType::DataTypeUnknown)
829 return new RSExportVectorType(Context,
830 TypeName,
831 DT,
832 DK,
833 Normalized,
834 EVT->getNumElements());
835 else
836 fprintf(stderr, "RSExportVectorType::Create : unsupported base element "
837 "type\n");
838 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700839}
840
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700841RSExportType::ExportClass RSExportVectorType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700842 return RSExportType::ExportClassVector;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700843}
844
845const llvm::Type* RSExportVectorType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700846 const llvm::Type* ElementType = RSExportPrimitiveType::convertToLLVMType();
847 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700848}
849
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700850/**************************** RSExportRecordType ****************************/
851RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
852 const clang::RecordType *RT,
853 const llvm::StringRef &TypeName,
854 bool mIsArtificial) {
855 assert(RT != NULL && RT->getTypeClass() == Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700856
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700857 const clang::RecordDecl *RD = RT->getDecl();
858 assert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700859
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700860 RD = RD->getDefinition();
861 if (RD == NULL) {
862 // TODO: warning: actual struct definition isn't declared in this moudle
863 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined "
864 "in this module.");
865 return NULL;
866 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700867
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700868 RSExportRecordType *ERT = new RSExportRecordType(Context,
869 TypeName,
870 RD->
871 hasAttr<clang::PackedAttr>(),
872 mIsArtificial);
873 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700874
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700875 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
876 FE = RD->field_end();
877 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -0700878 FI++, Index++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700879#define FAILED_CREATE_FIELD(err) do { \
880 if (*err) \
881 fprintf(stderr, \
882 "RSExportRecordType::Create : failed to create field (%s)\n", \
883 err); \
884 delete ERT; \
885 return NULL; \
886 } while (false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700887
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700888 // FIXME: All fields should be primitive type
889 assert((*FI)->getKind() == clang::Decl::Field);
890 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700891
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700892 // We don't support bit field
893 //
894 // TODO: allow bitfield with size 8, 16, 32
895 if (FD->isBitField())
896 FAILED_CREATE_FIELD("bit field is not supported");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700897
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700898 // Type
899 RSExportType* ET = RSExportElement::CreateFromDecl(Context, FD);
900
901 if(ET != NULL)
902 ERT->mFields.push_back( new Field(ET, FD->getName(), ERT, Index) );
903 else
904 FAILED_CREATE_FIELD(FD->getName().str().c_str());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700905#undef FAILED_CREATE_FIELD
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700906 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700907
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700908 const clang::ASTRecordLayout &ASTRL =
909 Context->getASTContext()->getASTRecordLayout(RD);
910 ERT->AllocSize =
911 (ASTRL.getSize() > ASTRL.getDataSize()) ?
912 (ASTRL.getSize() >> 3) :
913 (ASTRL.getDataSize() >> 3);
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -0700914
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700915 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700916}
917
918RSExportType::ExportClass RSExportRecordType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700919 return RSExportType::ExportClassRecord;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700920}
921
922const llvm::Type* RSExportRecordType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700923 std::vector<const llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700924
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700925 for (const_field_iterator FI = fields_begin(),
926 FE = fields_end();
927 FI != FE;
928 FI++) {
929 const Field *F = *FI;
930 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700931
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700932 FieldTypes.push_back(FET->getLLVMType());
933 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700934
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700935 return llvm::StructType::get(getRSContext()->getLLVMContext(),
936 FieldTypes,
937 mIsPacked);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700938}
939
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700940/************************* RSExportRecordType::Field *************************/
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700941size_t RSExportRecordType::Field::getOffsetInParent() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700942 // Struct layout obtains below will be cached by LLVM
943 const llvm::StructLayout *SL =
944 mParent->getRSContext()->getTargetData()->getStructLayout(
945 static_cast<const llvm::StructType*>(mParent->getLLVMType())
946 );
947 return SL->getElementOffset(mIndex);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700948}