blob: 300d5f4365797e454d1f77f54b9e44870529ae24 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
zonr6315f762010-10-05 15:35:14 +080017#include "slang_rs_export_type.h"
18
19#include <vector>
Shih-wei Liao462aefd2010-06-04 15:32:04 -070020
21#include "llvm/Type.h"
22#include "llvm/DerivedTypes.h"
23
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024#include "llvm/ADT/StringExtras.h"
25#include "llvm/Target/TargetData.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070026
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070027#include "clang/AST/RecordLayout.h"
28
zonr6315f762010-10-05 15:35:14 +080029#include "slang_rs_context.h"
30#include "slang_rs_export_element.h"
Zonr Changa7a828d2010-10-22 03:44:27 +080031#include "slang_rs_type_spec.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070032
Zonr Chang641558f2010-10-12 21:07:06 +080033#define CHECK_PARENT_EQUALITY(ParentClass, E) \
34 if (!ParentClass::equals(E)) \
35 return false;
36
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070037using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070038
39/****************************** RSExportType ******************************/
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070040bool RSExportType::NormalizeType(const clang::Type *&T,
41 llvm::StringRef &TypeName) {
42 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
43 llvm::SmallPtrSet<const clang::Type*, 8>();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070045 if ((T = RSExportType::TypeExportable(T, SPS)) == NULL)
zonr6315f762010-10-05 15:35:14 +080046 // TODO(zonr): warn that type not exportable.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070047 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070048
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070049 // Get type name
50 TypeName = RSExportType::GetTypeName(T);
51 if (TypeName.empty())
zonr6315f762010-10-05 15:35:14 +080052 // TODO(zonr): warning that the type is unnamed.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070053 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070054
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070055 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070056}
57
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070058const clang::Type
59*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +080060 if (DD) {
61 clang::QualType T;
62 if (DD->getTypeSourceInfo())
63 T = DD->getTypeSourceInfo()->getType();
64 else
65 T = DD->getType();
66
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070067 if (T.isNull())
68 return NULL;
69 else
70 return T.getTypePtr();
71 }
72 return NULL;
73}
74
75llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
76 T = GET_CANONICAL_TYPE(T);
77 if (T == NULL)
78 return llvm::StringRef();
79
80 switch (T->getTypeClass()) {
81 case clang::Type::Builtin: {
82 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
83
84 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +080085#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
86 case builtin_type: \
87 return cname; \
88 break;
89#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +080090 default: {
91 assert(false && "Unknown data type of the builtin");
92 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070093 }
Zonr Changa65ec162010-10-17 01:53:05 +080094 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070095 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097 case clang::Type::Record: {
98 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
99 llvm::StringRef Name = RD->getName();
100 if (Name.empty()) {
101 if (RD->getTypedefForAnonDecl() != NULL)
102 Name = RD->getTypedefForAnonDecl()->getName();
103
zonr6315f762010-10-05 15:35:14 +0800104 if (Name.empty())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700105 // Try to find a name from redeclaration (i.e. typedef)
106 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
107 RE = RD->redecls_end();
108 RI != RE;
109 RI++) {
110 assert(*RI != NULL && "cannot be NULL object");
111
112 Name = (*RI)->getName();
113 if (!Name.empty())
114 break;
115 }
116 }
117 return Name;
118 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700119 case clang::Type::Pointer: {
120 // "*" plus pointee name
zonr6315f762010-10-05 15:35:14 +0800121 const clang::Type *PT = GET_POINTEE_TYPE(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700122 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 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700132 case clang::Type::ExtVector: {
133 const clang::ExtVectorType *EVT =
134 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
135 return RSExportVectorType::GetTypeName(EVT);
136 break;
137 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800138 case clang::Type::ConstantArray : {
139 // Construct name for a constant array is too complicated.
140 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE;
141 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 default: {
143 break;
144 }
145 }
146
147 return llvm::StringRef();
148}
149
150const clang::Type *RSExportType::TypeExportable(
151 const clang::Type *T,
152 llvm::SmallPtrSet<const clang::Type*, 8>& SPS) {
153 // Normalize first
154 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
155 return NULL;
156
157 if (SPS.count(T))
158 return T;
159
160 switch (T->getTypeClass()) {
161 case clang::Type::Builtin: {
162 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
163
164 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800165#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700166 case builtin_type:
Zonr Changa65ec162010-10-17 01:53:05 +0800167#include "RSClangBuiltinEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700168 return T;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700169 default: {
170 return NULL;
171 }
172 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700173 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700174 case clang::Type::Record: {
175 if (RSExportPrimitiveType::GetRSObjectType(T) !=
176 RSExportPrimitiveType::DataTypeUnknown)
zonr6315f762010-10-05 15:35:14 +0800177 return T; // RS object type, no further checks are needed
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700178
179 // Check internal struct
180 const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
181 if (RD != NULL)
182 RD = RD->getDefinition();
183
184 // Fast check
185 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
186 return NULL;
187
188 // Insert myself into checking set
189 SPS.insert(T);
190
191 // Check all element
192 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
193 FE = RD->field_end();
194 FI != FE;
195 FI++) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800196 const clang::FieldDecl *FD = *FI;
197 const clang::Type *FT = GetTypeOfDecl(FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700198 FT = GET_CANONICAL_TYPE(FT);
199
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800200 if (!TypeExportable(FT, SPS)) {
201 fprintf(stderr, "Field `%s' in Record `%s' contains unsupported "
202 "type\n", FD->getNameAsString().c_str(),
203 RD->getNameAsString().c_str());
204 FT->dump();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700205 return NULL;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800206 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700207 }
208
209 return T;
210 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700211 case clang::Type::Pointer: {
212 const clang::PointerType *PT = UNSAFE_CAST_TYPE(clang::PointerType, T);
213 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
214
Zonr Chang2e1dba62010-10-05 22:20:11 +0800215 if (PointeeType->getTypeClass() == clang::Type::Pointer)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700216 return T;
Zonr Chang2e1dba62010-10-05 22:20:11 +0800217 // We don't support pointer with array-type pointee or unsupported pointee
218 // type
219 if (PointeeType->isArrayType() ||
220 (TypeExportable(PointeeType, SPS) == NULL) )
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700221 return NULL;
222 else
223 return T;
224 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700225 case clang::Type::ExtVector: {
226 const clang::ExtVectorType *EVT =
227 UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
228 // Only vector with size 2, 3 and 4 are supported.
229 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
230 return NULL;
231
232 // Check base element type
233 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
234
235 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
236 (TypeExportable(ElementType, SPS) == NULL))
237 return NULL;
238 else
239 return T;
240 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800241 case clang::Type::ConstantArray: {
242 const clang::ConstantArrayType *CAT =
243 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
244
245 // Check size
246 if (CAT->getSize().getActiveBits() > 32) {
247 fprintf(stderr, "RSExportConstantArrayType::Create : array with too "
248 "large size (> 2^32).\n");
249 return NULL;
250 }
251 // Check element type
252 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
253 if (ElementType->isArrayType()) {
254 fprintf(stderr, "RSExportType::TypeExportable : constant array with 2 "
255 "or higher dimension of constant is not supported.\n");
256 return NULL;
257 }
258 if (TypeExportable(ElementType, SPS) == NULL)
259 return NULL;
260 else
261 return T;
262 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700263 default: {
264 return NULL;
265 }
266 }
267}
268
269RSExportType *RSExportType::Create(RSContext *Context,
270 const clang::Type *T,
271 const llvm::StringRef &TypeName) {
272 // Lookup the context to see whether the type was processed before.
273 // Newly created RSExportType will insert into context
274 // in RSExportType::RSExportType()
275 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
276
277 if (ETI != Context->export_types_end())
278 return ETI->second;
279
280 RSExportType *ET = NULL;
281 switch (T->getTypeClass()) {
282 case clang::Type::Record: {
283 RSExportPrimitiveType::DataType dt =
284 RSExportPrimitiveType::GetRSObjectType(TypeName);
285 switch (dt) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800286 case RSExportPrimitiveType::DataTypeUnknown: {
287 // User-defined types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700288 ET = RSExportRecordType::Create(Context,
289 T->getAsStructureType(),
290 TypeName);
291 break;
292 }
Zonr Chang92b344a2010-10-05 20:39:03 +0800293 case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
294 // 2 x 2 Matrix type
295 ET = RSExportMatrixType::Create(Context,
296 T->getAsStructureType(),
297 TypeName,
298 2);
299 break;
300 }
301 case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
302 // 3 x 3 Matrix type
303 ET = RSExportMatrixType::Create(Context,
304 T->getAsStructureType(),
305 TypeName,
306 3);
307 break;
308 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700309 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800310 // 4 x 4 Matrix type
311 ET = RSExportMatrixType::Create(Context,
312 T->getAsStructureType(),
313 TypeName,
314 4);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700315 break;
316 }
317 default: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800318 // Others are primitive types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
320 break;
321 }
322 }
323 break;
324 }
325 case clang::Type::Builtin: {
326 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
327 break;
328 }
329 case clang::Type::Pointer: {
330 ET = RSExportPointerType::Create(Context,
331 UNSAFE_CAST_TYPE(clang::PointerType, T),
332 TypeName);
Zonr Chang92b344a2010-10-05 20:39:03 +0800333 // FIXME: free the name (allocated in RSExportType::GetTypeName)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700334 delete [] TypeName.data();
335 break;
336 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700337 case clang::Type::ExtVector: {
338 ET = RSExportVectorType::Create(Context,
339 UNSAFE_CAST_TYPE(clang::ExtVectorType, T),
340 TypeName);
341 break;
342 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800343 case clang::Type::ConstantArray: {
344 ET = RSExportConstantArrayType::Create(
345 Context,
346 UNSAFE_CAST_TYPE(clang::ConstantArrayType, T));
347 break;
348 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349 default: {
zonr6315f762010-10-05 15:35:14 +0800350 // TODO(zonr): warn that type is not exportable.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 fprintf(stderr,
352 "RSExportType::Create : type '%s' is not exportable\n",
353 T->getTypeClassName());
354 break;
355 }
356 }
357
358 return ET;
359}
360
zonr6315f762010-10-05 15:35:14 +0800361RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700362 llvm::StringRef TypeName;
363 if (NormalizeType(T, TypeName))
364 return Create(Context, T, TypeName);
365 else
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700366 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700367}
368
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700369RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
370 const clang::VarDecl *VD) {
371 return RSExportType::Create(Context, GetTypeOfDecl(VD));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700372}
373
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700374size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
375 return ET->getRSContext()->getTargetData()->getTypeStoreSize(
zonr6315f762010-10-05 15:35:14 +0800376 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700377}
378
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700379size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
380 if (ET->getClass() == RSExportType::ExportClassRecord)
381 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
382 else
383 return ET->getRSContext()->getTargetData()->getTypeAllocSize(
zonr6315f762010-10-05 15:35:14 +0800384 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700385}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700386
Zonr Chang6b6320a2010-10-05 22:42:01 +0800387RSExportType::RSExportType(RSContext *Context,
388 ExportClass Class,
389 const llvm::StringRef &Name)
Zonr Changa41ce1d2010-10-06 02:23:12 +0800390 : RSExportable(Context, RSExportable::EX_TYPE),
Zonr Chang6b6320a2010-10-05 22:42:01 +0800391 mClass(Class),
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()),
Zonr Changa7a828d2010-10-22 03:44:27 +0800395 mLLVMType(NULL),
396 mSpecType(NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800397 // Don't cache the type whose name start with '<'. Those type failed to
398 // get their name since constructing their name in GetTypeName() requiring
399 // complicated work.
400 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
401 // TODO(zonr): Need to check whether the insertion is successful or not.
402 Context->insertExportType(llvm::StringRef(Name), this);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700403 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700404}
405
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800406bool RSExportType::keep() {
407 if (!RSExportable::keep())
408 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800409 // Invalidate converted LLVM type.
410 mLLVMType = NULL;
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800411 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800412}
413
414bool RSExportType::equals(const RSExportable *E) const {
415 CHECK_PARENT_EQUALITY(RSExportable, E);
416 return (static_cast<const RSExportType*>(E)->getClass() == getClass());
417}
418
Zonr Changa7a828d2010-10-22 03:44:27 +0800419RSExportType::~RSExportType() {
420 delete mSpecType;
421}
422
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700423/************************** RSExportPrimitiveType **************************/
Zonr Changa41ce1d2010-10-06 02:23:12 +0800424llvm::ManagedStatic<RSExportPrimitiveType::RSObjectTypeMapTy>
425RSExportPrimitiveType::RSObjectTypeMap;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700426
zonr6315f762010-10-05 15:35:14 +0800427llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700428
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700429bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
430 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
431 return true;
432 else
433 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700434}
435
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700436RSExportPrimitiveType::DataType
437RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef &TypeName) {
438 if (TypeName.empty())
439 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700440
Zonr Changa41ce1d2010-10-06 02:23:12 +0800441 if (RSObjectTypeMap->empty()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800442#define ENUM_RS_OBJECT_TYPE(type, cname) \
443 RSObjectTypeMap->GetOrCreateValue(cname, DataType ## type);
444#include "RSObjectTypeEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700445 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700446
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700447 RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
448 if (I == RSObjectTypeMap->end())
449 return DataTypeUnknown;
450 else
451 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700452}
453
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700454RSExportPrimitiveType::DataType
455RSExportPrimitiveType::GetRSObjectType(const clang::Type *T) {
456 T = GET_CANONICAL_TYPE(T);
457 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
458 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700459
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700460 return GetRSObjectType( RSExportType::GetTypeName(T) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700461}
462
Zonr Changa65ec162010-10-17 01:53:05 +0800463const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
464#define ENUM_RS_DATA_TYPE(type, cname, bits) \
465 bits,
466#include "RSDataTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800467 0 // DataTypeMax
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700468};
469
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700470size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
Zonr Changa65ec162010-10-17 01:53:05 +0800471 assert(((EPT->getType() > DataTypeUnknown) &&
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700472 (EPT->getType() < DataTypeMax)) &&
473 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
474 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700475}
476
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700477RSExportPrimitiveType::DataType
zonr6315f762010-10-05 15:35:14 +0800478RSExportPrimitiveType::GetDataType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700479 if (T == NULL)
480 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700481
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700482 switch (T->getTypeClass()) {
483 case clang::Type::Builtin: {
484 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
485 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800486#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
487 case builtin_type: { \
488 return DataType ## type; \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700489 }
Zonr Changa65ec162010-10-17 01:53:05 +0800490#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800491 // The size of type WChar depend on platform so we abandon the support
492 // to them.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700493 default: {
Zonr Changa65ec162010-10-17 01:53:05 +0800494 fprintf(stderr, "RSExportPrimitiveType::GetDataType : unsupported "
495 "built-in type '%s'\n.", T->getTypeClassName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700496 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700497 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700498 }
499 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700500 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700501 case clang::Type::Record: {
502 // must be RS object type
503 return RSExportPrimitiveType::GetRSObjectType(T);
504 break;
505 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700506 default: {
507 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not "
Zonr Changa65ec162010-10-17 01:53:05 +0800508 "supported primitive type\n", T->getTypeClassName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700509 break;
510 }
511 }
512
513 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700514}
515
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700516RSExportPrimitiveType
517*RSExportPrimitiveType::Create(RSContext *Context,
518 const clang::Type *T,
519 const llvm::StringRef &TypeName,
520 DataKind DK,
521 bool Normalized) {
522 DataType DT = GetDataType(T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700523
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700524 if ((DT == DataTypeUnknown) || TypeName.empty())
525 return NULL;
526 else
Zonr Chang6b6320a2010-10-05 22:42:01 +0800527 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
528 DT, DK, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700529}
530
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700531RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
532 const clang::Type *T,
533 DataKind DK) {
534 llvm::StringRef TypeName;
535 if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
536 return Create(Context, T, TypeName, DK);
537 else
538 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700539}
540
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700541const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
542 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700543
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700544 if (isRSObjectType()) {
545 // struct {
546 // int *p;
547 // } __attribute__((packed, aligned(pointer_size)))
548 //
549 // which is
550 //
551 // <{ [1 x i32] }> in LLVM
552 //
553 if (RSObjectLLVMType == NULL) {
554 std::vector<const llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +0800555 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700556 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700557 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700558 return RSObjectLLVMType;
559 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700560
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700561 switch (mType) {
562 case DataTypeFloat32: {
563 return llvm::Type::getFloatTy(C);
564 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700565 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700566 case DataTypeFloat64: {
567 return llvm::Type::getDoubleTy(C);
568 break;
569 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700570 case DataTypeBoolean: {
571 return llvm::Type::getInt1Ty(C);
572 break;
573 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700574 case DataTypeSigned8:
575 case DataTypeUnsigned8: {
576 return llvm::Type::getInt8Ty(C);
577 break;
578 }
579 case DataTypeSigned16:
580 case DataTypeUnsigned16:
581 case DataTypeUnsigned565:
582 case DataTypeUnsigned5551:
583 case DataTypeUnsigned4444: {
584 return llvm::Type::getInt16Ty(C);
585 break;
586 }
587 case DataTypeSigned32:
588 case DataTypeUnsigned32: {
589 return llvm::Type::getInt32Ty(C);
590 break;
591 }
Stephen Hinesa5d2c232010-10-11 16:10:02 -0700592 case DataTypeSigned64:
593 case DataTypeUnsigned64: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700594 return llvm::Type::getInt64Ty(C);
595 break;
596 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700597 default: {
598 assert(false && "Unknown data type");
599 }
600 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700601
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700602 return NULL;
603}
604
Zonr Changa7a828d2010-10-22 03:44:27 +0800605union RSType *RSExportPrimitiveType::convertToSpecType() const {
606 llvm::OwningPtr<union RSType> ST(new union RSType);
607 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
608 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
609 // slang_rs_type_spec.h
610 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
611 return ST.take();
612}
613
Zonr Chang641558f2010-10-12 21:07:06 +0800614bool RSExportPrimitiveType::equals(const RSExportable *E) const {
615 CHECK_PARENT_EQUALITY(RSExportType, E);
616 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
617}
618
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700619/**************************** 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 Liao9ef2f782010-10-01 12:31:37 -0700646const llvm::Type *RSExportPointerType::convertToLLVMType() const {
647 const llvm::Type *PointeeType = mPointeeType->getLLVMType();
648 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700649}
650
Zonr Changa7a828d2010-10-22 03:44:27 +0800651union RSType *RSExportPointerType::convertToSpecType() const {
652 llvm::OwningPtr<union RSType> ST(new union RSType);
653
654 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
655 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
656
657 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
658 return ST.take();
659 else
660 return NULL;
661}
662
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800663bool RSExportPointerType::keep() {
664 if (!RSExportType::keep())
665 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800666 const_cast<RSExportType*>(mPointeeType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800667 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800668}
669
670bool RSExportPointerType::equals(const RSExportable *E) const {
671 CHECK_PARENT_EQUALITY(RSExportType, E);
672 return (static_cast<const RSExportPointerType*>(E)
673 ->getPointeeType()->equals(getPointeeType()));
674}
675
zonr6315f762010-10-05 15:35:14 +0800676/***************************** RSExportVectorType *****************************/
zonr6315f762010-10-05 15:35:14 +0800677llvm::StringRef
678RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700679 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700680
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700681 if ((ElementType->getTypeClass() != clang::Type::Builtin))
682 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700683
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700684 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType,
685 ElementType);
Zonr Changa65ec162010-10-17 01:53:05 +0800686 if ((EVT->getNumElements() < 1) ||
687 (EVT->getNumElements() > 4))
688 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700689
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700690 switch (BT->getKind()) {
691 // Compiler is smart enough to optimize following *big if branches* since
692 // they all become "constant comparison" after macro expansion
Zonr Changa65ec162010-10-17 01:53:05 +0800693#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
694 case builtin_type: { \
695 const char *Name[] = { cname"2", cname"3", cname"4" }; \
696 return Name[EVT->getNumElements() - 2]; \
697 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700698 }
Zonr Changa65ec162010-10-17 01:53:05 +0800699#include "RSClangBuiltinEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700700 default: {
701 return llvm::StringRef();
702 }
703 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700704}
705
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700706RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
707 const clang::ExtVectorType *EVT,
708 const llvm::StringRef &TypeName,
709 DataKind DK,
710 bool Normalized) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800711 assert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700712
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700713 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
714 RSExportPrimitiveType::DataType DT =
715 RSExportPrimitiveType::GetDataType(ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700716
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700717 if (DT != RSExportPrimitiveType::DataTypeUnknown)
718 return new RSExportVectorType(Context,
719 TypeName,
720 DT,
721 DK,
722 Normalized,
723 EVT->getNumElements());
724 else
725 fprintf(stderr, "RSExportVectorType::Create : unsupported base element "
726 "type\n");
727 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700728}
729
zonr6315f762010-10-05 15:35:14 +0800730const llvm::Type *RSExportVectorType::convertToLLVMType() const {
731 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700732 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700733}
734
Zonr Changa7a828d2010-10-22 03:44:27 +0800735union RSType *RSExportVectorType::convertToSpecType() const {
736 llvm::OwningPtr<union RSType> ST(new union RSType);
737
738 RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
739 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
740 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
741
742 return ST.take();
743}
744
Zonr Chang641558f2010-10-12 21:07:06 +0800745bool RSExportVectorType::equals(const RSExportable *E) const {
746 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
747 return (static_cast<const RSExportVectorType*>(E)->getNumElement()
748 == getNumElement());
749}
750
Zonr Chang92b344a2010-10-05 20:39:03 +0800751/***************************** RSExportMatrixType *****************************/
752RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
753 const clang::RecordType *RT,
754 const llvm::StringRef &TypeName,
755 unsigned Dim) {
756 assert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
757 assert((Dim > 1) && "Invalid dimension of matrix");
758
759 // Check whether the struct rs_matrix is in our expected form (but assume it's
760 // correct if we're not sure whether it's correct or not)
761 const clang::RecordDecl* RD = RT->getDecl();
762 RD = RD->getDefinition();
763 if (RD != NULL) {
764 // Find definition, perform further examination
765 if (RD->field_empty()) {
766 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
767 "must have 1 field for saving values", TypeName.data());
768 return NULL;
769 }
770
771 clang::RecordDecl::field_iterator FIT = RD->field_begin();
772 const clang::FieldDecl *FD = *FIT;
773 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
774 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
775 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
776 "first field should be an array with constant size",
777 TypeName.data());
778 return NULL;
779 }
780 const clang::ConstantArrayType *CAT =
781 static_cast<const clang::ConstantArrayType *>(FT);
Zonr Chang2e1dba62010-10-05 22:20:11 +0800782 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Zonr Chang92b344a2010-10-05 20:39:03 +0800783 if ((ElementType == NULL) ||
784 (ElementType->getTypeClass() != clang::Type::Builtin) ||
785 (static_cast<const clang::BuiltinType *>(ElementType)->getKind()
786 != clang::BuiltinType::Float)) {
787 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
788 "first field should be a float array", TypeName.data());
789 return NULL;
790 }
791
792 if (CAT->getSize() != Dim * Dim) {
793 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
794 "first field should be an array with size %d",
795 TypeName.data(), Dim * Dim);
796 return NULL;
797 }
798
799 FIT++;
800 if (FIT != RD->field_end()) {
801 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
802 "must have exactly 1 field", TypeName.data());
803 return NULL;
804 }
805 }
806
807 return new RSExportMatrixType(Context, TypeName, Dim);
808}
809
Zonr Chang92b344a2010-10-05 20:39:03 +0800810const llvm::Type *RSExportMatrixType::convertToLLVMType() const {
811 // Construct LLVM type:
812 // struct {
813 // float X[mDim * mDim];
814 // }
815
816 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
817 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
818 mDim * mDim);
819 return llvm::StructType::get(C, X, NULL);
820}
821
Zonr Changa7a828d2010-10-22 03:44:27 +0800822union RSType *RSExportMatrixType::convertToSpecType() const {
823 llvm::OwningPtr<union RSType> ST(new union RSType);
824 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
825 switch (getDim()) {
826 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
827 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
828 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
829 default: assert(false && "Matrix type with unsupported dimension.");
830 }
831 return ST.take();
832}
833
Zonr Chang641558f2010-10-12 21:07:06 +0800834bool RSExportMatrixType::equals(const RSExportable *E) const {
835 CHECK_PARENT_EQUALITY(RSExportType, E);
836 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
837}
838
Zonr Chang2e1dba62010-10-05 22:20:11 +0800839/************************* RSExportConstantArrayType *************************/
840RSExportConstantArrayType
841*RSExportConstantArrayType::Create(RSContext *Context,
842 const clang::ConstantArrayType *CAT) {
843 assert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
844
845 assert((CAT->getSize().getActiveBits() < 32) && "array too large");
846
847 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
848 assert((Size > 0) && "Constant array should have size greater than 0");
849
850 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
851 RSExportType *ElementET = RSExportType::Create(Context, ElementType);
852
853 if (ElementET == NULL) {
854 fprintf(stderr, "RSExportConstantArrayType::Create : failed to create "
855 "RSExportType for array element.\n");
856 return NULL;
857 }
858
859 return new RSExportConstantArrayType(Context,
860 ElementET,
861 Size);
862}
863
Zonr Chang2e1dba62010-10-05 22:20:11 +0800864const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
865 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
866}
867
Zonr Changa7a828d2010-10-22 03:44:27 +0800868union RSType *RSExportConstantArrayType::convertToSpecType() const {
869 llvm::OwningPtr<union RSType> ST(new union RSType);
870
871 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
872 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
873 ST, getElementType()->getSpecType());
874 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
875
876 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
877 return ST.take();
878 else
879 return NULL;
880}
881
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800882bool RSExportConstantArrayType::keep() {
883 if (!RSExportType::keep())
884 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800885 const_cast<RSExportType*>(mElementType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800886 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800887}
888
889bool RSExportConstantArrayType::equals(const RSExportable *E) const {
890 CHECK_PARENT_EQUALITY(RSExportType, E);
891 return ((static_cast<const RSExportConstantArrayType*>(E)
892 ->getSize() == getSize()) && (mElementType->equals(E)));
893}
894
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700895/**************************** RSExportRecordType ****************************/
896RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
897 const clang::RecordType *RT,
898 const llvm::StringRef &TypeName,
899 bool mIsArtificial) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800900 assert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700901
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700902 const clang::RecordDecl *RD = RT->getDecl();
903 assert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700904
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700905 RD = RD->getDefinition();
906 if (RD == NULL) {
zonr6315f762010-10-05 15:35:14 +0800907 // TODO(zonr): warn that actual struct definition isn't declared in this
908 // moudle.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700909 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined "
910 "in this module.");
911 return NULL;
912 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700913
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800914 // Struct layout construct by clang. We rely on this for obtaining the
915 // alloc size of a struct and offset of every field in that struct.
916 const clang::ASTRecordLayout *RL =
917 &Context->getASTContext()->getASTRecordLayout(RD);
918 assert((RL != NULL) && "Failed to retrieve the struct layout from Clang.");
919
920 RSExportRecordType *ERT =
921 new RSExportRecordType(Context,
922 TypeName,
923 RD->hasAttr<clang::PackedAttr>(),
924 mIsArtificial,
925 (RL->getSize() >> 3));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700926 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700927
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700928 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
929 FE = RD->field_end();
930 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -0700931 FI++, Index++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700932#define FAILED_CREATE_FIELD(err) do { \
933 if (*err) \
934 fprintf(stderr, \
935 "RSExportRecordType::Create : failed to create field (%s)\n", \
936 err); \
937 delete ERT; \
938 return NULL; \
939 } while (false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700940
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700941 // FIXME: All fields should be primitive type
942 assert((*FI)->getKind() == clang::Decl::Field);
943 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700944
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700945 // We don't support bit field
946 //
zonr6315f762010-10-05 15:35:14 +0800947 // TODO(zonr): allow bitfield with size 8, 16, 32
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700948 if (FD->isBitField())
949 FAILED_CREATE_FIELD("bit field is not supported");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700950
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700951 // Type
zonr6315f762010-10-05 15:35:14 +0800952 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700953
zonr6315f762010-10-05 15:35:14 +0800954 if (ET != NULL)
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800955 ERT->mFields.push_back(
956 new Field(ET, FD->getName(), ERT,
957 static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700958 else
959 FAILED_CREATE_FIELD(FD->getName().str().c_str());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700960#undef FAILED_CREATE_FIELD
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700961 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700962
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700963 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700964}
965
zonr6315f762010-10-05 15:35:14 +0800966const llvm::Type *RSExportRecordType::convertToLLVMType() const {
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800967 // Create an opaque type since struct may reference itself recursively.
968 llvm::PATypeHolder ResultHolder =
969 llvm::OpaqueType::get(getRSContext()->getLLVMContext());
970 setAbstractLLVMType(ResultHolder.get());
971
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700972 std::vector<const llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700973
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800974 for (const_field_iterator FI = fields_begin(), FE = fields_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700975 FI != FE;
976 FI++) {
977 const Field *F = *FI;
978 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700979
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700980 FieldTypes.push_back(FET->getLLVMType());
981 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700982
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800983 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
984 FieldTypes,
985 mIsPacked);
986 if (ST != NULL)
987 static_cast<llvm::OpaqueType*>(ResultHolder.get())
988 ->refineAbstractTypeTo(ST);
989 else
990 return NULL;
991 return ResultHolder.get();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700992}
Zonr Chang641558f2010-10-12 21:07:06 +0800993
Zonr Changa7a828d2010-10-22 03:44:27 +0800994union RSType *RSExportRecordType::convertToSpecType() const {
995 unsigned NumFields = getFields().size();
996 unsigned AllocSize = sizeof(union RSType) +
997 sizeof(struct RSRecordField) * NumFields;
998 llvm::OwningPtr<union RSType> ST(
999 reinterpret_cast<union RSType*>(operator new (AllocSize)));
1000
1001 ::memset(ST.get(), 0, AllocSize);
1002
1003 RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1004 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1005 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1006
1007 setSpecTypeTemporarily(ST.get());
1008
1009 unsigned FieldIdx = 0;
1010 for (const_field_iterator FI = fields_begin(), FE = fields_end();
1011 FI != FE;
1012 FI++, FieldIdx++) {
1013 const Field *F = *FI;
1014
1015 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1016 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
1017
1018 enum RSDataKind DK = RS_DK_User;
1019 if ((F->getType()->getClass() == ExportClassPrimitive) ||
1020 (F->getType()->getClass() == ExportClassVector)) {
1021 const RSExportPrimitiveType *EPT =
1022 static_cast<const RSExportPrimitiveType*>(F->getType());
1023 // enum RSExportPrimitiveType::DataKind is synced with enum RSDataKind in
1024 // slang_rs_type_spec.h
1025 DK = static_cast<enum RSDataKind>(EPT->getKind());
1026 }
1027 RS_RECORD_TYPE_SET_FIELD_DATA_KIND(ST, FieldIdx, DK);
1028 }
1029
1030 // TODO: Check whether all fields were created normaly.
1031
1032 return ST.take();
1033}
1034
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001035bool RSExportRecordType::keep() {
1036 if (!RSExportType::keep())
1037 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001038 for (std::list<const Field*>::iterator I = mFields.begin(),
1039 E = mFields.end();
1040 I != E;
1041 I++) {
1042 const_cast<RSExportType*>((*I)->getType())->keep();
1043 }
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001044 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001045}
1046
1047bool RSExportRecordType::equals(const RSExportable *E) const {
1048 CHECK_PARENT_EQUALITY(RSExportType, E);
1049
1050 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1051
1052 if (ERT->getFields().size() != getFields().size())
1053 return false;
1054
1055 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1056
1057 for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1058 if (!(*AI)->getType()->equals((*BI)->getType()))
1059 return false;
1060 AI++;
1061 BI++;
1062 }
1063
1064 return true;
1065}