blob: 01cb3291023a20175067ad021558f3aed0900520 [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: {
Zonr Changb1771ef2010-10-22 18:03:46 +0800175 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700176 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 =
Zonr Changb1771ef2010-10-22 18:03:46 +0800284 RSExportPrimitiveType::GetRSSpecificType(TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700285 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 Changb1771ef2010-10-22 18:03:46 +0800424llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy>
425RSExportPrimitiveType::RSSpecificTypeMap;
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
Zonr Changb1771ef2010-10-22 18:03:46 +0800437RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700438 if (TypeName.empty())
439 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700440
Zonr Changb1771ef2010-10-22 18:03:46 +0800441 if (RSSpecificTypeMap->empty()) {
442#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \
443 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
444#include "RSMatrixTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800445#define ENUM_RS_OBJECT_TYPE(type, cname) \
Zonr Changb1771ef2010-10-22 18:03:46 +0800446 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
Zonr Changa65ec162010-10-17 01:53:05 +0800447#include "RSObjectTypeEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700448 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700449
Zonr Changb1771ef2010-10-22 18:03:46 +0800450 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName);
451 if (I == RSSpecificTypeMap->end())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700452 return DataTypeUnknown;
453 else
454 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700455}
456
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700457RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800458RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700459 T = GET_CANONICAL_TYPE(T);
460 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
461 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700462
Zonr Changb1771ef2010-10-22 18:03:46 +0800463 return GetRSSpecificType( RSExportType::GetTypeName(T) );
464}
465
466bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) {
467 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType));
468}
469
470bool RSExportPrimitiveType::IsRSObjectType(DataType DT) {
471 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700472}
473
Zonr Changa65ec162010-10-17 01:53:05 +0800474const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
475#define ENUM_RS_DATA_TYPE(type, cname, bits) \
476 bits,
477#include "RSDataTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800478 0 // DataTypeMax
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700479};
480
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700481size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
Zonr Changa65ec162010-10-17 01:53:05 +0800482 assert(((EPT->getType() > DataTypeUnknown) &&
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700483 (EPT->getType() < DataTypeMax)) &&
484 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
485 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700486}
487
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700488RSExportPrimitiveType::DataType
zonr6315f762010-10-05 15:35:14 +0800489RSExportPrimitiveType::GetDataType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700490 if (T == NULL)
491 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700492
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700493 switch (T->getTypeClass()) {
494 case clang::Type::Builtin: {
495 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
496 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800497#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
498 case builtin_type: { \
499 return DataType ## type; \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700500 }
Zonr Changa65ec162010-10-17 01:53:05 +0800501#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800502 // The size of type WChar depend on platform so we abandon the support
503 // to them.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700504 default: {
Zonr Changa65ec162010-10-17 01:53:05 +0800505 fprintf(stderr, "RSExportPrimitiveType::GetDataType : unsupported "
506 "built-in type '%s'\n.", T->getTypeClassName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700507 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700508 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700509 }
510 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700511 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700512 case clang::Type::Record: {
513 // must be RS object type
Zonr Changb1771ef2010-10-22 18:03:46 +0800514 return RSExportPrimitiveType::GetRSSpecificType(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700515 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700516 default: {
517 fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not "
Zonr Changa65ec162010-10-17 01:53:05 +0800518 "supported primitive type\n", T->getTypeClassName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700519 break;
520 }
521 }
522
523 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700524}
525
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700526RSExportPrimitiveType
527*RSExportPrimitiveType::Create(RSContext *Context,
528 const clang::Type *T,
529 const llvm::StringRef &TypeName,
530 DataKind DK,
531 bool Normalized) {
532 DataType DT = GetDataType(T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700533
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700534 if ((DT == DataTypeUnknown) || TypeName.empty())
535 return NULL;
536 else
Zonr Chang6b6320a2010-10-05 22:42:01 +0800537 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
538 DT, DK, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700539}
540
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700541RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
542 const clang::Type *T,
543 DataKind DK) {
544 llvm::StringRef TypeName;
545 if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
546 return Create(Context, T, TypeName, DK);
547 else
548 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700549}
550
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700551const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
552 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700553
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700554 if (isRSObjectType()) {
555 // struct {
556 // int *p;
557 // } __attribute__((packed, aligned(pointer_size)))
558 //
559 // which is
560 //
561 // <{ [1 x i32] }> in LLVM
562 //
563 if (RSObjectLLVMType == NULL) {
564 std::vector<const llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +0800565 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700566 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700567 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700568 return RSObjectLLVMType;
569 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700570
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700571 switch (mType) {
572 case DataTypeFloat32: {
573 return llvm::Type::getFloatTy(C);
574 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700575 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700576 case DataTypeFloat64: {
577 return llvm::Type::getDoubleTy(C);
578 break;
579 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700580 case DataTypeBoolean: {
581 return llvm::Type::getInt1Ty(C);
582 break;
583 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700584 case DataTypeSigned8:
585 case DataTypeUnsigned8: {
586 return llvm::Type::getInt8Ty(C);
587 break;
588 }
589 case DataTypeSigned16:
590 case DataTypeUnsigned16:
591 case DataTypeUnsigned565:
592 case DataTypeUnsigned5551:
593 case DataTypeUnsigned4444: {
594 return llvm::Type::getInt16Ty(C);
595 break;
596 }
597 case DataTypeSigned32:
598 case DataTypeUnsigned32: {
599 return llvm::Type::getInt32Ty(C);
600 break;
601 }
Stephen Hinesa5d2c232010-10-11 16:10:02 -0700602 case DataTypeSigned64:
603 case DataTypeUnsigned64: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700604 return llvm::Type::getInt64Ty(C);
605 break;
606 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700607 default: {
608 assert(false && "Unknown data type");
609 }
610 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700611
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700612 return NULL;
613}
614
Zonr Changa7a828d2010-10-22 03:44:27 +0800615union RSType *RSExportPrimitiveType::convertToSpecType() const {
616 llvm::OwningPtr<union RSType> ST(new union RSType);
617 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
618 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
619 // slang_rs_type_spec.h
620 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
621 return ST.take();
622}
623
Zonr Chang641558f2010-10-12 21:07:06 +0800624bool RSExportPrimitiveType::equals(const RSExportable *E) const {
625 CHECK_PARENT_EQUALITY(RSExportType, E);
626 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
627}
628
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700629/**************************** RSExportPointerType ****************************/
630
631const clang::Type *RSExportPointerType::IntegerType = NULL;
632
633RSExportPointerType
634*RSExportPointerType::Create(RSContext *Context,
635 const clang::PointerType *PT,
636 const llvm::StringRef &TypeName) {
637 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
638 const RSExportType *PointeeET;
639
640 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
641 PointeeET = RSExportType::Create(Context, PointeeType);
642 } else {
643 // Double or higher dimension of pointer, export as int*
644 assert(IntegerType != NULL && "Built-in integer type is not set");
645 PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
646 }
647
648 if (PointeeET == NULL) {
649 fprintf(stderr, "Failed to create type for pointee");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700650 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700651 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700652
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700653 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700654}
655
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700656const llvm::Type *RSExportPointerType::convertToLLVMType() const {
657 const llvm::Type *PointeeType = mPointeeType->getLLVMType();
658 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700659}
660
Zonr Changa7a828d2010-10-22 03:44:27 +0800661union RSType *RSExportPointerType::convertToSpecType() const {
662 llvm::OwningPtr<union RSType> ST(new union RSType);
663
664 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
665 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
666
667 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
668 return ST.take();
669 else
670 return NULL;
671}
672
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800673bool RSExportPointerType::keep() {
674 if (!RSExportType::keep())
675 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800676 const_cast<RSExportType*>(mPointeeType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800677 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800678}
679
680bool RSExportPointerType::equals(const RSExportable *E) const {
681 CHECK_PARENT_EQUALITY(RSExportType, E);
682 return (static_cast<const RSExportPointerType*>(E)
683 ->getPointeeType()->equals(getPointeeType()));
684}
685
zonr6315f762010-10-05 15:35:14 +0800686/***************************** RSExportVectorType *****************************/
zonr6315f762010-10-05 15:35:14 +0800687llvm::StringRef
688RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700689 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700690
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700691 if ((ElementType->getTypeClass() != clang::Type::Builtin))
692 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700693
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700694 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType,
695 ElementType);
Zonr Changa65ec162010-10-17 01:53:05 +0800696 if ((EVT->getNumElements() < 1) ||
697 (EVT->getNumElements() > 4))
698 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700699
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700700 switch (BT->getKind()) {
701 // Compiler is smart enough to optimize following *big if branches* since
702 // they all become "constant comparison" after macro expansion
Zonr Changa65ec162010-10-17 01:53:05 +0800703#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
704 case builtin_type: { \
705 const char *Name[] = { cname"2", cname"3", cname"4" }; \
706 return Name[EVT->getNumElements() - 2]; \
707 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700708 }
Zonr Changa65ec162010-10-17 01:53:05 +0800709#include "RSClangBuiltinEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700710 default: {
711 return llvm::StringRef();
712 }
713 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700714}
715
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700716RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
717 const clang::ExtVectorType *EVT,
718 const llvm::StringRef &TypeName,
719 DataKind DK,
720 bool Normalized) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800721 assert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700722
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700723 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
724 RSExportPrimitiveType::DataType DT =
725 RSExportPrimitiveType::GetDataType(ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700726
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700727 if (DT != RSExportPrimitiveType::DataTypeUnknown)
728 return new RSExportVectorType(Context,
729 TypeName,
730 DT,
731 DK,
732 Normalized,
733 EVT->getNumElements());
734 else
735 fprintf(stderr, "RSExportVectorType::Create : unsupported base element "
736 "type\n");
737 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700738}
739
zonr6315f762010-10-05 15:35:14 +0800740const llvm::Type *RSExportVectorType::convertToLLVMType() const {
741 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700742 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700743}
744
Zonr Changa7a828d2010-10-22 03:44:27 +0800745union RSType *RSExportVectorType::convertToSpecType() const {
746 llvm::OwningPtr<union RSType> ST(new union RSType);
747
748 RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
749 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
750 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
751
752 return ST.take();
753}
754
Zonr Chang641558f2010-10-12 21:07:06 +0800755bool RSExportVectorType::equals(const RSExportable *E) const {
756 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
757 return (static_cast<const RSExportVectorType*>(E)->getNumElement()
758 == getNumElement());
759}
760
Zonr Chang92b344a2010-10-05 20:39:03 +0800761/***************************** RSExportMatrixType *****************************/
762RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
763 const clang::RecordType *RT,
764 const llvm::StringRef &TypeName,
765 unsigned Dim) {
766 assert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
767 assert((Dim > 1) && "Invalid dimension of matrix");
768
769 // Check whether the struct rs_matrix is in our expected form (but assume it's
770 // correct if we're not sure whether it's correct or not)
771 const clang::RecordDecl* RD = RT->getDecl();
772 RD = RD->getDefinition();
773 if (RD != NULL) {
774 // Find definition, perform further examination
775 if (RD->field_empty()) {
776 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
777 "must have 1 field for saving values", TypeName.data());
778 return NULL;
779 }
780
781 clang::RecordDecl::field_iterator FIT = RD->field_begin();
782 const clang::FieldDecl *FD = *FIT;
783 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
784 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
785 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
786 "first field should be an array with constant size",
787 TypeName.data());
788 return NULL;
789 }
790 const clang::ConstantArrayType *CAT =
791 static_cast<const clang::ConstantArrayType *>(FT);
Zonr Chang2e1dba62010-10-05 22:20:11 +0800792 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Zonr Chang92b344a2010-10-05 20:39:03 +0800793 if ((ElementType == NULL) ||
794 (ElementType->getTypeClass() != clang::Type::Builtin) ||
795 (static_cast<const clang::BuiltinType *>(ElementType)->getKind()
796 != clang::BuiltinType::Float)) {
797 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
798 "first field should be a float array", TypeName.data());
799 return NULL;
800 }
801
802 if (CAT->getSize() != Dim * Dim) {
803 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
804 "first field should be an array with size %d",
805 TypeName.data(), Dim * Dim);
806 return NULL;
807 }
808
809 FIT++;
810 if (FIT != RD->field_end()) {
811 fprintf(stderr, "RSExportMatrixType::Create : invalid %s struct: "
812 "must have exactly 1 field", TypeName.data());
813 return NULL;
814 }
815 }
816
817 return new RSExportMatrixType(Context, TypeName, Dim);
818}
819
Zonr Chang92b344a2010-10-05 20:39:03 +0800820const llvm::Type *RSExportMatrixType::convertToLLVMType() const {
821 // Construct LLVM type:
822 // struct {
823 // float X[mDim * mDim];
824 // }
825
826 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
827 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
828 mDim * mDim);
829 return llvm::StructType::get(C, X, NULL);
830}
831
Zonr Changa7a828d2010-10-22 03:44:27 +0800832union RSType *RSExportMatrixType::convertToSpecType() const {
833 llvm::OwningPtr<union RSType> ST(new union RSType);
834 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
835 switch (getDim()) {
836 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
837 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
838 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
839 default: assert(false && "Matrix type with unsupported dimension.");
840 }
841 return ST.take();
842}
843
Zonr Chang641558f2010-10-12 21:07:06 +0800844bool RSExportMatrixType::equals(const RSExportable *E) const {
845 CHECK_PARENT_EQUALITY(RSExportType, E);
846 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
847}
848
Zonr Chang2e1dba62010-10-05 22:20:11 +0800849/************************* RSExportConstantArrayType *************************/
850RSExportConstantArrayType
851*RSExportConstantArrayType::Create(RSContext *Context,
852 const clang::ConstantArrayType *CAT) {
853 assert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
854
855 assert((CAT->getSize().getActiveBits() < 32) && "array too large");
856
857 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
858 assert((Size > 0) && "Constant array should have size greater than 0");
859
860 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
861 RSExportType *ElementET = RSExportType::Create(Context, ElementType);
862
863 if (ElementET == NULL) {
864 fprintf(stderr, "RSExportConstantArrayType::Create : failed to create "
865 "RSExportType for array element.\n");
866 return NULL;
867 }
868
869 return new RSExportConstantArrayType(Context,
870 ElementET,
871 Size);
872}
873
Zonr Chang2e1dba62010-10-05 22:20:11 +0800874const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
875 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
876}
877
Zonr Changa7a828d2010-10-22 03:44:27 +0800878union RSType *RSExportConstantArrayType::convertToSpecType() const {
879 llvm::OwningPtr<union RSType> ST(new union RSType);
880
881 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
882 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
883 ST, getElementType()->getSpecType());
884 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
885
886 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
887 return ST.take();
888 else
889 return NULL;
890}
891
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800892bool RSExportConstantArrayType::keep() {
893 if (!RSExportType::keep())
894 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800895 const_cast<RSExportType*>(mElementType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800896 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800897}
898
899bool RSExportConstantArrayType::equals(const RSExportable *E) const {
900 CHECK_PARENT_EQUALITY(RSExportType, E);
901 return ((static_cast<const RSExportConstantArrayType*>(E)
902 ->getSize() == getSize()) && (mElementType->equals(E)));
903}
904
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700905/**************************** RSExportRecordType ****************************/
906RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
907 const clang::RecordType *RT,
908 const llvm::StringRef &TypeName,
909 bool mIsArtificial) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800910 assert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700911
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700912 const clang::RecordDecl *RD = RT->getDecl();
913 assert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700914
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700915 RD = RD->getDefinition();
916 if (RD == NULL) {
zonr6315f762010-10-05 15:35:14 +0800917 // TODO(zonr): warn that actual struct definition isn't declared in this
918 // moudle.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700919 fprintf(stderr, "RSExportRecordType::Create : this struct is not defined "
920 "in this module.");
921 return NULL;
922 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700923
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800924 // Struct layout construct by clang. We rely on this for obtaining the
925 // alloc size of a struct and offset of every field in that struct.
926 const clang::ASTRecordLayout *RL =
Stephen Hines9e5b5032010-11-03 13:19:14 -0700927 &Context->getASTContext().getASTRecordLayout(RD);
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800928 assert((RL != NULL) && "Failed to retrieve the struct layout from Clang.");
929
930 RSExportRecordType *ERT =
931 new RSExportRecordType(Context,
932 TypeName,
933 RD->hasAttr<clang::PackedAttr>(),
934 mIsArtificial,
935 (RL->getSize() >> 3));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700936 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700937
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700938 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
939 FE = RD->field_end();
940 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -0700941 FI++, Index++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700942#define FAILED_CREATE_FIELD(err) do { \
943 if (*err) \
944 fprintf(stderr, \
945 "RSExportRecordType::Create : failed to create field (%s)\n", \
946 err); \
947 delete ERT; \
948 return NULL; \
949 } while (false)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700950
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700951 // FIXME: All fields should be primitive type
952 assert((*FI)->getKind() == clang::Decl::Field);
953 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700954
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700955 // We don't support bit field
956 //
zonr6315f762010-10-05 15:35:14 +0800957 // TODO(zonr): allow bitfield with size 8, 16, 32
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700958 if (FD->isBitField())
959 FAILED_CREATE_FIELD("bit field is not supported");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700960
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700961 // Type
zonr6315f762010-10-05 15:35:14 +0800962 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700963
zonr6315f762010-10-05 15:35:14 +0800964 if (ET != NULL)
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800965 ERT->mFields.push_back(
966 new Field(ET, FD->getName(), ERT,
967 static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700968 else
969 FAILED_CREATE_FIELD(FD->getName().str().c_str());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700970#undef FAILED_CREATE_FIELD
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700971 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700972
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700973 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700974}
975
zonr6315f762010-10-05 15:35:14 +0800976const llvm::Type *RSExportRecordType::convertToLLVMType() const {
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800977 // Create an opaque type since struct may reference itself recursively.
978 llvm::PATypeHolder ResultHolder =
979 llvm::OpaqueType::get(getRSContext()->getLLVMContext());
980 setAbstractLLVMType(ResultHolder.get());
981
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700982 std::vector<const llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700983
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800984 for (const_field_iterator FI = fields_begin(), FE = fields_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700985 FI != FE;
986 FI++) {
987 const Field *F = *FI;
988 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700989
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700990 FieldTypes.push_back(FET->getLLVMType());
991 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700992
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800993 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
994 FieldTypes,
995 mIsPacked);
996 if (ST != NULL)
997 static_cast<llvm::OpaqueType*>(ResultHolder.get())
998 ->refineAbstractTypeTo(ST);
999 else
1000 return NULL;
1001 return ResultHolder.get();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001002}
Zonr Chang641558f2010-10-12 21:07:06 +08001003
Zonr Changa7a828d2010-10-22 03:44:27 +08001004union RSType *RSExportRecordType::convertToSpecType() const {
1005 unsigned NumFields = getFields().size();
1006 unsigned AllocSize = sizeof(union RSType) +
1007 sizeof(struct RSRecordField) * NumFields;
1008 llvm::OwningPtr<union RSType> ST(
1009 reinterpret_cast<union RSType*>(operator new (AllocSize)));
1010
1011 ::memset(ST.get(), 0, AllocSize);
1012
1013 RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1014 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1015 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1016
1017 setSpecTypeTemporarily(ST.get());
1018
1019 unsigned FieldIdx = 0;
1020 for (const_field_iterator FI = fields_begin(), FE = fields_end();
1021 FI != FE;
1022 FI++, FieldIdx++) {
1023 const Field *F = *FI;
1024
1025 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1026 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
1027
1028 enum RSDataKind DK = RS_DK_User;
1029 if ((F->getType()->getClass() == ExportClassPrimitive) ||
1030 (F->getType()->getClass() == ExportClassVector)) {
1031 const RSExportPrimitiveType *EPT =
1032 static_cast<const RSExportPrimitiveType*>(F->getType());
1033 // enum RSExportPrimitiveType::DataKind is synced with enum RSDataKind in
1034 // slang_rs_type_spec.h
1035 DK = static_cast<enum RSDataKind>(EPT->getKind());
1036 }
1037 RS_RECORD_TYPE_SET_FIELD_DATA_KIND(ST, FieldIdx, DK);
1038 }
1039
1040 // TODO: Check whether all fields were created normaly.
1041
1042 return ST.take();
1043}
1044
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001045bool RSExportRecordType::keep() {
1046 if (!RSExportType::keep())
1047 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001048 for (std::list<const Field*>::iterator I = mFields.begin(),
1049 E = mFields.end();
1050 I != E;
1051 I++) {
1052 const_cast<RSExportType*>((*I)->getType())->keep();
1053 }
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001054 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001055}
1056
1057bool RSExportRecordType::equals(const RSExportable *E) const {
1058 CHECK_PARENT_EQUALITY(RSExportType, E);
1059
1060 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1061
1062 if (ERT->getFields().size() != getFields().size())
1063 return false;
1064
1065 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1066
1067 for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1068 if (!(*AI)->getType()->equals((*BI)->getType()))
1069 return false;
1070 AI++;
1071 BI++;
1072 }
1073
1074 return true;
1075}