blob: a0b94e3fa93971ce46e53a18702aa757f4fbfd3a [file] [log] [blame]
zonr6315f762010-10-05 15:35:14 +08001#include "slang_rs_export_type.h"
2
3#include <vector>
Shih-wei Liao462aefd2010-06-04 15:32:04 -07004
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
zonr6315f762010-10-05 15:35:14 +080013#include "slang_rs_context.h"
14#include "slang_rs_export_element.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070015
16using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070017
18/****************************** RSExportType ******************************/
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070019bool RSExportType::NormalizeType(const clang::Type *&T,
20 llvm::StringRef &TypeName) {
21 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
22 llvm::SmallPtrSet<const clang::Type*, 8>();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070023
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024 if ((T = RSExportType::TypeExportable(T, SPS)) == NULL)
zonr6315f762010-10-05 15:35:14 +080025 // TODO(zonr): warn that type not exportable.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070026 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070027
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070028 // Get type name
29 TypeName = RSExportType::GetTypeName(T);
30 if (TypeName.empty())
zonr6315f762010-10-05 15:35:14 +080031 // TODO(zonr): warning that the type is unnamed.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070032 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070033
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070034 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070035}
36
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070037const clang::Type
38*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +080039 if (DD) {
40 clang::QualType T;
41 if (DD->getTypeSourceInfo())
42 T = DD->getTypeSourceInfo()->getType();
43 else
44 T = DD->getType();
45
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070046 if (T.isNull())
47 return NULL;
48 else
49 return T.getTypePtr();
50 }
51 return NULL;
52}
53
54llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
55 T = GET_CANONICAL_TYPE(T);
56 if (T == NULL)
57 return llvm::StringRef();
58
59 switch (T->getTypeClass()) {
60 case clang::Type::Builtin: {
61 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
62
63 switch (BT->getKind()) {
64 // Compiler is smart enough to optimize following *big if branches*
65 // since they all become "constant comparison" after macro expansion
66#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
67 case builtin_type: { \
68 if (type == RSExportPrimitiveType::DataTypeFloat32) \
69 return "float"; \
70 else if (type == RSExportPrimitiveType::DataTypeFloat64) \
71 return "double"; \
72 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
73 return "uchar"; \
74 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
75 return "ushort"; \
76 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
77 return "uint"; \
78 else if (type == RSExportPrimitiveType::DataTypeSigned8) \
79 return "char"; \
80 else if (type == RSExportPrimitiveType::DataTypeSigned16) \
81 return "short"; \
82 else if (type == RSExportPrimitiveType::DataTypeSigned32) \
83 return "int"; \
zonr6315f762010-10-05 15:35:14 +080084 else if (type == RSExportPrimitiveType::DataTypeSigned64) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070085 return "long"; \
Shih-wei Liao91a37832010-10-03 19:11:51 -070086 else if (type == RSExportPrimitiveType::DataTypeBoolean) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070087 return "bool"; \
88 else \
89 assert(false && "Unknow data type of supported builtin"); \
90 break; \
91 }
92#include "slang_rs_export_type_support.inc"
93
94 default: {
95 assert(false && "Unknown data type of the builtin");
96 break;
97 }
98 }
99 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700100 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700101 case clang::Type::Record: {
102 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
103 llvm::StringRef Name = RD->getName();
104 if (Name.empty()) {
105 if (RD->getTypedefForAnonDecl() != NULL)
106 Name = RD->getTypedefForAnonDecl()->getName();
107
zonr6315f762010-10-05 15:35:14 +0800108 if (Name.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700109 // Try to find a name from redeclaration (i.e. typedef)
110 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
111 RE = RD->redecls_end();
112 RI != RE;
113 RI++) {
114 assert(*RI != NULL && "cannot be NULL object");
115
116 Name = (*RI)->getName();
117 if (!Name.empty())
118 break;
119 }
120 }
121 return Name;
122 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700123 case clang::Type::Pointer: {
124 // "*" plus pointee name
zonr6315f762010-10-05 15:35:14 +0800125 const clang::Type *PT = GET_POINTEE_TYPE(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700126 llvm::StringRef PointeeName;
127 if (NormalizeType(PT, PointeeName)) {
128 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
129 Name[0] = '*';
130 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
131 Name[PointeeName.size() + 1] = '\0';
132 return Name;
133 }
134 break;
135 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700136 case clang::Type::ConstantArray: {
137 const clang::ConstantArrayType *ECT =
138 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
139 return RSExportConstantArrayType::GetTypeName(ECT);
140 break;
141 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 case clang::Type::ExtVector: {
143 const clang::ExtVectorType *EVT =
144 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
145 return RSExportVectorType::GetTypeName(EVT);
146 break;
147 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700148 default: {
149 break;
150 }
151 }
152
153 return llvm::StringRef();
154}
155
156const clang::Type *RSExportType::TypeExportable(
157 const clang::Type *T,
158 llvm::SmallPtrSet<const clang::Type*, 8>& SPS) {
159 // Normalize first
160 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
161 return NULL;
162
163 if (SPS.count(T))
164 return T;
165
166 switch (T->getTypeClass()) {
167 case clang::Type::Builtin: {
168 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
169
170 switch (BT->getKind()) {
171#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
172 case builtin_type:
173#include "slang_rs_export_type_support.inc"
174 {
175 return T;
176 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700177 default: {
178 return NULL;
179 }
180 }
181 // Never be here
182 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700183 case clang::Type::Record: {
184 if (RSExportPrimitiveType::GetRSObjectType(T) !=
185 RSExportPrimitiveType::DataTypeUnknown)
zonr6315f762010-10-05 15:35:14 +0800186 return T; // RS object type, no further checks are needed
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187
188 // Check internal struct
189 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
190 if (RD != NULL)
191 RD = RD->getDefinition();
192
193 // Fast check
194 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
195 return NULL;
196
197 // Insert myself into checking set
198 SPS.insert(T);
199
200 // Check all element
201 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
202 FE = RD->field_end();
203 FI != FE;
204 FI++) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800205 const clang::FieldDecl *FD = *FI;
206 const clang::Type *FT = GetTypeOfDecl(FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700207 FT = GET_CANONICAL_TYPE(FT);
208
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800209 if (!TypeExportable(FT, SPS)) {
210 fprintf(stderr, "Field `%s' in Record `%s' contains unsupported "
211 "type\n", FD->getNameAsString().c_str(),
212 RD->getNameAsString().c_str());
213 FT->dump();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700214 return NULL;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800215 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700216 }
217
218 return T;
219 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700220 case clang::Type::Pointer: {
221 const clang::PointerType *PT = UNSAFE_CAST_TYPE(clang::PointerType, T);
222 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
223
224 if ((PointeeType->getTypeClass() != clang::Type::Pointer) &&
225 (TypeExportable(PointeeType, SPS) == NULL) )
226 return NULL;
227 else
228 return T;
229 }
230
231 case clang::Type::ConstantArray: {
232 const clang::ConstantArrayType *ECT =
233 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
234 // No longer only support 2x2, 3x3 and 4x4 arrays
235 // if (ECT->getNumElements() != 4 &&
236 // ECT->getNumElements() != 9 &&
237 // ECT->getNumElements() != 16)
238 // return NULL;
239
240 // Check base element type
241 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(ECT);
242
243 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
244 (TypeExportable(ElementType, SPS) == NULL))
245 return NULL;
246 else
247 return T;
248 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700249 case clang::Type::ExtVector: {
250 const clang::ExtVectorType *EVT =
251 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
252 // Only vector with size 2, 3 and 4 are supported.
253 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
254 return NULL;
255
256 // Check base element type
257 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
258
259 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
260 (TypeExportable(ElementType, SPS) == NULL))
261 return NULL;
262 else
263 return T;
264 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700265 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) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800288 case RSExportPrimitiveType::DataTypeUnknown: {
289 // User-defined types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700290 ET = RSExportRecordType::Create(Context,
291 T->getAsStructureType(),
292 TypeName);
293 break;
294 }
Zonr Chang92b344a2010-10-05 20:39:03 +0800295 case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
296 // 2 x 2 Matrix type
297 ET = RSExportMatrixType::Create(Context,
298 T->getAsStructureType(),
299 TypeName,
300 2);
301 break;
302 }
303 case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
304 // 3 x 3 Matrix type
305 ET = RSExportMatrixType::Create(Context,
306 T->getAsStructureType(),
307 TypeName,
308 3);
309 break;
310 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700311 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800312 // 4 x 4 Matrix type
313 ET = RSExportMatrixType::Create(Context,
314 T->getAsStructureType(),
315 TypeName,
316 4);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700317 break;
318 }
319 default: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800320 // Others are primitive types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700321 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
322 break;
323 }
324 }
325 break;
326 }
327 case clang::Type::Builtin: {
328 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
329 break;
330 }
331 case clang::Type::Pointer: {
332 ET = RSExportPointerType::Create(Context,
333 UNSAFE_CAST_TYPE(clang::PointerType, T),
334 TypeName);
Zonr Chang92b344a2010-10-05 20:39:03 +0800335 // FIXME: free the name (allocated in RSExportType::GetTypeName)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700336 delete [] TypeName.data();
337 break;
338 }
339 case clang::Type::ConstantArray: {
340 ET = RSExportConstantArrayType::Create(
341 Context,
342 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T),
343 TypeName);
344 break;
345 }
346 case clang::Type::ExtVector: {
347 ET = RSExportVectorType::Create(Context,
348 UNSAFE_CAST_TYPE(clang::ExtVectorType, T),
349 TypeName);
350 break;
351 }
352 default: {
zonr6315f762010-10-05 15:35:14 +0800353 // TODO(zonr): warn that type is not exportable.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700354 fprintf(stderr,
355 "RSExportType::Create : type '%s' is not exportable\n",
356 T->getTypeClassName());
357 break;
358 }
359 }
360
361 return ET;
362}
363
zonr6315f762010-10-05 15:35:14 +0800364RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700365 llvm::StringRef TypeName;
366 if (NormalizeType(T, TypeName))
367 return Create(Context, T, TypeName);
368 else
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700369 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700370}
371
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700372RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
373 const clang::VarDecl *VD) {
374 return RSExportType::Create(Context, GetTypeOfDecl(VD));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700375}
376
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700377size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
378 return ET->getRSContext()->getTargetData()->getTypeStoreSize(
zonr6315f762010-10-05 15:35:14 +0800379 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700380}
381
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700382size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
383 if (ET->getClass() == RSExportType::ExportClassRecord)
384 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
385 else
386 return ET->getRSContext()->getTargetData()->getTypeAllocSize(
zonr6315f762010-10-05 15:35:14 +0800387 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700388}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700389
zonr6315f762010-10-05 15:35:14 +0800390RSExportType::RSExportType(RSContext *Context, const llvm::StringRef &Name)
391 : mContext(Context),
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800392 // Make a copy on Name since memory stored @Name is either allocated in
393 // ASTContext or allocated in GetTypeName which will be destroyed later.
zonr6315f762010-10-05 15:35:14 +0800394 mName(Name.data(), Name.size()),
395 mLLVMType(NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800396 // Don't cache the type whose name start with '<'. Those type failed to
397 // get their name since constructing their name in GetTypeName() requiring
398 // complicated work.
399 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
400 // TODO(zonr): Need to check whether the insertion is successful or not.
401 Context->insertExportType(llvm::StringRef(Name), this);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700402 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700403}
404
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700405/************************** RSExportPrimitiveType **************************/
406RSExportPrimitiveType::RSObjectTypeMapTy
407*RSExportPrimitiveType::RSObjectTypeMap = NULL;
408
zonr6315f762010-10-05 15:35:14 +0800409llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700410
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700411bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
412 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
413 return true;
414 else
415 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700416}
417
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700418RSExportPrimitiveType::DataType
419RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef &TypeName) {
420 if (TypeName.empty())
421 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700422
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700423 if (RSObjectTypeMap == NULL) {
424 RSObjectTypeMap = new RSObjectTypeMapTy(16);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700425
426#define USE_ELEMENT_DATA_TYPE
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700427#define DEF_RS_OBJECT_TYPE(type, name) \
428 RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700429#include "slang_rs_export_element_support.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700430 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700431
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700432 RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
433 if (I == RSObjectTypeMap->end())
434 return DataTypeUnknown;
435 else
436 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700437}
438
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700439RSExportPrimitiveType::DataType
440RSExportPrimitiveType::GetRSObjectType(const clang::Type *T) {
441 T = GET_CANONICAL_TYPE(T);
442 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
443 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700444
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700445 return GetRSObjectType( RSExportType::GetTypeName(T) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700446}
447
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700448const size_t
449RSExportPrimitiveType::SizeOfDataTypeInBits[
450 RSExportPrimitiveType::DataTypeMax + 1] = {
zonr6315f762010-10-05 15:35:14 +0800451 16, // DataTypeFloat16
452 32, // DataTypeFloat32
453 64, // DataTypeFloat64
454 8, // DataTypeSigned8
455 16, // DataTypeSigned16
456 32, // DataTypeSigned32
457 64, // DataTypeSigned64
458 8, // DataTypeUnsigned8
459 16, // DataTypeUnsigned16
460 32, // DataTypeUnsigned32
461 64, // DataTypeUnSigned64
462 1, // DataTypeBoolean
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700463
zonr6315f762010-10-05 15:35:14 +0800464 16, // DataTypeUnsigned565
465 16, // DataTypeUnsigned5551
466 16, // DataTypeUnsigned4444
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700467
zonr6315f762010-10-05 15:35:14 +0800468 128, // DataTypeRSMatrix2x2
469 288, // DataTypeRSMatrix3x3
470 512, // DataTypeRSMatrix4x4
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700471
zonr6315f762010-10-05 15:35:14 +0800472 32, // DataTypeRSElement
473 32, // DataTypeRSType
474 32, // DataTypeRSAllocation
475 32, // DataTypeRSSampler
476 32, // DataTypeRSScript
477 32, // DataTypeRSMesh
478 32, // DataTypeRSProgramFragment
479 32, // DataTypeRSProgramVertex
480 32, // DataTypeRSProgramRaster
481 32, // DataTypeRSProgramStore
482 32, // DataTypeRSFont
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700483 0
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700484};
485
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700486size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
487 assert(((EPT->getType() >= DataTypeFloat32) &&
488 (EPT->getType() < DataTypeMax)) &&
489 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
490 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700491}
492
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700493RSExportPrimitiveType::DataType
zonr6315f762010-10-05 15:35:14 +0800494RSExportPrimitiveType::GetDataType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700495 if (T == NULL)
496 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700497
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700498 switch (T->getTypeClass()) {
499 case clang::Type::Builtin: {
500 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
501 switch (BT->getKind()) {
502#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
503 case builtin_type: { \
504 return type; \
505 break; \
506 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700507#include "slang_rs_export_type_support.inc"
508
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700509 // The size of types Long, ULong and WChar depend on platform so we
510 // abandon the support to them. Type of its size exceeds 32 bits (e.g.
511 // int64_t, double, etc.): no support
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700512
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700513 default: {
zonr6315f762010-10-05 15:35:14 +0800514 // TODO(zonr): warn that the type is unsupported
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700515 fprintf(stderr, "RSExportPrimitiveType::GetDataType : built-in type "
516 "has no corresponding data type for built-in type");
517 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700518 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700519 }
520 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700521 }
522
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700523 case clang::Type::Record: {
524 // must be RS object type
525 return RSExportPrimitiveType::GetRSObjectType(T);
526 break;
527 }
528
529 default: {
530 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not "
531 "supported primitive type", T->getTypeClassName());
532 break;
533 }
534 }
535
536 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700537}
538
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700539RSExportPrimitiveType
540*RSExportPrimitiveType::Create(RSContext *Context,
541 const clang::Type *T,
542 const llvm::StringRef &TypeName,
543 DataKind DK,
544 bool Normalized) {
545 DataType DT = GetDataType(T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700546
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700547 if ((DT == DataTypeUnknown) || TypeName.empty())
548 return NULL;
549 else
550 return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700551}
552
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700553RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
554 const clang::Type *T,
555 DataKind DK) {
556 llvm::StringRef TypeName;
557 if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
558 return Create(Context, T, TypeName, DK);
559 else
560 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700561}
562
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700563RSExportType::ExportClass RSExportPrimitiveType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700564 return RSExportType::ExportClassPrimitive;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700565}
566
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700567const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
568 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700569
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700570 if (isRSObjectType()) {
571 // struct {
572 // int *p;
573 // } __attribute__((packed, aligned(pointer_size)))
574 //
575 // which is
576 //
577 // <{ [1 x i32] }> in LLVM
578 //
579 if (RSObjectLLVMType == NULL) {
580 std::vector<const llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +0800581 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700582 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700583 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700584 return RSObjectLLVMType;
585 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700586
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700587 switch (mType) {
588 case DataTypeFloat32: {
589 return llvm::Type::getFloatTy(C);
590 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700591 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700592 case DataTypeFloat64: {
593 return llvm::Type::getDoubleTy(C);
594 break;
595 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700596 case DataTypeBoolean: {
597 return llvm::Type::getInt1Ty(C);
598 break;
599 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700600 case DataTypeSigned8:
601 case DataTypeUnsigned8: {
602 return llvm::Type::getInt8Ty(C);
603 break;
604 }
605 case DataTypeSigned16:
606 case DataTypeUnsigned16:
607 case DataTypeUnsigned565:
608 case DataTypeUnsigned5551:
609 case DataTypeUnsigned4444: {
610 return llvm::Type::getInt16Ty(C);
611 break;
612 }
613 case DataTypeSigned32:
614 case DataTypeUnsigned32: {
615 return llvm::Type::getInt32Ty(C);
616 break;
617 }
618 case DataTypeSigned64: {
619 // case DataTypeUnsigned64:
620 return llvm::Type::getInt64Ty(C);
621 break;
622 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700623 default: {
624 assert(false && "Unknown data type");
625 }
626 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700627
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700628 return NULL;
629}
630
631/**************************** RSExportPointerType ****************************/
632
633const clang::Type *RSExportPointerType::IntegerType = NULL;
634
635RSExportPointerType
636*RSExportPointerType::Create(RSContext *Context,
637 const clang::PointerType *PT,
638 const llvm::StringRef &TypeName) {
639 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
640 const RSExportType *PointeeET;
641
642 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
643 PointeeET = RSExportType::Create(Context, PointeeType);
644 } else {
645 // Double or higher dimension of pointer, export as int*
646 assert(IntegerType != NULL && "Built-in integer type is not set");
647 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
648 }
649
650 if (PointeeET == NULL) {
651 fprintf(stderr, "Failed to create type for pointee");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700652 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700653 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700654
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700655 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700656}
657
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700658RSExportType::ExportClass RSExportPointerType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700659 return RSExportType::ExportClassPointer;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700660}
661
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700662const llvm::Type *RSExportPointerType::convertToLLVMType() const {
663 const llvm::Type *PointeeType = mPointeeType->getLLVMType();
664 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700665}
666
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700667/************************* RSExportConstantArrayType *************************/
668llvm::StringRef
669RSExportConstantArrayType::GetTypeName(const clang::ConstantArrayType *CT) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700670 llvm::APInt i = CT->getSize();
671 if (i == 4) {
672 return llvm::StringRef("rs_matrix2x2");
673 } else if (i == 9) {
674 return llvm::StringRef("rs_matrix3x3");
675 } else if (i == 16) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700676 return llvm::StringRef("rs_matrix4x4");
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700677 }
678 return llvm::StringRef();
679}
680
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700681RSExportConstantArrayType
682*RSExportConstantArrayType::Create(RSContext *Context,
683 const clang::ConstantArrayType *CT,
684 const llvm::StringRef &TypeName,
685 DataKind DK,
686 bool Normalized) {
687 assert(CT != NULL && CT->getTypeClass() == clang::Type::ConstantArray);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700688
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700689 int64_t Size = CT->getSize().getSExtValue();
690 RSExportPrimitiveType::DataType DT;
691 if (Size == 4) {
692 DT = RSExportPrimitiveType::DataTypeRSMatrix2x2;
693 } else if (Size == 9) {
694 DT = RSExportPrimitiveType::DataTypeRSMatrix3x3;
695 } else if (Size == 16) {
696 DT = RSExportPrimitiveType::DataTypeRSMatrix4x4;
697 } else {
698 fprintf(stderr, "RSExportConstantArrayType::Create : unsupported base "
699 "element type\n");
700 return NULL;
701 }
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700702
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700703 return new RSExportConstantArrayType(Context,
704 TypeName,
705 DT,
706 DK,
707 Normalized,
708 Size);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700709}
710
711RSExportType::ExportClass RSExportConstantArrayType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700712 return RSExportType::ExportClassConstantArray;
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700713}
714
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700715const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
716 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700717 const llvm::Type *typ;
718 switch (getType()) {
719 case DataTypeFloat32:
720 case DataTypeRSMatrix2x2:
721 case DataTypeRSMatrix3x3:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700722 case DataTypeRSMatrix4x4: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700723 typ = llvm::Type::getFloatTy(C);
724 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700725 }
726 case DataTypeFloat64: {
Stephen Hines70842c72010-09-20 17:18:10 -0700727 typ = llvm::Type::getDoubleTy(C);
728 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700729 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700730 case DataTypeBoolean: {
731 typ = llvm::Type::getInt1Ty(C);
732 break;
733 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700734 case DataTypeSigned8:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700735 case DataTypeUnsigned8: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700736 typ = llvm::Type::getInt8Ty(C);
737 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700738 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700739 case DataTypeSigned16:
740 case DataTypeUnsigned16:
741 case DataTypeUnsigned565:
742 case DataTypeUnsigned5551:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700743 case DataTypeUnsigned4444: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700744 typ = llvm::Type::getInt16Ty(C);
745 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700746 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700747 case DataTypeSigned32:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700748 case DataTypeUnsigned32: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700749 typ = llvm::Type::getInt32Ty(C);
750 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700751 }
752 case DataTypeSigned64: {
Stephen Hines8d75dc42010-10-01 15:36:03 -0700753 //case DataTypeUnsigned64:
754 typ = llvm::Type::getInt64Ty(C);
755 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700756 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700757 default: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700758 assert(false && "Unknown data type");
759 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700760 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700761 }
762 return llvm::ArrayType::get(typ, mNumElement);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700763}
764
zonr6315f762010-10-05 15:35:14 +0800765/***************************** RSExportVectorType *****************************/
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700766const char* RSExportVectorType::VectorTypeNameStore[][3] = {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700767 /* 0 */ { "char2", "char3", "char4" },
768 /* 1 */ { "uchar2", "uchar3", "uchar4" },
769 /* 2 */ { "short2", "short3", "short4" },
770 /* 3 */ { "ushort2", "ushort3", "ushort4" },
771 /* 4 */ { "int2", "int3", "int4" },
772 /* 5 */ { "uint2", "uint3", "uint4" },
773 /* 6 */ { "float2", "float3", "float4" },
774 /* 7 */ { "double2", "double3", "double4" },
775 /* 8 */ { "long2", "long3", "long4" },
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700776};
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700777
zonr6315f762010-10-05 15:35:14 +0800778llvm::StringRef
779RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700780 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700781
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700782 if ((ElementType->getTypeClass() != clang::Type::Builtin))
783 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700784
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700785 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType,
786 ElementType);
787 const char **BaseElement = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700788
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700789 switch (BT->getKind()) {
790 // Compiler is smart enough to optimize following *big if branches* since
791 // they all become "constant comparison" after macro expansion
792#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
793 case builtin_type: { \
794 if (type == RSExportPrimitiveType::DataTypeSigned8) \
795 BaseElement = VectorTypeNameStore[0]; \
796 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
797 BaseElement = VectorTypeNameStore[1]; \
798 else if (type == RSExportPrimitiveType::DataTypeSigned16) \
799 BaseElement = VectorTypeNameStore[2]; \
800 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
801 BaseElement = VectorTypeNameStore[3]; \
802 else if (type == RSExportPrimitiveType::DataTypeSigned32) \
803 BaseElement = VectorTypeNameStore[4]; \
804 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
805 BaseElement = VectorTypeNameStore[5]; \
806 else if (type == RSExportPrimitiveType::DataTypeFloat32) \
807 BaseElement = VectorTypeNameStore[6]; \
808 else if (type == RSExportPrimitiveType::DataTypeFloat64) \
809 BaseElement = VectorTypeNameStore[7]; \
810 else if (type == RSExportPrimitiveType::DataTypeSigned64) \
811 BaseElement = VectorTypeNameStore[8]; \
Shih-wei Liao91a37832010-10-03 19:11:51 -0700812 else if (type == RSExportPrimitiveType::DataTypeBoolean) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700813 BaseElement = VectorTypeNameStore[0]; \
814 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700815 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700816#include "slang_rs_export_type_support.inc"
817 default: {
818 return llvm::StringRef();
819 }
820 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700821
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700822 if ((BaseElement != NULL) &&
823 (EVT->getNumElements() > 1) &&
824 (EVT->getNumElements() <= 4))
825 return BaseElement[EVT->getNumElements() - 2];
826 else
827 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700828}
829
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700830RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
831 const clang::ExtVectorType *EVT,
832 const llvm::StringRef &TypeName,
833 DataKind DK,
834 bool Normalized) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800835 assert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700836
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700837 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
838 RSExportPrimitiveType::DataType DT =
839 RSExportPrimitiveType::GetDataType(ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700840
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700841 if (DT != RSExportPrimitiveType::DataTypeUnknown)
842 return new RSExportVectorType(Context,
843 TypeName,
844 DT,
845 DK,
846 Normalized,
847 EVT->getNumElements());
848 else
849 fprintf(stderr, "RSExportVectorType::Create : unsupported base element "
850 "type\n");
851 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700852}
853
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700854RSExportType::ExportClass RSExportVectorType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700855 return RSExportType::ExportClassVector;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700856}
857
zonr6315f762010-10-05 15:35:14 +0800858const llvm::Type *RSExportVectorType::convertToLLVMType() const {
859 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700860 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700861}
862
Zonr Chang92b344a2010-10-05 20:39:03 +0800863/***************************** RSExportMatrixType *****************************/
864RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
865 const clang::RecordType *RT,
866 const llvm::StringRef &TypeName,
867 unsigned Dim) {
868 assert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
869 assert((Dim > 1) && "Invalid dimension of matrix");
870
871 // Check whether the struct rs_matrix is in our expected form (but assume it's
872 // correct if we're not sure whether it's correct or not)
873 const clang::RecordDecl* RD = RT->getDecl();
874 RD = RD->getDefinition();
875 if (RD != NULL) {
876 // Find definition, perform further examination
877 if (RD->field_empty()) {
878 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
879 "must have 1 field for saving values", TypeName.data());
880 return NULL;
881 }
882
883 clang::RecordDecl::field_iterator FIT = RD->field_begin();
884 const clang::FieldDecl *FD = *FIT;
885 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
886 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
887 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
888 "first field should be an array with constant size",
889 TypeName.data());
890 return NULL;
891 }
892 const clang::ConstantArrayType *CAT =
893 static_cast<const clang::ConstantArrayType *>(FT);
894 const clang::Type *ElementType =
895 GET_CANONICAL_TYPE(CAT->getElementType().getTypePtr());
896 if ((ElementType == NULL) ||
897 (ElementType->getTypeClass() != clang::Type::Builtin) ||
898 (static_cast<const clang::BuiltinType *>(ElementType)->getKind()
899 != clang::BuiltinType::Float)) {
900 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
901 "first field should be a float array", TypeName.data());
902 return NULL;
903 }
904
905 if (CAT->getSize() != Dim * Dim) {
906 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
907 "first field should be an array with size %d",
908 TypeName.data(), Dim * Dim);
909 return NULL;
910 }
911
912 FIT++;
913 if (FIT != RD->field_end()) {
914 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
915 "must have exactly 1 field", TypeName.data());
916 return NULL;
917 }
918 }
919
920 return new RSExportMatrixType(Context, TypeName, Dim);
921}
922
923RSExportType::ExportClass RSExportMatrixType::getClass() const {
924 return RSExportType::ExportClassMatrix;
925}
926
927const llvm::Type *RSExportMatrixType::convertToLLVMType() const {
928 // Construct LLVM type:
929 // struct {
930 // float X[mDim * mDim];
931 // }
932
933 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
934 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
935 mDim * mDim);
936 return llvm::StructType::get(C, X, NULL);
937}
938
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700939/**************************** RSExportRecordType ****************************/
940RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
941 const clang::RecordType *RT,
942 const llvm::StringRef &TypeName,
943 bool mIsArtificial) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800944 assert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700945
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700946 const clang::RecordDecl *RD = RT->getDecl();
947 assert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700948
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700949 RD = RD->getDefinition();
950 if (RD == NULL) {
zonr6315f762010-10-05 15:35:14 +0800951 // TODO(zonr): warn that actual struct definition isn't declared in this
952 // moudle.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700953 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined "
954 "in this module.");
955 return NULL;
956 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700957
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800958 // Struct layout construct by clang. We rely on this for obtaining the
959 // alloc size of a struct and offset of every field in that struct.
960 const clang::ASTRecordLayout *RL =
961 &Context->getASTContext()->getASTRecordLayout(RD);
962 assert((RL != NULL) && "Failed to retrieve the struct layout from Clang.");
963
964 RSExportRecordType *ERT =
965 new RSExportRecordType(Context,
966 TypeName,
967 RD->hasAttr<clang::PackedAttr>(),
968 mIsArtificial,
969 (RL->getSize() >> 3));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700970 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700971
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700972 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
973 FE = RD->field_end();
974 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -0700975 FI++, Index++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700976#define FAILED_CREATE_FIELD(err) do { \
977 if (*err) \
978 fprintf(stderr, \
979 "RSExportRecordType::Create : failed to create field (%s)\n", \
980 err); \
981 delete ERT; \
982 return NULL; \
983 } while (false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700984
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700985 // FIXME: All fields should be primitive type
986 assert((*FI)->getKind() == clang::Decl::Field);
987 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700988
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700989 // We don't support bit field
990 //
zonr6315f762010-10-05 15:35:14 +0800991 // TODO(zonr): allow bitfield with size 8, 16, 32
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700992 if (FD->isBitField())
993 FAILED_CREATE_FIELD("bit field is not supported");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700994
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700995 // Type
zonr6315f762010-10-05 15:35:14 +0800996 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700997
zonr6315f762010-10-05 15:35:14 +0800998 if (ET != NULL)
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800999 ERT->mFields.push_back(
1000 new Field(ET, FD->getName(), ERT,
1001 static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001002 else
1003 FAILED_CREATE_FIELD(FD->getName().str().c_str());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001004#undef FAILED_CREATE_FIELD
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001005 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001006
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001007 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001008}
1009
1010RSExportType::ExportClass RSExportRecordType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001011 return RSExportType::ExportClassRecord;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001012}
1013
zonr6315f762010-10-05 15:35:14 +08001014const llvm::Type *RSExportRecordType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001015 std::vector<const llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001016
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001017 for (const_field_iterator FI = fields_begin(),
1018 FE = fields_end();
1019 FI != FE;
1020 FI++) {
1021 const Field *F = *FI;
1022 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -07001023
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001024 FieldTypes.push_back(FET->getLLVMType());
1025 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001026
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001027 return llvm::StructType::get(getRSContext()->getLLVMContext(),
1028 FieldTypes,
1029 mIsPacked);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001030}