blob: 2d35ef6b8b710c63e537b2a2bd1d1864da16f9df [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
Stephen Hinesd5a84f62012-04-04 17:44:38 -07002 * Copyright 2010-2012, The Android Open Source Project
Zonr Changc383a502010-10-12 01:52:08 +08003 *
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
Stephen Hinese639eb52010-11-08 19:27:20 -080019#include <list>
zonr6315f762010-10-05 15:35:14 +080020#include <vector>
Shih-wei Liao462aefd2010-06-04 15:32:04 -070021
Shih-wei Liao43730fe2012-08-02 23:06:18 -070022#include "clang/AST/ASTContext.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080023#include "clang/AST/RecordLayout.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070024
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070025#include "llvm/ADT/StringExtras.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080026
27#include "llvm/DerivedTypes.h"
28
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070029#include "llvm/Target/TargetData.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070030
Stephen Hinese639eb52010-11-08 19:27:20 -080031#include "llvm/Type.h"
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070032
Stephen Hines6e6578a2011-02-07 18:05:48 -080033#include "slang_assert.h"
zonr6315f762010-10-05 15:35:14 +080034#include "slang_rs_context.h"
35#include "slang_rs_export_element.h"
Zonr Changa7a828d2010-10-22 03:44:27 +080036#include "slang_rs_type_spec.h"
Stephen Hinesd5a84f62012-04-04 17:44:38 -070037#include "slang_version.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070038
Zonr Chang641558f2010-10-12 21:07:06 +080039#define CHECK_PARENT_EQUALITY(ParentClass, E) \
40 if (!ParentClass::equals(E)) \
41 return false;
42
Stephen Hinese639eb52010-11-08 19:27:20 -080043namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
Stephen Hinese5e64432010-12-02 18:48:20 -080045namespace {
46
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080047static RSReflectionType gReflectionTypes[] = {
48 {"FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false},
49 {"FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false},
50 {"FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false},
51 {"SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false},
52 {"SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false},
53 {"SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false},
54 {"SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false},
Stephen Hines47aca4e2012-03-08 20:07:28 -080055 {"UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true},
56 {"UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true},
57 {"UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true},
58 {"UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false},
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080059
Stephen Hines47aca4e2012-03-08 20:07:28 -080060 {"BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false},
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080061
62 {"UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false},
63 {"UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false},
64 {"UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false},
65
66 {"MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false},
67 {"MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false},
68 {"MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false},
69
70 {"RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false},
71 {"RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false},
72 {"RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false},
73 {"RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false},
74 {"RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false},
75 {"RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false},
76 {"RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false},
77 {"RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false},
78 {"RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false},
79 {"RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false},
80 {"RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false},
81 {"RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false}
82};
83
Stephen Hines24e79f62010-12-13 12:55:57 -080084static const clang::Type *TypeExportableHelper(
85 const clang::Type *T,
86 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Logan Chien9207a2e2011-10-21 15:39:28 +080087 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -080088 const clang::VarDecl *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -070089 const clang::RecordDecl *TopLevelRecord);
Stephen Hines24e79f62010-12-13 12:55:57 -080090
Logan Chien9207a2e2011-10-21 15:39:28 +080091static void ReportTypeError(clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -080092 const clang::VarDecl *VD,
93 const clang::RecordDecl *TopLevelRecord,
Stephen Hinesd5a84f62012-04-04 17:44:38 -070094 const char *Message,
95 unsigned int TargetAPI = 0) {
Logan Chien9207a2e2011-10-21 15:39:28 +080096 if (!DiagEngine) {
Stephen Hines24e79f62010-12-13 12:55:57 -080097 return;
98 }
99
Logan Chien9207a2e2011-10-21 15:39:28 +0800100 const clang::SourceManager &SM = DiagEngine->getSourceManager();
Stephen Hines78e69cb2011-04-22 15:03:19 -0700101
Stephen Hines24e79f62010-12-13 12:55:57 -0800102 // Attempt to use the type declaration first (if we have one).
103 // Fall back to the variable definition, if we are looking at something
104 // like an array declaration that can't be exported.
105 if (TopLevelRecord) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800106 DiagEngine->Report(
107 clang::FullSourceLoc(TopLevelRecord->getLocation(), SM),
108 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700109 << TopLevelRecord->getName() << TargetAPI;
Stephen Hines24e79f62010-12-13 12:55:57 -0800110 } else if (VD) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800111 DiagEngine->Report(
112 clang::FullSourceLoc(VD->getLocation(), SM),
113 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700114 << VD->getName() << TargetAPI;
Stephen Hines24e79f62010-12-13 12:55:57 -0800115 } else {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800116 slangAssert(false && "Variables should be validated before exporting");
Stephen Hines24e79f62010-12-13 12:55:57 -0800117 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800118}
119
120static const clang::Type *ConstantArrayTypeExportableHelper(
121 const clang::ConstantArrayType *CAT,
122 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Logan Chien9207a2e2011-10-21 15:39:28 +0800123 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -0800124 const clang::VarDecl *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700125 const clang::RecordDecl *TopLevelRecord) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800126 // Check element type
127 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
128 if (ElementType->isArrayType()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800129 ReportTypeError(DiagEngine, VD, TopLevelRecord,
130 "multidimensional arrays cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800131 return NULL;
132 } else if (ElementType->isExtVectorType()) {
133 const clang::ExtVectorType *EVT =
134 static_cast<const clang::ExtVectorType*>(ElementType);
135 unsigned numElements = EVT->getNumElements();
136
137 const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
138 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800139 ReportTypeError(DiagEngine, VD, TopLevelRecord,
140 "vectors of non-primitive types cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800141 return NULL;
142 }
143
144 if (numElements == 3 && CAT->getSize() != 1) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800145 ReportTypeError(DiagEngine, VD, TopLevelRecord,
146 "arrays of width 3 vector types cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800147 return NULL;
148 }
149 }
150
Logan Chien9207a2e2011-10-21 15:39:28 +0800151 if (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700152 TopLevelRecord) == NULL) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800153 return NULL;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700154 } else {
Stephen Hines24e79f62010-12-13 12:55:57 -0800155 return CAT;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700156 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800157}
158
159static const clang::Type *TypeExportableHelper(
Stephen Hinese67239d2012-02-24 15:08:36 -0800160 clang::Type const *T,
161 llvm::SmallPtrSet<clang::Type const *, 8> &SPS,
162 clang::DiagnosticsEngine *DiagEngine,
163 clang::VarDecl const *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700164 clang::RecordDecl const *TopLevelRecord) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800165 // Normalize first
166 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
167 return NULL;
168
169 if (SPS.count(T))
170 return T;
171
172 switch (T->getTypeClass()) {
173 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800174 const clang::BuiltinType *BT =
175 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800176
177 switch (BT->getKind()) {
178#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
179 case builtin_type:
180#include "RSClangBuiltinEnums.inc"
181 return T;
182 default: {
183 return NULL;
184 }
185 }
186 }
187 case clang::Type::Record: {
188 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700189 RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800190 return T; // RS object type, no further checks are needed
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700191 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800192
193 // Check internal struct
Stephen Hinescd440ee2010-12-06 14:57:04 -0800194 if (T->isUnionType()) {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700195 ReportTypeError(DiagEngine, VD, T->getAsUnionType()->getDecl(),
Logan Chien9207a2e2011-10-21 15:39:28 +0800196 "unions cannot be exported: '%0'");
Stephen Hinescd440ee2010-12-06 14:57:04 -0800197 return NULL;
198 } else if (!T->isStructureType()) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800199 slangAssert(false && "Unknown type cannot be exported");
Stephen Hinescd440ee2010-12-06 14:57:04 -0800200 return NULL;
201 }
202
Stephen Hines24e79f62010-12-13 12:55:57 -0800203 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800204 if (RD != NULL) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800205 RD = RD->getDefinition();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800206 if (RD == NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800207 ReportTypeError(DiagEngine, NULL, T->getAsStructureType()->getDecl(),
208 "struct is not defined in this module");
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800209 return NULL;
210 }
211 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800212
213 if (!TopLevelRecord) {
214 TopLevelRecord = RD;
215 }
216 if (RD->getName().empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800217 ReportTypeError(DiagEngine, NULL, RD,
218 "anonymous structures cannot be exported");
Stephen Hinese5e64432010-12-02 18:48:20 -0800219 return NULL;
220 }
221
222 // Fast check
223 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
224 return NULL;
225
226 // Insert myself into checking set
227 SPS.insert(T);
228
229 // Check all element
230 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
231 FE = RD->field_end();
232 FI != FE;
233 FI++) {
234 const clang::FieldDecl *FD = *FI;
235 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
236 FT = GET_CANONICAL_TYPE(FT);
237
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700238 if (!TypeExportableHelper(FT, SPS, DiagEngine, VD, TopLevelRecord)) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800239 return NULL;
240 }
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800241
242 // We don't support bit fields yet
243 //
244 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32
245 if (FD->isBitField()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800246 if (DiagEngine) {
247 DiagEngine->Report(
248 clang::FullSourceLoc(FD->getLocation(),
249 DiagEngine->getSourceManager()),
250 DiagEngine->getCustomDiagID(
251 clang::DiagnosticsEngine::Error,
252 "bit fields are not able to be exported: '%0.%1'"))
253 << RD->getName()
254 << FD->getName();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800255 }
256 return NULL;
257 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800258 }
259
260 return T;
261 }
262 case clang::Type::Pointer: {
263 if (TopLevelRecord) {
Stephen Hinesaa82e742012-04-11 12:38:17 -0700264 ReportTypeError(DiagEngine, VD, TopLevelRecord,
265 "structures containing pointers cannot be exported: '%0'");
Stephen Hinese5e64432010-12-02 18:48:20 -0800266 return NULL;
267 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800268
Loganbe274822011-02-16 22:02:54 +0800269 const clang::PointerType *PT =
270 UNSAFE_CAST_TYPE(const clang::PointerType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800271 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
272
Stephen Hinesaa82e742012-04-11 12:38:17 -0700273 if (PointeeType->getTypeClass() == clang::Type::Pointer) {
274 ReportTypeError(DiagEngine, VD, TopLevelRecord,
275 "multiple levels of pointers cannot be exported: '%0'");
276 return NULL;
277 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800278 // We don't support pointer with array-type pointee or unsupported pointee
279 // type
280 if (PointeeType->isArrayType() ||
Logan Chien9207a2e2011-10-21 15:39:28 +0800281 (TypeExportableHelper(PointeeType, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700282 TopLevelRecord) == NULL))
Stephen Hinese5e64432010-12-02 18:48:20 -0800283 return NULL;
284 else
285 return T;
286 }
287 case clang::Type::ExtVector: {
288 const clang::ExtVectorType *EVT =
Loganbe274822011-02-16 22:02:54 +0800289 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800290 // Only vector with size 2, 3 and 4 are supported.
291 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
292 return NULL;
293
294 // Check base element type
295 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
296
297 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
Logan Chien9207a2e2011-10-21 15:39:28 +0800298 (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700299 TopLevelRecord) == NULL))
Stephen Hinese5e64432010-12-02 18:48:20 -0800300 return NULL;
301 else
302 return T;
303 }
304 case clang::Type::ConstantArray: {
305 const clang::ConstantArrayType *CAT =
Loganbe274822011-02-16 22:02:54 +0800306 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800307
Logan Chien9207a2e2011-10-21 15:39:28 +0800308 return ConstantArrayTypeExportableHelper(CAT, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700309 TopLevelRecord);
Stephen Hinese5e64432010-12-02 18:48:20 -0800310 }
311 default: {
312 return NULL;
313 }
314 }
315}
316
317// Return the type that can be used to create RSExportType, will always return
318// the canonical type
Logan Chien9207a2e2011-10-21 15:39:28 +0800319// If the Type T is not exportable, this function returns NULL. DiagEngine is
Stephen Hines78e69cb2011-04-22 15:03:19 -0700320// used to generate proper Clang diagnostic messages when a
Stephen Hinese5e64432010-12-02 18:48:20 -0800321// non-exportable type is detected. TopLevelRecord is used to capture the
322// highest struct (in the case of a nested hierarchy) for detecting other
323// types that cannot be exported (mostly pointers within a struct).
324static const clang::Type *TypeExportable(const clang::Type *T,
Logan Chien9207a2e2011-10-21 15:39:28 +0800325 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700326 const clang::VarDecl *VD) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700327 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
328 llvm::SmallPtrSet<const clang::Type*, 8>();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700329
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700330 return TypeExportableHelper(T, SPS, DiagEngine, VD, NULL);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700331}
332
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700333static bool ValidateRSObjectInVarDecl(clang::VarDecl *VD,
334 bool InCompositeType,
335 unsigned int TargetAPI) {
336 if (TargetAPI < SLANG_JB_TARGET_API) {
337 // Only if we are already in a composite type (like an array or structure).
338 if (InCompositeType) {
339 // Only if we are actually exported (i.e. non-static).
340 if (VD->getLinkage() == clang::ExternalLinkage) {
341 // Only if we are not a pointer to an object.
342 const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr());
343 if (T->getTypeClass() != clang::Type::Pointer) {
344 clang::ASTContext &C = VD->getASTContext();
345 ReportTypeError(&C.getDiagnostics(), VD, NULL,
346 "arrays/structures containing RS object types "
347 "cannot be exported in target API < %1: '%0'",
348 SLANG_JB_TARGET_API);
349 return false;
350 }
351 }
352 }
353 }
354
355 return true;
356}
357
358// Helper function for ValidateVarDecl(). We do a recursive descent on the
359// type hierarchy to ensure that we can properly export/handle the
360// declaration.
361// \return true if the variable declaration is valid,
362// false if it is invalid (along with proper diagnostics).
363//
364// VD - top-level variable declaration that we are validating.
365// T - sub-type of VD's type that we are validating.
366// SPS - set of types we have already seen/validated.
367// InCompositeType - true if we are within an outer composite type.
368// UnionDecl - set if we are in a sub-type of a union.
369// TargetAPI - target SDK API level.
Stephen Hines78e69cb2011-04-22 15:03:19 -0700370static bool ValidateVarDeclHelper(
371 clang::VarDecl *VD,
372 const clang::Type *&T,
373 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700374 bool InCompositeType,
375 clang::RecordDecl *UnionDecl,
376 unsigned int TargetAPI) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700377 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
378 return true;
379
380 if (SPS.count(T))
381 return true;
382
383 switch (T->getTypeClass()) {
384 case clang::Type::Record: {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700385 if (RSExportPrimitiveType::IsRSObjectType(T)) {
386 if (!ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) {
387 return false;
388 }
389 }
390
Stephen Hines78e69cb2011-04-22 15:03:19 -0700391 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
392 RSExportPrimitiveType::DataTypeUnknown) {
393 if (!UnionDecl) {
394 return true;
395 } else if (RSExportPrimitiveType::IsRSObjectType(T)) {
396 clang::ASTContext &C = VD->getASTContext();
397 ReportTypeError(&C.getDiagnostics(), VD, UnionDecl,
398 "unions containing RS object types are not allowed");
399 return false;
400 }
401 }
402
403 clang::RecordDecl *RD = NULL;
404
405 // Check internal struct
406 if (T->isUnionType()) {
407 RD = T->getAsUnionType()->getDecl();
408 UnionDecl = RD;
409 } else if (T->isStructureType()) {
410 RD = T->getAsStructureType()->getDecl();
411 } else {
412 slangAssert(false && "Unknown type cannot be exported");
413 return false;
414 }
415
416 if (RD != NULL) {
417 RD = RD->getDefinition();
418 if (RD == NULL) {
419 // FIXME
420 return true;
421 }
422 }
423
424 // Fast check
425 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
426 return false;
427
428 // Insert myself into checking set
429 SPS.insert(T);
430
431 // Check all elements
432 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
433 FE = RD->field_end();
434 FI != FE;
435 FI++) {
436 const clang::FieldDecl *FD = *FI;
437 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
438 FT = GET_CANONICAL_TYPE(FT);
439
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700440 if (!ValidateVarDeclHelper(VD, FT, SPS, true, UnionDecl, TargetAPI)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700441 return false;
442 }
443 }
444
445 return true;
446 }
447
448 case clang::Type::Builtin: {
449 break;
450 }
451
452 case clang::Type::Pointer: {
453 const clang::PointerType *PT =
454 UNSAFE_CAST_TYPE(const clang::PointerType, T);
455 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
456
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700457 return ValidateVarDeclHelper(VD, PointeeType, SPS, InCompositeType,
458 UnionDecl, TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700459 }
460
461 case clang::Type::ExtVector: {
462 const clang::ExtVectorType *EVT =
463 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
464 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Stephen Hinesb13b85e2012-08-31 19:27:48 -0700465 if (TargetAPI < SLANG_ICS_TARGET_API &&
466 InCompositeType &&
467 EVT->getNumElements() == 3) {
468 clang::ASTContext &C = VD->getASTContext();
469 ReportTypeError(&C.getDiagnostics(), VD, NULL,
470 "structs containing vectors of dimension 3 cannot "
471 "be exported at this API level: '%0'");
472 return false;
473 }
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700474 return ValidateVarDeclHelper(VD, ElementType, SPS, true, UnionDecl,
475 TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700476 }
477
478 case clang::Type::ConstantArray: {
479 const clang::ConstantArrayType *CAT =
480 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
481 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700482 return ValidateVarDeclHelper(VD, ElementType, SPS, true, UnionDecl,
483 TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700484 }
485
486 default: {
487 break;
488 }
489 }
490
491 return true;
Stephen Hinese5e64432010-12-02 18:48:20 -0800492}
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700493
Stephen Hinese5e64432010-12-02 18:48:20 -0800494} // namespace
495
496/****************************** RSExportType ******************************/
497bool RSExportType::NormalizeType(const clang::Type *&T,
498 llvm::StringRef &TypeName,
Logan Chien9207a2e2011-10-21 15:39:28 +0800499 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700500 const clang::VarDecl *VD) {
501 if ((T = TypeExportable(T, DiagEngine, VD)) == NULL) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800502 return false;
503 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700504 // Get type name
505 TypeName = RSExportType::GetTypeName(T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800506 if (TypeName.empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800507 if (DiagEngine) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800508 if (VD) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800509 DiagEngine->Report(
510 clang::FullSourceLoc(VD->getLocation(),
511 DiagEngine->getSourceManager()),
512 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
513 "anonymous types cannot be exported"));
Stephen Hines24e79f62010-12-13 12:55:57 -0800514 } else {
Logan Chien9207a2e2011-10-21 15:39:28 +0800515 DiagEngine->Report(
516 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
517 "anonymous types cannot be exported"));
Stephen Hines24e79f62010-12-13 12:55:57 -0800518 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800519 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700520 return false;
Stephen Hinese5e64432010-12-02 18:48:20 -0800521 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700522
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700523 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700524}
525
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700526bool RSExportType::ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700527 const clang::Type *T = VD->getType().getTypePtr();
528 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
529 llvm::SmallPtrSet<const clang::Type*, 8>();
530
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700531 return ValidateVarDeclHelper(VD, T, SPS, false, NULL, TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700532}
533
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700534const clang::Type
535*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800536 if (DD) {
537 clang::QualType T;
538 if (DD->getTypeSourceInfo())
539 T = DD->getTypeSourceInfo()->getType();
540 else
541 T = DD->getType();
542
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700543 if (T.isNull())
544 return NULL;
545 else
546 return T.getTypePtr();
547 }
548 return NULL;
549}
550
551llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
552 T = GET_CANONICAL_TYPE(T);
553 if (T == NULL)
554 return llvm::StringRef();
555
556 switch (T->getTypeClass()) {
557 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800558 const clang::BuiltinType *BT =
559 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700560
561 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800562#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
563 case builtin_type: \
564 return cname; \
565 break;
566#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800567 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800568 slangAssert(false && "Unknown data type of the builtin");
Zonr Changa65ec162010-10-17 01:53:05 +0800569 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700570 }
Zonr Changa65ec162010-10-17 01:53:05 +0800571 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700572 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700573 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700574 case clang::Type::Record: {
Stephen Hinescd440ee2010-12-06 14:57:04 -0800575 clang::RecordDecl *RD;
576 if (T->isStructureType()) {
577 RD = T->getAsStructureType()->getDecl();
Stephen Hinesdd6206b2010-12-09 19:39:22 -0800578 } else {
Stephen Hinescd440ee2010-12-06 14:57:04 -0800579 break;
580 }
581
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700582 llvm::StringRef Name = RD->getName();
583 if (Name.empty()) {
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700584 if (RD->getTypedefNameForAnonDecl() != NULL) {
585 Name = RD->getTypedefNameForAnonDecl()->getName();
586 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700587
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700588 if (Name.empty()) {
589 // Try to find a name from redeclaration (i.e. typedef)
590 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
591 RE = RD->redecls_end();
592 RI != RE;
593 RI++) {
594 slangAssert(*RI != NULL && "cannot be NULL object");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700595
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700596 Name = (*RI)->getName();
597 if (!Name.empty())
598 break;
599 }
600 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700601 }
602 return Name;
603 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700604 case clang::Type::Pointer: {
605 // "*" plus pointee name
zonr6315f762010-10-05 15:35:14 +0800606 const clang::Type *PT = GET_POINTEE_TYPE(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700607 llvm::StringRef PointeeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700608 if (NormalizeType(PT, PointeeName, NULL, NULL)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700609 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
610 Name[0] = '*';
611 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
612 Name[PointeeName.size() + 1] = '\0';
613 return Name;
614 }
615 break;
616 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700617 case clang::Type::ExtVector: {
618 const clang::ExtVectorType *EVT =
Loganbe274822011-02-16 22:02:54 +0800619 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700620 return RSExportVectorType::GetTypeName(EVT);
621 break;
622 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800623 case clang::Type::ConstantArray : {
624 // Construct name for a constant array is too complicated.
625 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE;
626 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700627 default: {
628 break;
629 }
630 }
631
632 return llvm::StringRef();
633}
634
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700635
636RSExportType *RSExportType::Create(RSContext *Context,
637 const clang::Type *T,
638 const llvm::StringRef &TypeName) {
639 // Lookup the context to see whether the type was processed before.
640 // Newly created RSExportType will insert into context
641 // in RSExportType::RSExportType()
642 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
643
644 if (ETI != Context->export_types_end())
645 return ETI->second;
646
647 RSExportType *ET = NULL;
648 switch (T->getTypeClass()) {
649 case clang::Type::Record: {
650 RSExportPrimitiveType::DataType dt =
Zonr Changb1771ef2010-10-22 18:03:46 +0800651 RSExportPrimitiveType::GetRSSpecificType(TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700652 switch (dt) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800653 case RSExportPrimitiveType::DataTypeUnknown: {
654 // User-defined types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700655 ET = RSExportRecordType::Create(Context,
656 T->getAsStructureType(),
657 TypeName);
658 break;
659 }
Zonr Chang92b344a2010-10-05 20:39:03 +0800660 case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
661 // 2 x 2 Matrix type
662 ET = RSExportMatrixType::Create(Context,
663 T->getAsStructureType(),
664 TypeName,
665 2);
666 break;
667 }
668 case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
669 // 3 x 3 Matrix type
670 ET = RSExportMatrixType::Create(Context,
671 T->getAsStructureType(),
672 TypeName,
673 3);
674 break;
675 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700676 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800677 // 4 x 4 Matrix type
678 ET = RSExportMatrixType::Create(Context,
679 T->getAsStructureType(),
680 TypeName,
681 4);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700682 break;
683 }
684 default: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800685 // Others are primitive types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700686 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
687 break;
688 }
689 }
690 break;
691 }
692 case clang::Type::Builtin: {
693 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
694 break;
695 }
696 case clang::Type::Pointer: {
697 ET = RSExportPointerType::Create(Context,
Stephen Hines5baf6322011-04-25 17:21:15 -0700698 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName);
Zonr Chang92b344a2010-10-05 20:39:03 +0800699 // FIXME: free the name (allocated in RSExportType::GetTypeName)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700700 delete [] TypeName.data();
701 break;
702 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700703 case clang::Type::ExtVector: {
704 ET = RSExportVectorType::Create(Context,
Stephen Hines5baf6322011-04-25 17:21:15 -0700705 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700706 break;
707 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800708 case clang::Type::ConstantArray: {
709 ET = RSExportConstantArrayType::Create(
710 Context,
Loganbe274822011-02-16 22:02:54 +0800711 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T));
Zonr Chang2e1dba62010-10-05 22:20:11 +0800712 break;
713 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700714 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800715 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
716 DiagEngine->Report(
717 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
718 "unknown type cannot be exported: '%0'"))
719 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700720 break;
721 }
722 }
723
724 return ET;
725}
726
zonr6315f762010-10-05 15:35:14 +0800727RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700728 llvm::StringRef TypeName;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700729 if (NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700730 return Create(Context, T, TypeName);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700731 } else {
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700732 return NULL;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700733 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700734}
735
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700736RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
737 const clang::VarDecl *VD) {
738 return RSExportType::Create(Context, GetTypeOfDecl(VD));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700739}
740
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700741size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
742 return ET->getRSContext()->getTargetData()->getTypeStoreSize(
zonr6315f762010-10-05 15:35:14 +0800743 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700744}
745
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700746size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
747 if (ET->getClass() == RSExportType::ExportClassRecord)
748 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
749 else
750 return ET->getRSContext()->getTargetData()->getTypeAllocSize(
zonr6315f762010-10-05 15:35:14 +0800751 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700752}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700753
Zonr Chang6b6320a2010-10-05 22:42:01 +0800754RSExportType::RSExportType(RSContext *Context,
755 ExportClass Class,
756 const llvm::StringRef &Name)
Zonr Changa41ce1d2010-10-06 02:23:12 +0800757 : RSExportable(Context, RSExportable::EX_TYPE),
Zonr Chang6b6320a2010-10-05 22:42:01 +0800758 mClass(Class),
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800759 // Make a copy on Name since memory stored @Name is either allocated in
760 // ASTContext or allocated in GetTypeName which will be destroyed later.
zonr6315f762010-10-05 15:35:14 +0800761 mName(Name.data(), Name.size()),
Zonr Changa7a828d2010-10-22 03:44:27 +0800762 mLLVMType(NULL),
763 mSpecType(NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800764 // Don't cache the type whose name start with '<'. Those type failed to
765 // get their name since constructing their name in GetTypeName() requiring
766 // complicated work.
767 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
768 // TODO(zonr): Need to check whether the insertion is successful or not.
769 Context->insertExportType(llvm::StringRef(Name), this);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700770 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700771}
772
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800773bool RSExportType::keep() {
774 if (!RSExportable::keep())
775 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800776 // Invalidate converted LLVM type.
777 mLLVMType = NULL;
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800778 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800779}
780
781bool RSExportType::equals(const RSExportable *E) const {
782 CHECK_PARENT_EQUALITY(RSExportable, E);
783 return (static_cast<const RSExportType*>(E)->getClass() == getClass());
784}
785
Zonr Changa7a828d2010-10-22 03:44:27 +0800786RSExportType::~RSExportType() {
787 delete mSpecType;
788}
789
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700790/************************** RSExportPrimitiveType **************************/
Zonr Changb1771ef2010-10-22 18:03:46 +0800791llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy>
792RSExportPrimitiveType::RSSpecificTypeMap;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700793
zonr6315f762010-10-05 15:35:14 +0800794llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700795
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700796bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
797 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
798 return true;
799 else
800 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700801}
802
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700803RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800804RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700805 if (TypeName.empty())
806 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700807
Zonr Changb1771ef2010-10-22 18:03:46 +0800808 if (RSSpecificTypeMap->empty()) {
809#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \
810 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
811#include "RSMatrixTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800812#define ENUM_RS_OBJECT_TYPE(type, cname) \
Zonr Changb1771ef2010-10-22 18:03:46 +0800813 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
Zonr Changa65ec162010-10-17 01:53:05 +0800814#include "RSObjectTypeEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700815 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700816
Zonr Changb1771ef2010-10-22 18:03:46 +0800817 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName);
818 if (I == RSSpecificTypeMap->end())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700819 return DataTypeUnknown;
820 else
821 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700822}
823
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700824RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800825RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700826 T = GET_CANONICAL_TYPE(T);
827 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
828 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700829
Zonr Changb1771ef2010-10-22 18:03:46 +0800830 return GetRSSpecificType( RSExportType::GetTypeName(T) );
831}
832
833bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) {
834 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType));
835}
836
837bool RSExportPrimitiveType::IsRSObjectType(DataType DT) {
838 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700839}
840
Stephen Hinesfeaca062011-02-04 14:08:13 -0800841bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) {
842 bool RSObjectTypeSeen = false;
843 while (T && T->isArrayType()) {
844 T = T->getArrayElementTypeNoTypeQual();
845 }
846
847 const clang::RecordType *RT = T->getAsStructureType();
848 if (!RT) {
849 return false;
850 }
851 const clang::RecordDecl *RD = RT->getDecl();
852 RD = RD->getDefinition();
853 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
854 FE = RD->field_end();
855 FI != FE;
856 FI++) {
857 // We just look through all field declarations to see if we find a
858 // declaration for an RS object type (or an array of one).
859 const clang::FieldDecl *FD = *FI;
860 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
861 while (FT && FT->isArrayType()) {
862 FT = FT->getArrayElementTypeNoTypeQual();
863 }
864
865 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT);
866 if (IsRSObjectType(DT)) {
867 // RS object types definitely need to be zero-initialized
868 RSObjectTypeSeen = true;
869 } else {
870 switch (DT) {
871 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
872 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
873 case RSExportPrimitiveType::DataTypeRSMatrix4x4:
874 // Matrix types should get zero-initialized as well
875 RSObjectTypeSeen = true;
876 break;
877 default:
878 // Ignore all other primitive types
879 break;
880 }
881 while (FT && FT->isArrayType()) {
882 FT = FT->getArrayElementTypeNoTypeQual();
883 }
884 if (FT->isStructureType()) {
885 // Recursively handle structs of structs (even though these can't
886 // be exported, it is possible for a user to have them internally).
887 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT);
888 }
889 }
890 }
891
892 return RSObjectTypeSeen;
893}
894
Zonr Changa65ec162010-10-17 01:53:05 +0800895const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
896#define ENUM_RS_DATA_TYPE(type, cname, bits) \
897 bits,
898#include "RSDataTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800899 0 // DataTypeMax
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700900};
901
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700902size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800903 slangAssert(((EPT->getType() > DataTypeUnknown) &&
904 (EPT->getType() < DataTypeMax)) &&
905 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700906 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700907}
908
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700909RSExportPrimitiveType::DataType
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800910RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700911 if (T == NULL)
912 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700913
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700914 switch (T->getTypeClass()) {
915 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800916 const clang::BuiltinType *BT =
917 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700918 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800919#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
920 case builtin_type: { \
921 return DataType ## type; \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700922 }
Zonr Changa65ec162010-10-17 01:53:05 +0800923#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800924 // The size of type WChar depend on platform so we abandon the support
925 // to them.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700926 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800927 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
928 DiagEngine->Report(
929 DiagEngine->getCustomDiagID(
930 clang::DiagnosticsEngine::Error,
931 "built-in type cannot be exported: '%0'"))
932 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700933 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700934 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700935 }
936 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700937 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700938 case clang::Type::Record: {
939 // must be RS object type
Zonr Changb1771ef2010-10-22 18:03:46 +0800940 return RSExportPrimitiveType::GetRSSpecificType(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700941 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700942 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800943 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
944 DiagEngine->Report(
945 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
946 "primitive type cannot be exported: '%0'"))
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800947 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700948 break;
949 }
950 }
951
952 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700953}
954
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700955RSExportPrimitiveType
956*RSExportPrimitiveType::Create(RSContext *Context,
957 const clang::Type *T,
958 const llvm::StringRef &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700959 bool Normalized) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800960 DataType DT = GetDataType(Context, T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700961
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700962 if ((DT == DataTypeUnknown) || TypeName.empty())
963 return NULL;
964 else
Zonr Chang6b6320a2010-10-05 22:42:01 +0800965 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
Stephen Hines2b8fb642012-03-09 00:12:47 -0800966 DT, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700967}
968
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700969RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
Stephen Hines2b8fb642012-03-09 00:12:47 -0800970 const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700971 llvm::StringRef TypeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700972 if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)
Stephen Hines78e69cb2011-04-22 15:03:19 -0700973 && IsPrimitiveType(T)) {
Stephen Hines2b8fb642012-03-09 00:12:47 -0800974 return Create(Context, T, TypeName);
Stephen Hinese5e64432010-12-02 18:48:20 -0800975 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700976 return NULL;
Stephen Hinese5e64432010-12-02 18:48:20 -0800977 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700978}
979
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700980llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700981 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700982
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700983 if (isRSObjectType()) {
984 // struct {
985 // int *p;
986 // } __attribute__((packed, aligned(pointer_size)))
987 //
988 // which is
989 //
990 // <{ [1 x i32] }> in LLVM
991 //
992 if (RSObjectLLVMType == NULL) {
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700993 std::vector<llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +0800994 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Stephen Hinesa67e4452011-07-19 15:39:26 -0700995 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700996 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700997 return RSObjectLLVMType;
998 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700999
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001000 switch (mType) {
1001 case DataTypeFloat32: {
1002 return llvm::Type::getFloatTy(C);
1003 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001004 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001005 case DataTypeFloat64: {
1006 return llvm::Type::getDoubleTy(C);
1007 break;
1008 }
Shih-wei Liao91a37832010-10-03 19:11:51 -07001009 case DataTypeBoolean: {
1010 return llvm::Type::getInt1Ty(C);
1011 break;
1012 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001013 case DataTypeSigned8:
1014 case DataTypeUnsigned8: {
1015 return llvm::Type::getInt8Ty(C);
1016 break;
1017 }
1018 case DataTypeSigned16:
1019 case DataTypeUnsigned16:
1020 case DataTypeUnsigned565:
1021 case DataTypeUnsigned5551:
1022 case DataTypeUnsigned4444: {
1023 return llvm::Type::getInt16Ty(C);
1024 break;
1025 }
1026 case DataTypeSigned32:
1027 case DataTypeUnsigned32: {
1028 return llvm::Type::getInt32Ty(C);
1029 break;
1030 }
Stephen Hinesa5d2c232010-10-11 16:10:02 -07001031 case DataTypeSigned64:
1032 case DataTypeUnsigned64: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001033 return llvm::Type::getInt64Ty(C);
1034 break;
1035 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001036 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001037 slangAssert(false && "Unknown data type");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001038 }
1039 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001040
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001041 return NULL;
1042}
1043
Zonr Changa7a828d2010-10-22 03:44:27 +08001044union RSType *RSExportPrimitiveType::convertToSpecType() const {
1045 llvm::OwningPtr<union RSType> ST(new union RSType);
1046 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
1047 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
1048 // slang_rs_type_spec.h
1049 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
1050 return ST.take();
1051}
1052
Zonr Chang641558f2010-10-12 21:07:06 +08001053bool RSExportPrimitiveType::equals(const RSExportable *E) const {
1054 CHECK_PARENT_EQUALITY(RSExportType, E);
1055 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
1056}
1057
Stephen Hinesfdd1ba12012-03-08 17:26:32 -08001058RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) {
1059 if (DT > DataTypeUnknown && DT < DataTypeMax) {
1060 return &gReflectionTypes[DT];
1061 } else {
1062 return NULL;
1063 }
1064}
1065
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001066/**************************** RSExportPointerType ****************************/
1067
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001068RSExportPointerType
1069*RSExportPointerType::Create(RSContext *Context,
1070 const clang::PointerType *PT,
1071 const llvm::StringRef &TypeName) {
1072 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
1073 const RSExportType *PointeeET;
1074
1075 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
1076 PointeeET = RSExportType::Create(Context, PointeeType);
1077 } else {
1078 // Double or higher dimension of pointer, export as int*
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001079 PointeeET = RSExportPrimitiveType::Create(Context,
1080 Context->getASTContext().IntTy.getTypePtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001081 }
1082
1083 if (PointeeET == NULL) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001084 // Error diagnostic is emitted for corresponding pointee type
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001085 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001086 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001087
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001088 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001089}
1090
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001091llvm::Type *RSExportPointerType::convertToLLVMType() const {
1092 llvm::Type *PointeeType = mPointeeType->getLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001093 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001094}
1095
Zonr Changa7a828d2010-10-22 03:44:27 +08001096union RSType *RSExportPointerType::convertToSpecType() const {
1097 llvm::OwningPtr<union RSType> ST(new union RSType);
1098
1099 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
1100 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
1101
1102 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
1103 return ST.take();
1104 else
1105 return NULL;
1106}
1107
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001108bool RSExportPointerType::keep() {
1109 if (!RSExportType::keep())
1110 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001111 const_cast<RSExportType*>(mPointeeType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001112 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001113}
1114
1115bool RSExportPointerType::equals(const RSExportable *E) const {
1116 CHECK_PARENT_EQUALITY(RSExportType, E);
1117 return (static_cast<const RSExportPointerType*>(E)
1118 ->getPointeeType()->equals(getPointeeType()));
1119}
1120
zonr6315f762010-10-05 15:35:14 +08001121/***************************** RSExportVectorType *****************************/
zonr6315f762010-10-05 15:35:14 +08001122llvm::StringRef
1123RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001124 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001125
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001126 if ((ElementType->getTypeClass() != clang::Type::Builtin))
1127 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001128
Loganbe274822011-02-16 22:02:54 +08001129 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001130 ElementType);
Zonr Changa65ec162010-10-17 01:53:05 +08001131 if ((EVT->getNumElements() < 1) ||
1132 (EVT->getNumElements() > 4))
1133 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001134
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001135 switch (BT->getKind()) {
1136 // Compiler is smart enough to optimize following *big if branches* since
1137 // they all become "constant comparison" after macro expansion
Zonr Changa65ec162010-10-17 01:53:05 +08001138#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
1139 case builtin_type: { \
1140 const char *Name[] = { cname"2", cname"3", cname"4" }; \
1141 return Name[EVT->getNumElements() - 2]; \
1142 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001143 }
Zonr Changa65ec162010-10-17 01:53:05 +08001144#include "RSClangBuiltinEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001145 default: {
1146 return llvm::StringRef();
1147 }
1148 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001149}
1150
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001151RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
1152 const clang::ExtVectorType *EVT,
1153 const llvm::StringRef &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001154 bool Normalized) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001155 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001156
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001157 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1158 RSExportPrimitiveType::DataType DT =
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001159 RSExportPrimitiveType::GetDataType(Context, ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001160
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001161 if (DT != RSExportPrimitiveType::DataTypeUnknown)
1162 return new RSExportVectorType(Context,
1163 TypeName,
1164 DT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001165 Normalized,
1166 EVT->getNumElements());
1167 else
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001168 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001169}
1170
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001171llvm::Type *RSExportVectorType::convertToLLVMType() const {
1172 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001173 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001174}
1175
Zonr Changa7a828d2010-10-22 03:44:27 +08001176union RSType *RSExportVectorType::convertToSpecType() const {
1177 llvm::OwningPtr<union RSType> ST(new union RSType);
1178
1179 RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
1180 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
1181 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
1182
1183 return ST.take();
1184}
1185
Zonr Chang641558f2010-10-12 21:07:06 +08001186bool RSExportVectorType::equals(const RSExportable *E) const {
1187 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
1188 return (static_cast<const RSExportVectorType*>(E)->getNumElement()
1189 == getNumElement());
1190}
1191
Zonr Chang92b344a2010-10-05 20:39:03 +08001192/***************************** RSExportMatrixType *****************************/
1193RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
1194 const clang::RecordType *RT,
1195 const llvm::StringRef &TypeName,
1196 unsigned Dim) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001197 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
1198 slangAssert((Dim > 1) && "Invalid dimension of matrix");
Zonr Chang92b344a2010-10-05 20:39:03 +08001199
1200 // Check whether the struct rs_matrix is in our expected form (but assume it's
1201 // correct if we're not sure whether it's correct or not)
1202 const clang::RecordDecl* RD = RT->getDecl();
1203 RD = RD->getDefinition();
1204 if (RD != NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001205 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001206 const clang::SourceManager *SM = Context->getSourceManager();
Zonr Chang92b344a2010-10-05 20:39:03 +08001207 // Find definition, perform further examination
1208 if (RD->field_empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001209 DiagEngine->Report(
1210 clang::FullSourceLoc(RD->getLocation(), *SM),
1211 DiagEngine->getCustomDiagID(
1212 clang::DiagnosticsEngine::Error,
1213 "invalid matrix struct: must have 1 field for saving values: '%0'"))
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001214 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001215 return NULL;
1216 }
1217
1218 clang::RecordDecl::field_iterator FIT = RD->field_begin();
1219 const clang::FieldDecl *FD = *FIT;
1220 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1221 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001222 DiagEngine->Report(
1223 clang::FullSourceLoc(RD->getLocation(), *SM),
1224 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1225 "invalid matrix struct: first field should"
1226 " be an array with constant size: '%0'"))
1227 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001228 return NULL;
1229 }
1230 const clang::ConstantArrayType *CAT =
1231 static_cast<const clang::ConstantArrayType *>(FT);
Zonr Chang2e1dba62010-10-05 22:20:11 +08001232 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Zonr Chang92b344a2010-10-05 20:39:03 +08001233 if ((ElementType == NULL) ||
1234 (ElementType->getTypeClass() != clang::Type::Builtin) ||
Logan Chien9207a2e2011-10-21 15:39:28 +08001235 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() !=
1236 clang::BuiltinType::Float)) {
1237 DiagEngine->Report(
1238 clang::FullSourceLoc(RD->getLocation(), *SM),
1239 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1240 "invalid matrix struct: first field "
1241 "should be a float array: '%0'"))
1242 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001243 return NULL;
1244 }
1245
1246 if (CAT->getSize() != Dim * Dim) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001247 DiagEngine->Report(
1248 clang::FullSourceLoc(RD->getLocation(), *SM),
1249 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1250 "invalid matrix struct: first field "
1251 "should be an array with size %0: '%1'"))
1252 << (Dim * Dim) << (RD->getName());
Zonr Chang92b344a2010-10-05 20:39:03 +08001253 return NULL;
1254 }
1255
1256 FIT++;
1257 if (FIT != RD->field_end()) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001258 DiagEngine->Report(
1259 clang::FullSourceLoc(RD->getLocation(), *SM),
1260 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1261 "invalid matrix struct: must have "
1262 "exactly 1 field: '%0'"))
1263 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001264 return NULL;
1265 }
1266 }
1267
1268 return new RSExportMatrixType(Context, TypeName, Dim);
1269}
1270
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001271llvm::Type *RSExportMatrixType::convertToLLVMType() const {
Zonr Chang92b344a2010-10-05 20:39:03 +08001272 // Construct LLVM type:
1273 // struct {
1274 // float X[mDim * mDim];
1275 // }
1276
1277 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
1278 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
1279 mDim * mDim);
Stephen Hinesa67e4452011-07-19 15:39:26 -07001280 return llvm::StructType::get(C, X, false);
Zonr Chang92b344a2010-10-05 20:39:03 +08001281}
1282
Zonr Changa7a828d2010-10-22 03:44:27 +08001283union RSType *RSExportMatrixType::convertToSpecType() const {
1284 llvm::OwningPtr<union RSType> ST(new union RSType);
1285 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
1286 switch (getDim()) {
1287 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
1288 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
1289 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
Stephen Hines6e6578a2011-02-07 18:05:48 -08001290 default: slangAssert(false && "Matrix type with unsupported dimension.");
Zonr Changa7a828d2010-10-22 03:44:27 +08001291 }
1292 return ST.take();
1293}
1294
Zonr Chang641558f2010-10-12 21:07:06 +08001295bool RSExportMatrixType::equals(const RSExportable *E) const {
1296 CHECK_PARENT_EQUALITY(RSExportType, E);
1297 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
1298}
1299
Zonr Chang2e1dba62010-10-05 22:20:11 +08001300/************************* RSExportConstantArrayType *************************/
1301RSExportConstantArrayType
1302*RSExportConstantArrayType::Create(RSContext *Context,
1303 const clang::ConstantArrayType *CAT) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001304 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
Zonr Chang2e1dba62010-10-05 22:20:11 +08001305
Stephen Hines6e6578a2011-02-07 18:05:48 -08001306 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large");
Zonr Chang2e1dba62010-10-05 22:20:11 +08001307
1308 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
Stephen Hines6e6578a2011-02-07 18:05:48 -08001309 slangAssert((Size > 0) && "Constant array should have size greater than 0");
Zonr Chang2e1dba62010-10-05 22:20:11 +08001310
1311 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1312 RSExportType *ElementET = RSExportType::Create(Context, ElementType);
1313
1314 if (ElementET == NULL) {
Zonr Chang2e1dba62010-10-05 22:20:11 +08001315 return NULL;
1316 }
1317
1318 return new RSExportConstantArrayType(Context,
1319 ElementET,
1320 Size);
1321}
1322
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001323llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
Zonr Chang2e1dba62010-10-05 22:20:11 +08001324 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
1325}
1326
Zonr Changa7a828d2010-10-22 03:44:27 +08001327union RSType *RSExportConstantArrayType::convertToSpecType() const {
1328 llvm::OwningPtr<union RSType> ST(new union RSType);
1329
1330 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
1331 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
1332 ST, getElementType()->getSpecType());
1333 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
1334
1335 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
1336 return ST.take();
1337 else
1338 return NULL;
1339}
1340
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001341bool RSExportConstantArrayType::keep() {
1342 if (!RSExportType::keep())
1343 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001344 const_cast<RSExportType*>(mElementType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001345 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001346}
1347
1348bool RSExportConstantArrayType::equals(const RSExportable *E) const {
1349 CHECK_PARENT_EQUALITY(RSExportType, E);
Stephen Hinesa7b75182010-12-07 15:49:49 -08001350 const RSExportConstantArrayType *RHS =
1351 static_cast<const RSExportConstantArrayType*>(E);
1352 return ((getSize() == RHS->getSize()) &&
1353 (getElementType()->equals(RHS->getElementType())));
Zonr Chang641558f2010-10-12 21:07:06 +08001354}
1355
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001356/**************************** RSExportRecordType ****************************/
1357RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
1358 const clang::RecordType *RT,
1359 const llvm::StringRef &TypeName,
1360 bool mIsArtificial) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001361 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001362
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001363 const clang::RecordDecl *RD = RT->getDecl();
Stephen Hines6e6578a2011-02-07 18:05:48 -08001364 slangAssert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001365
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001366 RD = RD->getDefinition();
1367 if (RD == NULL) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001368 slangAssert(false && "struct is not defined in this module");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001369 return NULL;
1370 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001371
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001372 // Struct layout construct by clang. We rely on this for obtaining the
1373 // alloc size of a struct and offset of every field in that struct.
1374 const clang::ASTRecordLayout *RL =
Stephen Hines9e5b5032010-11-03 13:19:14 -07001375 &Context->getASTContext().getASTRecordLayout(RD);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001376 slangAssert((RL != NULL) &&
1377 "Failed to retrieve the struct layout from Clang.");
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001378
1379 RSExportRecordType *ERT =
1380 new RSExportRecordType(Context,
1381 TypeName,
1382 RD->hasAttr<clang::PackedAttr>(),
1383 mIsArtificial,
Shih-wei Liao68318a12011-03-11 05:56:15 -08001384 RL->getSize().getQuantity());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001385 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001386
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001387 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1388 FE = RD->field_end();
1389 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -07001390 FI++, Index++) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001391 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001392
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001393 // FIXME: All fields should be primitive type
Shih-wei Liao43730fe2012-08-02 23:06:18 -07001394 slangAssert(FI->getKind() == clang::Decl::Field);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001395 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001396
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001397 if (FD->isBitField()) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001398 return NULL;
1399 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001400
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001401 // Type
zonr6315f762010-10-05 15:35:14 +08001402 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001403
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001404 if (ET != NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001405 ERT->mFields.push_back(
1406 new Field(ET, FD->getName(), ERT,
1407 static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001408 } else {
Logan Chien9207a2e2011-10-21 15:39:28 +08001409 DiagEngine->Report(
1410 clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()),
1411 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1412 "field type cannot be exported: '%0.%1'"))
1413 << RD->getName() << FD->getName();
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001414 return NULL;
1415 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001416 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001417
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001418 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001419}
1420
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001421llvm::Type *RSExportRecordType::convertToLLVMType() const {
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001422 // Create an opaque type since struct may reference itself recursively.
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001423
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001424 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to?
1425 std::vector<llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001426
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001427 for (const_field_iterator FI = fields_begin(), FE = fields_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001428 FI != FE;
1429 FI++) {
1430 const Field *F = *FI;
1431 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -07001432
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001433 FieldTypes.push_back(FET->getLLVMType());
1434 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001435
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001436 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
1437 FieldTypes,
1438 mIsPacked);
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001439 if (ST != NULL) {
1440 return ST;
1441 } else {
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001442 return NULL;
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001443 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001444}
Zonr Chang641558f2010-10-12 21:07:06 +08001445
Zonr Changa7a828d2010-10-22 03:44:27 +08001446union RSType *RSExportRecordType::convertToSpecType() const {
1447 unsigned NumFields = getFields().size();
1448 unsigned AllocSize = sizeof(union RSType) +
1449 sizeof(struct RSRecordField) * NumFields;
1450 llvm::OwningPtr<union RSType> ST(
Stephen Hinese639eb52010-11-08 19:27:20 -08001451 reinterpret_cast<union RSType*>(operator new(AllocSize)));
Zonr Changa7a828d2010-10-22 03:44:27 +08001452
1453 ::memset(ST.get(), 0, AllocSize);
1454
1455 RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1456 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1457 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1458
1459 setSpecTypeTemporarily(ST.get());
1460
1461 unsigned FieldIdx = 0;
1462 for (const_field_iterator FI = fields_begin(), FE = fields_end();
1463 FI != FE;
1464 FI++, FieldIdx++) {
1465 const Field *F = *FI;
1466
1467 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1468 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
Zonr Changa7a828d2010-10-22 03:44:27 +08001469 }
1470
Stephen Hinese639eb52010-11-08 19:27:20 -08001471 // TODO(slang): Check whether all fields were created normally.
Zonr Changa7a828d2010-10-22 03:44:27 +08001472
1473 return ST.take();
1474}
1475
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001476bool RSExportRecordType::keep() {
1477 if (!RSExportType::keep())
1478 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001479 for (std::list<const Field*>::iterator I = mFields.begin(),
1480 E = mFields.end();
1481 I != E;
1482 I++) {
1483 const_cast<RSExportType*>((*I)->getType())->keep();
1484 }
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001485 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001486}
1487
1488bool RSExportRecordType::equals(const RSExportable *E) const {
1489 CHECK_PARENT_EQUALITY(RSExportType, E);
1490
1491 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1492
1493 if (ERT->getFields().size() != getFields().size())
1494 return false;
1495
1496 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1497
1498 for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1499 if (!(*AI)->getType()->equals((*BI)->getType()))
1500 return false;
1501 AI++;
1502 BI++;
1503 }
1504
1505 return true;
1506}
Stephen Hinese639eb52010-11-08 19:27:20 -08001507
Jason Sams1b6a0882012-03-12 15:07:58 -07001508void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
1509 memset(rtd, 0, sizeof(*rtd));
1510 rtd->vecSize = 1;
1511
1512 switch(getClass()) {
1513 case RSExportType::ExportClassPrimitive: {
1514 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
1515 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
1516 return;
1517 }
1518 case RSExportType::ExportClassPointer: {
1519 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
1520 const RSExportType *PointeeType = EPT->getPointeeType();
1521 PointeeType->convertToRTD(rtd);
1522 rtd->isPointer = true;
1523 return;
1524 }
1525 case RSExportType::ExportClassVector: {
1526 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
1527 rtd->type = EVT->getRSReflectionType(EVT);
1528 rtd->vecSize = EVT->getNumElement();
1529 return;
1530 }
1531 case RSExportType::ExportClassMatrix: {
1532 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
1533 unsigned Dim = EMT->getDim();
1534 slangAssert((Dim >= 2) && (Dim <= 4));
1535 rtd->type = &gReflectionTypes[15 + Dim-2];
1536 return;
1537 }
1538 case RSExportType::ExportClassConstantArray: {
1539 const RSExportConstantArrayType* CAT =
1540 static_cast<const RSExportConstantArrayType*>(this);
1541 CAT->getElementType()->convertToRTD(rtd);
1542 rtd->arraySize = CAT->getSize();
1543 return;
1544 }
1545 case RSExportType::ExportClassRecord: {
1546 slangAssert(!"RSExportType::ExportClassRecord not implemented");
1547 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
1548 }
1549 default: {
1550 slangAssert(false && "Unknown class of type");
1551 }
1552 }
1553}
1554
1555
Stephen Hinese639eb52010-11-08 19:27:20 -08001556} // namespace slang