blob: 9e7fe9ecaae5acb4e7681c529c4d16cceb413c06 [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) {
39 if (DD && DD->getTypeSourceInfo()) {
40 clang::QualType T = DD->getTypeSourceInfo()->getType();
41 if (T.isNull())
42 return NULL;
43 else
44 return T.getTypePtr();
45 }
46 return NULL;
47}
48
49llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
50 T = GET_CANONICAL_TYPE(T);
51 if (T == NULL)
52 return llvm::StringRef();
53
54 switch (T->getTypeClass()) {
55 case clang::Type::Builtin: {
56 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
57
58 switch (BT->getKind()) {
59 // Compiler is smart enough to optimize following *big if branches*
60 // since they all become "constant comparison" after macro expansion
61#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
62 case builtin_type: { \
63 if (type == RSExportPrimitiveType::DataTypeFloat32) \
64 return "float"; \
65 else if (type == RSExportPrimitiveType::DataTypeFloat64) \
66 return "double"; \
67 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
68 return "uchar"; \
69 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
70 return "ushort"; \
71 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
72 return "uint"; \
73 else if (type == RSExportPrimitiveType::DataTypeSigned8) \
74 return "char"; \
75 else if (type == RSExportPrimitiveType::DataTypeSigned16) \
76 return "short"; \
77 else if (type == RSExportPrimitiveType::DataTypeSigned32) \
78 return "int"; \
zonr6315f762010-10-05 15:35:14 +080079 else if (type == RSExportPrimitiveType::DataTypeSigned64) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070080 return "long"; \
Shih-wei Liao91a37832010-10-03 19:11:51 -070081 else if (type == RSExportPrimitiveType::DataTypeBoolean) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070082 return "bool"; \
83 else \
84 assert(false && "Unknow data type of supported builtin"); \
85 break; \
86 }
87#include "slang_rs_export_type_support.inc"
88
89 default: {
90 assert(false && "Unknown data type of the builtin");
91 break;
92 }
93 }
94 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070095 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070096 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
zonr6315f762010-10-05 15:35:14 +0800103 if (Name.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700104 // 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 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700118 case clang::Type::Pointer: {
119 // "*" plus pointee name
zonr6315f762010-10-05 15:35:14 +0800120 const clang::Type *PT = GET_POINTEE_TYPE(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700121 llvm::StringRef PointeeName;
122 if (NormalizeType(PT, PointeeName)) {
123 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
124 Name[0] = '*';
125 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
126 Name[PointeeName.size() + 1] = '\0';
127 return Name;
128 }
129 break;
130 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700131 case clang::Type::ConstantArray: {
132 const clang::ConstantArrayType *ECT =
133 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
134 return RSExportConstantArrayType::GetTypeName(ECT);
135 break;
136 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700137 case clang::Type::ExtVector: {
138 const clang::ExtVectorType *EVT =
139 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
140 return RSExportVectorType::GetTypeName(EVT);
141 break;
142 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700143 default: {
144 break;
145 }
146 }
147
148 return llvm::StringRef();
149}
150
151const clang::Type *RSExportType::TypeExportable(
152 const clang::Type *T,
153 llvm::SmallPtrSet<const clang::Type*, 8>& SPS) {
154 // Normalize first
155 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
156 return NULL;
157
158 if (SPS.count(T))
159 return T;
160
161 switch (T->getTypeClass()) {
162 case clang::Type::Builtin: {
163 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
164
165 switch (BT->getKind()) {
166#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
167 case builtin_type:
168#include "slang_rs_export_type_support.inc"
169 {
170 return T;
171 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700172 default: {
173 return NULL;
174 }
175 }
176 // Never be here
177 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700178 case clang::Type::Record: {
179 if (RSExportPrimitiveType::GetRSObjectType(T) !=
180 RSExportPrimitiveType::DataTypeUnknown)
zonr6315f762010-10-05 15:35:14 +0800181 return T; // RS object type, no further checks are needed
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182
183 // Check internal struct
184 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
185 if (RD != NULL)
186 RD = RD->getDefinition();
187
188 // Fast check
189 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
190 return NULL;
191
192 // Insert myself into checking set
193 SPS.insert(T);
194
195 // Check all element
196 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
197 FE = RD->field_end();
198 FI != FE;
199 FI++) {
zonr6315f762010-10-05 15:35:14 +0800200 const clang::Type *FT = GetTypeOfDecl(*FI);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700201 FT = GET_CANONICAL_TYPE(FT);
202
203 if (!TypeExportable(FT, SPS))
zonr6315f762010-10-05 15:35:14 +0800204 // TODO(zonr): warn that is's an unsupported field type
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700205 return NULL;
206 }
207
208 return T;
209 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700210 case clang::Type::Pointer: {
211 const clang::PointerType *PT = UNSAFE_CAST_TYPE(clang::PointerType, T);
212 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
213
214 if ((PointeeType->getTypeClass() != clang::Type::Pointer) &&
215 (TypeExportable(PointeeType, SPS) == NULL) )
216 return NULL;
217 else
218 return T;
219 }
220
221 case clang::Type::ConstantArray: {
222 const clang::ConstantArrayType *ECT =
223 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
224 // No longer only support 2x2, 3x3 and 4x4 arrays
225 // if (ECT->getNumElements() != 4 &&
226 // ECT->getNumElements() != 9 &&
227 // ECT->getNumElements() != 16)
228 // return NULL;
229
230 // Check base element type
231 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(ECT);
232
233 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
234 (TypeExportable(ElementType, SPS) == NULL))
235 return NULL;
236 else
237 return T;
238 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700239 case clang::Type::ExtVector: {
240 const clang::ExtVectorType *EVT =
241 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
242 // Only vector with size 2, 3 and 4 are supported.
243 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
244 return NULL;
245
246 // Check base element type
247 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
248
249 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
250 (TypeExportable(ElementType, SPS) == NULL))
251 return NULL;
252 else
253 return T;
254 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700255 default: {
256 return NULL;
257 }
258 }
259}
260
261RSExportType *RSExportType::Create(RSContext *Context,
262 const clang::Type *T,
263 const llvm::StringRef &TypeName) {
264 // Lookup the context to see whether the type was processed before.
265 // Newly created RSExportType will insert into context
266 // in RSExportType::RSExportType()
267 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
268
269 if (ETI != Context->export_types_end())
270 return ETI->second;
271
272 RSExportType *ET = NULL;
273 switch (T->getTypeClass()) {
274 case clang::Type::Record: {
275 RSExportPrimitiveType::DataType dt =
276 RSExportPrimitiveType::GetRSObjectType(TypeName);
277 switch (dt) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800278 case RSExportPrimitiveType::DataTypeUnknown: {
279 // User-defined types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700280 ET = RSExportRecordType::Create(Context,
281 T->getAsStructureType(),
282 TypeName);
283 break;
284 }
Zonr Chang92b344a2010-10-05 20:39:03 +0800285 case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
286 // 2 x 2 Matrix type
287 ET = RSExportMatrixType::Create(Context,
288 T->getAsStructureType(),
289 TypeName,
290 2);
291 break;
292 }
293 case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
294 // 3 x 3 Matrix type
295 ET = RSExportMatrixType::Create(Context,
296 T->getAsStructureType(),
297 TypeName,
298 3);
299 break;
300 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800302 // 4 x 4 Matrix type
303 ET = RSExportMatrixType::Create(Context,
304 T->getAsStructureType(),
305 TypeName,
306 4);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700307 break;
308 }
309 default: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800310 // Others are primitive types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700311 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);
Zonr Chang92b344a2010-10-05 20:39:03 +0800325 // FIXME: free the name (allocated in RSExportType::GetTypeName)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700326 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: {
zonr6315f762010-10-05 15:35:14 +0800343 // TODO(zonr): warn that type is not exportable.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700344 fprintf(stderr,
345 "RSExportType::Create : type '%s' is not exportable\n",
346 T->getTypeClassName());
347 break;
348 }
349 }
350
351 return ET;
352}
353
zonr6315f762010-10-05 15:35:14 +0800354RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700355 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(
zonr6315f762010-10-05 15:35:14 +0800369 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700370}
371
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700372size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
373 if (ET->getClass() == RSExportType::ExportClassRecord)
374 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
375 else
376 return ET->getRSContext()->getTargetData()->getTypeAllocSize(
zonr6315f762010-10-05 15:35:14 +0800377 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700378}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700379
zonr6315f762010-10-05 15:35:14 +0800380RSExportType::RSExportType(RSContext *Context, const llvm::StringRef &Name)
381 : mContext(Context),
382 // Make a copy on Name since data of @Name which is stored in ASTContext
383 // will be destroyed later
384 mName(Name.data(), Name.size()),
385 mLLVMType(NULL) {
386 // TODO(zonr): Need to check whether the insertion is successful or not.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700387 Context->insertExportType(Name, this);
388 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700389}
390
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700391/************************** RSExportPrimitiveType **************************/
392RSExportPrimitiveType::RSObjectTypeMapTy
393*RSExportPrimitiveType::RSObjectTypeMap = NULL;
394
zonr6315f762010-10-05 15:35:14 +0800395llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700396
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700397bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
398 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
399 return true;
400 else
401 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700402}
403
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700404RSExportPrimitiveType::DataType
405RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef &TypeName) {
406 if (TypeName.empty())
407 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700408
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700409 if (RSObjectTypeMap == NULL) {
410 RSObjectTypeMap = new RSObjectTypeMapTy(16);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700411
412#define USE_ELEMENT_DATA_TYPE
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700413#define DEF_RS_OBJECT_TYPE(type, name) \
414 RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700415#include "slang_rs_export_element_support.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700416 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700417
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700418 RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
419 if (I == RSObjectTypeMap->end())
420 return DataTypeUnknown;
421 else
422 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700423}
424
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700425RSExportPrimitiveType::DataType
426RSExportPrimitiveType::GetRSObjectType(const clang::Type *T) {
427 T = GET_CANONICAL_TYPE(T);
428 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
429 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700430
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700431 return GetRSObjectType( RSExportType::GetTypeName(T) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700432}
433
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700434const size_t
435RSExportPrimitiveType::SizeOfDataTypeInBits[
436 RSExportPrimitiveType::DataTypeMax + 1] = {
zonr6315f762010-10-05 15:35:14 +0800437 16, // DataTypeFloat16
438 32, // DataTypeFloat32
439 64, // DataTypeFloat64
440 8, // DataTypeSigned8
441 16, // DataTypeSigned16
442 32, // DataTypeSigned32
443 64, // DataTypeSigned64
444 8, // DataTypeUnsigned8
445 16, // DataTypeUnsigned16
446 32, // DataTypeUnsigned32
447 64, // DataTypeUnSigned64
448 1, // DataTypeBoolean
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700449
zonr6315f762010-10-05 15:35:14 +0800450 16, // DataTypeUnsigned565
451 16, // DataTypeUnsigned5551
452 16, // DataTypeUnsigned4444
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700453
zonr6315f762010-10-05 15:35:14 +0800454 128, // DataTypeRSMatrix2x2
455 288, // DataTypeRSMatrix3x3
456 512, // DataTypeRSMatrix4x4
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700457
zonr6315f762010-10-05 15:35:14 +0800458 32, // DataTypeRSElement
459 32, // DataTypeRSType
460 32, // DataTypeRSAllocation
461 32, // DataTypeRSSampler
462 32, // DataTypeRSScript
463 32, // DataTypeRSMesh
464 32, // DataTypeRSProgramFragment
465 32, // DataTypeRSProgramVertex
466 32, // DataTypeRSProgramRaster
467 32, // DataTypeRSProgramStore
468 32, // DataTypeRSFont
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700469 0
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700470};
471
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700472size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
473 assert(((EPT->getType() >= DataTypeFloat32) &&
474 (EPT->getType() < DataTypeMax)) &&
475 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
476 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700477}
478
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700479RSExportPrimitiveType::DataType
zonr6315f762010-10-05 15:35:14 +0800480RSExportPrimitiveType::GetDataType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700481 if (T == NULL)
482 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700483
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700484 switch (T->getTypeClass()) {
485 case clang::Type::Builtin: {
486 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
487 switch (BT->getKind()) {
488#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
489 case builtin_type: { \
490 return type; \
491 break; \
492 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700493#include "slang_rs_export_type_support.inc"
494
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700495 // The size of types Long, ULong and WChar depend on platform so we
496 // abandon the support to them. Type of its size exceeds 32 bits (e.g.
497 // int64_t, double, etc.): no support
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700498
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700499 default: {
zonr6315f762010-10-05 15:35:14 +0800500 // TODO(zonr): warn that the type is unsupported
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700501 fprintf(stderr, "RSExportPrimitiveType::GetDataType : built-in type "
502 "has no corresponding data type for built-in type");
503 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700504 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700505 }
506 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700507 }
508
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700509 case clang::Type::Record: {
510 // must be RS object type
511 return RSExportPrimitiveType::GetRSObjectType(T);
512 break;
513 }
514
515 default: {
516 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not "
517 "supported primitive type", T->getTypeClassName());
518 break;
519 }
520 }
521
522 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700523}
524
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700525RSExportPrimitiveType
526*RSExportPrimitiveType::Create(RSContext *Context,
527 const clang::Type *T,
528 const llvm::StringRef &TypeName,
529 DataKind DK,
530 bool Normalized) {
531 DataType DT = GetDataType(T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700532
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700533 if ((DT == DataTypeUnknown) || TypeName.empty())
534 return NULL;
535 else
536 return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700537}
538
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700539RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
540 const clang::Type *T,
541 DataKind DK) {
542 llvm::StringRef TypeName;
543 if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
544 return Create(Context, T, TypeName, DK);
545 else
546 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700547}
548
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700549RSExportType::ExportClass RSExportPrimitiveType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700550 return RSExportType::ExportClassPrimitive;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700551}
552
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700553const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
554 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700555
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700556 if (isRSObjectType()) {
557 // struct {
558 // int *p;
559 // } __attribute__((packed, aligned(pointer_size)))
560 //
561 // which is
562 //
563 // <{ [1 x i32] }> in LLVM
564 //
565 if (RSObjectLLVMType == NULL) {
566 std::vector<const llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +0800567 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700568 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700569 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700570 return RSObjectLLVMType;
571 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700572
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700573 switch (mType) {
574 case DataTypeFloat32: {
575 return llvm::Type::getFloatTy(C);
576 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700577 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700578 case DataTypeFloat64: {
579 return llvm::Type::getDoubleTy(C);
580 break;
581 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700582 case DataTypeBoolean: {
583 return llvm::Type::getInt1Ty(C);
584 break;
585 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700586 case DataTypeSigned8:
587 case DataTypeUnsigned8: {
588 return llvm::Type::getInt8Ty(C);
589 break;
590 }
591 case DataTypeSigned16:
592 case DataTypeUnsigned16:
593 case DataTypeUnsigned565:
594 case DataTypeUnsigned5551:
595 case DataTypeUnsigned4444: {
596 return llvm::Type::getInt16Ty(C);
597 break;
598 }
599 case DataTypeSigned32:
600 case DataTypeUnsigned32: {
601 return llvm::Type::getInt32Ty(C);
602 break;
603 }
604 case DataTypeSigned64: {
605 // case DataTypeUnsigned64:
606 return llvm::Type::getInt64Ty(C);
607 break;
608 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700609 default: {
610 assert(false && "Unknown data type");
611 }
612 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700613
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700614 return NULL;
615}
616
617/**************************** RSExportPointerType ****************************/
618
619const clang::Type *RSExportPointerType::IntegerType = NULL;
620
621RSExportPointerType
622*RSExportPointerType::Create(RSContext *Context,
623 const clang::PointerType *PT,
624 const llvm::StringRef &TypeName) {
625 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
626 const RSExportType *PointeeET;
627
628 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
629 PointeeET = RSExportType::Create(Context, PointeeType);
630 } else {
631 // Double or higher dimension of pointer, export as int*
632 assert(IntegerType != NULL && "Built-in integer type is not set");
633 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
634 }
635
636 if (PointeeET == NULL) {
637 fprintf(stderr, "Failed to create type for pointee");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700638 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700639 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700640
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700641 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700642}
643
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700644RSExportType::ExportClass RSExportPointerType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700645 return RSExportType::ExportClassPointer;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700646}
647
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700648const llvm::Type *RSExportPointerType::convertToLLVMType() const {
649 const llvm::Type *PointeeType = mPointeeType->getLLVMType();
650 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700651}
652
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700653/************************* RSExportConstantArrayType *************************/
654llvm::StringRef
655RSExportConstantArrayType::GetTypeName(const clang::ConstantArrayType *CT) {
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700656 llvm::APInt i = CT->getSize();
657 if (i == 4) {
658 return llvm::StringRef("rs_matrix2x2");
659 } else if (i == 9) {
660 return llvm::StringRef("rs_matrix3x3");
661 } else if (i == 16) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700662 return llvm::StringRef("rs_matrix4x4");
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700663 }
664 return llvm::StringRef();
665}
666
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700667RSExportConstantArrayType
668*RSExportConstantArrayType::Create(RSContext *Context,
669 const clang::ConstantArrayType *CT,
670 const llvm::StringRef &TypeName,
671 DataKind DK,
672 bool Normalized) {
673 assert(CT != NULL && CT->getTypeClass() == clang::Type::ConstantArray);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700674
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700675 int64_t Size = CT->getSize().getSExtValue();
676 RSExportPrimitiveType::DataType DT;
677 if (Size == 4) {
678 DT = RSExportPrimitiveType::DataTypeRSMatrix2x2;
679 } else if (Size == 9) {
680 DT = RSExportPrimitiveType::DataTypeRSMatrix3x3;
681 } else if (Size == 16) {
682 DT = RSExportPrimitiveType::DataTypeRSMatrix4x4;
683 } else {
684 fprintf(stderr, "RSExportConstantArrayType::Create : unsupported base "
685 "element type\n");
686 return NULL;
687 }
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700688
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700689 return new RSExportConstantArrayType(Context,
690 TypeName,
691 DT,
692 DK,
693 Normalized,
694 Size);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700695}
696
697RSExportType::ExportClass RSExportConstantArrayType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700698 return RSExportType::ExportClassConstantArray;
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700699}
700
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700701const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
702 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700703 const llvm::Type *typ;
704 switch (getType()) {
705 case DataTypeFloat32:
706 case DataTypeRSMatrix2x2:
707 case DataTypeRSMatrix3x3:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700708 case DataTypeRSMatrix4x4: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700709 typ = llvm::Type::getFloatTy(C);
710 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700711 }
712 case DataTypeFloat64: {
Stephen Hines70842c72010-09-20 17:18:10 -0700713 typ = llvm::Type::getDoubleTy(C);
714 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700715 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700716 case DataTypeBoolean: {
717 typ = llvm::Type::getInt1Ty(C);
718 break;
719 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700720 case DataTypeSigned8:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700721 case DataTypeUnsigned8: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700722 typ = llvm::Type::getInt8Ty(C);
723 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700724 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700725 case DataTypeSigned16:
726 case DataTypeUnsigned16:
727 case DataTypeUnsigned565:
728 case DataTypeUnsigned5551:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700729 case DataTypeUnsigned4444: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700730 typ = llvm::Type::getInt16Ty(C);
731 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700732 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700733 case DataTypeSigned32:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700734 case DataTypeUnsigned32: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700735 typ = llvm::Type::getInt32Ty(C);
736 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700737 }
738 case DataTypeSigned64: {
Stephen Hines8d75dc42010-10-01 15:36:03 -0700739 //case DataTypeUnsigned64:
740 typ = llvm::Type::getInt64Ty(C);
741 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700742 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700743 default: {
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700744 assert(false && "Unknown data type");
745 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700746 }
Shih-wei Liao1ebc0ca2010-09-14 10:57:21 -0700747 }
748 return llvm::ArrayType::get(typ, mNumElement);
Shih-wei Liaof8149d92010-08-22 05:32:02 -0700749}
750
zonr6315f762010-10-05 15:35:14 +0800751/***************************** RSExportVectorType *****************************/
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700752const char* RSExportVectorType::VectorTypeNameStore[][3] = {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700753 /* 0 */ { "char2", "char3", "char4" },
754 /* 1 */ { "uchar2", "uchar3", "uchar4" },
755 /* 2 */ { "short2", "short3", "short4" },
756 /* 3 */ { "ushort2", "ushort3", "ushort4" },
757 /* 4 */ { "int2", "int3", "int4" },
758 /* 5 */ { "uint2", "uint3", "uint4" },
759 /* 6 */ { "float2", "float3", "float4" },
760 /* 7 */ { "double2", "double3", "double4" },
761 /* 8 */ { "long2", "long3", "long4" },
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700762};
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700763
zonr6315f762010-10-05 15:35:14 +0800764llvm::StringRef
765RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700766 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700767
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700768 if ((ElementType->getTypeClass() != clang::Type::Builtin))
769 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700770
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700771 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType,
772 ElementType);
773 const char **BaseElement = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700774
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700775 switch (BT->getKind()) {
776 // Compiler is smart enough to optimize following *big if branches* since
777 // they all become "constant comparison" after macro expansion
778#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type) \
779 case builtin_type: { \
780 if (type == RSExportPrimitiveType::DataTypeSigned8) \
781 BaseElement = VectorTypeNameStore[0]; \
782 else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
783 BaseElement = VectorTypeNameStore[1]; \
784 else if (type == RSExportPrimitiveType::DataTypeSigned16) \
785 BaseElement = VectorTypeNameStore[2]; \
786 else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
787 BaseElement = VectorTypeNameStore[3]; \
788 else if (type == RSExportPrimitiveType::DataTypeSigned32) \
789 BaseElement = VectorTypeNameStore[4]; \
790 else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
791 BaseElement = VectorTypeNameStore[5]; \
792 else if (type == RSExportPrimitiveType::DataTypeFloat32) \
793 BaseElement = VectorTypeNameStore[6]; \
794 else if (type == RSExportPrimitiveType::DataTypeFloat64) \
795 BaseElement = VectorTypeNameStore[7]; \
796 else if (type == RSExportPrimitiveType::DataTypeSigned64) \
797 BaseElement = VectorTypeNameStore[8]; \
Shih-wei Liao91a37832010-10-03 19:11:51 -0700798 else if (type == RSExportPrimitiveType::DataTypeBoolean) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700799 BaseElement = VectorTypeNameStore[0]; \
800 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700801 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700802#include "slang_rs_export_type_support.inc"
803 default: {
804 return llvm::StringRef();
805 }
806 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700807
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700808 if ((BaseElement != NULL) &&
809 (EVT->getNumElements() > 1) &&
810 (EVT->getNumElements() <= 4))
811 return BaseElement[EVT->getNumElements() - 2];
812 else
813 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700814}
815
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700816RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
817 const clang::ExtVectorType *EVT,
818 const llvm::StringRef &TypeName,
819 DataKind DK,
820 bool Normalized) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800821 assert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700822
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700823 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
824 RSExportPrimitiveType::DataType DT =
825 RSExportPrimitiveType::GetDataType(ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700826
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700827 if (DT != RSExportPrimitiveType::DataTypeUnknown)
828 return new RSExportVectorType(Context,
829 TypeName,
830 DT,
831 DK,
832 Normalized,
833 EVT->getNumElements());
834 else
835 fprintf(stderr, "RSExportVectorType::Create : unsupported base element "
836 "type\n");
837 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700838}
839
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700840RSExportType::ExportClass RSExportVectorType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700841 return RSExportType::ExportClassVector;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700842}
843
zonr6315f762010-10-05 15:35:14 +0800844const llvm::Type *RSExportVectorType::convertToLLVMType() const {
845 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700846 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700847}
848
Zonr Chang92b344a2010-10-05 20:39:03 +0800849/***************************** RSExportMatrixType *****************************/
850RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
851 const clang::RecordType *RT,
852 const llvm::StringRef &TypeName,
853 unsigned Dim) {
854 assert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
855 assert((Dim > 1) && "Invalid dimension of matrix");
856
857 // Check whether the struct rs_matrix is in our expected form (but assume it's
858 // correct if we're not sure whether it's correct or not)
859 const clang::RecordDecl* RD = RT->getDecl();
860 RD = RD->getDefinition();
861 if (RD != NULL) {
862 // Find definition, perform further examination
863 if (RD->field_empty()) {
864 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
865 "must have 1 field for saving values", TypeName.data());
866 return NULL;
867 }
868
869 clang::RecordDecl::field_iterator FIT = RD->field_begin();
870 const clang::FieldDecl *FD = *FIT;
871 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
872 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
873 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
874 "first field should be an array with constant size",
875 TypeName.data());
876 return NULL;
877 }
878 const clang::ConstantArrayType *CAT =
879 static_cast<const clang::ConstantArrayType *>(FT);
880 const clang::Type *ElementType =
881 GET_CANONICAL_TYPE(CAT->getElementType().getTypePtr());
882 if ((ElementType == NULL) ||
883 (ElementType->getTypeClass() != clang::Type::Builtin) ||
884 (static_cast<const clang::BuiltinType *>(ElementType)->getKind()
885 != clang::BuiltinType::Float)) {
886 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
887 "first field should be a float array", TypeName.data());
888 return NULL;
889 }
890
891 if (CAT->getSize() != Dim * Dim) {
892 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
893 "first field should be an array with size %d",
894 TypeName.data(), Dim * Dim);
895 return NULL;
896 }
897
898 FIT++;
899 if (FIT != RD->field_end()) {
900 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
901 "must have exactly 1 field", TypeName.data());
902 return NULL;
903 }
904 }
905
906 return new RSExportMatrixType(Context, TypeName, Dim);
907}
908
909RSExportType::ExportClass RSExportMatrixType::getClass() const {
910 return RSExportType::ExportClassMatrix;
911}
912
913const llvm::Type *RSExportMatrixType::convertToLLVMType() const {
914 // Construct LLVM type:
915 // struct {
916 // float X[mDim * mDim];
917 // }
918
919 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
920 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
921 mDim * mDim);
922 return llvm::StructType::get(C, X, NULL);
923}
924
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700925/**************************** RSExportRecordType ****************************/
926RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
927 const clang::RecordType *RT,
928 const llvm::StringRef &TypeName,
929 bool mIsArtificial) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800930 assert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700931
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700932 const clang::RecordDecl *RD = RT->getDecl();
933 assert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700934
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700935 RD = RD->getDefinition();
936 if (RD == NULL) {
zonr6315f762010-10-05 15:35:14 +0800937 // TODO(zonr): warn that actual struct definition isn't declared in this
938 // moudle.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700939 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined "
940 "in this module.");
941 return NULL;
942 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700943
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700944 RSExportRecordType *ERT = new RSExportRecordType(Context,
945 TypeName,
946 RD->
947 hasAttr<clang::PackedAttr>(),
948 mIsArtificial);
949 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700950
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700951 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
952 FE = RD->field_end();
953 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -0700954 FI++, Index++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700955#define FAILED_CREATE_FIELD(err) do { \
956 if (*err) \
957 fprintf(stderr, \
958 "RSExportRecordType::Create : failed to create field (%s)\n", \
959 err); \
960 delete ERT; \
961 return NULL; \
962 } while (false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700963
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700964 // FIXME: All fields should be primitive type
965 assert((*FI)->getKind() == clang::Decl::Field);
966 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700967
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700968 // We don't support bit field
969 //
zonr6315f762010-10-05 15:35:14 +0800970 // TODO(zonr): allow bitfield with size 8, 16, 32
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700971 if (FD->isBitField())
972 FAILED_CREATE_FIELD("bit field is not supported");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700973
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700974 // Type
zonr6315f762010-10-05 15:35:14 +0800975 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700976
zonr6315f762010-10-05 15:35:14 +0800977 if (ET != NULL)
978 ERT->mFields.push_back(new Field(ET, FD->getName(), ERT, Index));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700979 else
980 FAILED_CREATE_FIELD(FD->getName().str().c_str());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700981#undef FAILED_CREATE_FIELD
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700982 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700983
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700984 const clang::ASTRecordLayout &ASTRL =
985 Context->getASTContext()->getASTRecordLayout(RD);
986 ERT->AllocSize =
987 (ASTRL.getSize() > ASTRL.getDataSize()) ?
988 (ASTRL.getSize() >> 3) :
989 (ASTRL.getDataSize() >> 3);
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -0700990
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700991 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700992}
993
994RSExportType::ExportClass RSExportRecordType::getClass() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700995 return RSExportType::ExportClassRecord;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700996}
997
zonr6315f762010-10-05 15:35:14 +0800998const llvm::Type *RSExportRecordType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700999 std::vector<const llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001000
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001001 for (const_field_iterator FI = fields_begin(),
1002 FE = fields_end();
1003 FI != FE;
1004 FI++) {
1005 const Field *F = *FI;
1006 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -07001007
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001008 FieldTypes.push_back(FET->getLLVMType());
1009 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001010
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001011 return llvm::StructType::get(getRSContext()->getLLVMContext(),
1012 FieldTypes,
1013 mIsPacked);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001014}
1015
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001016/************************* RSExportRecordType::Field *************************/
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001017size_t RSExportRecordType::Field::getOffsetInParent() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001018 // Struct layout obtains below will be cached by LLVM
1019 const llvm::StructLayout *SL =
1020 mParent->getRSContext()->getTargetData()->getStructLayout(
zonr6315f762010-10-05 15:35:14 +08001021 static_cast<const llvm::StructType*>(mParent->getLLVMType()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001022 return SL->getElementOffset(mIndex);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001023}