blob: 4ab4af27e59b392dfd044a53c2150f1e60b9fdbf [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
Stephen Hinese639eb52010-11-08 19:27:20 -080022#include "clang/AST/RecordLayout.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070023
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024#include "llvm/ADT/StringExtras.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080025
26#include "llvm/DerivedTypes.h"
27
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070028#include "llvm/Target/TargetData.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070029
Stephen Hinese639eb52010-11-08 19:27:20 -080030#include "llvm/Type.h"
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070031
Stephen Hines6e6578a2011-02-07 18:05:48 -080032#include "slang_assert.h"
zonr6315f762010-10-05 15:35:14 +080033#include "slang_rs_context.h"
34#include "slang_rs_export_element.h"
Zonr Changa7a828d2010-10-22 03:44:27 +080035#include "slang_rs_type_spec.h"
Stephen Hinesd5a84f62012-04-04 17:44:38 -070036#include "slang_version.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070037
Zonr Chang641558f2010-10-12 21:07:06 +080038#define CHECK_PARENT_EQUALITY(ParentClass, E) \
39 if (!ParentClass::equals(E)) \
40 return false;
41
Stephen Hinese639eb52010-11-08 19:27:20 -080042namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070043
Stephen Hinese5e64432010-12-02 18:48:20 -080044namespace {
45
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080046static RSReflectionType gReflectionTypes[] = {
47 {"FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false},
48 {"FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false},
49 {"FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false},
50 {"SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false},
51 {"SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false},
52 {"SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false},
53 {"SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false},
Stephen Hines47aca4e2012-03-08 20:07:28 -080054 {"UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true},
55 {"UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true},
56 {"UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true},
57 {"UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false},
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080058
Stephen Hines47aca4e2012-03-08 20:07:28 -080059 {"BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false},
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080060
61 {"UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false},
62 {"UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false},
63 {"UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false},
64
65 {"MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false},
66 {"MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false},
67 {"MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false},
68
69 {"RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false},
70 {"RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false},
71 {"RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false},
72 {"RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false},
73 {"RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false},
74 {"RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false},
75 {"RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false},
76 {"RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false},
77 {"RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false},
78 {"RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false},
79 {"RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false},
80 {"RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false}
81};
82
Stephen Hines24e79f62010-12-13 12:55:57 -080083static const clang::Type *TypeExportableHelper(
84 const clang::Type *T,
85 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Logan Chien9207a2e2011-10-21 15:39:28 +080086 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -080087 const clang::VarDecl *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -070088 const clang::RecordDecl *TopLevelRecord);
Stephen Hines24e79f62010-12-13 12:55:57 -080089
Logan Chien9207a2e2011-10-21 15:39:28 +080090static void ReportTypeError(clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -080091 const clang::VarDecl *VD,
92 const clang::RecordDecl *TopLevelRecord,
Stephen Hinesd5a84f62012-04-04 17:44:38 -070093 const char *Message,
94 unsigned int TargetAPI = 0) {
Logan Chien9207a2e2011-10-21 15:39:28 +080095 if (!DiagEngine) {
Stephen Hines24e79f62010-12-13 12:55:57 -080096 return;
97 }
98
Logan Chien9207a2e2011-10-21 15:39:28 +080099 const clang::SourceManager &SM = DiagEngine->getSourceManager();
Stephen Hines78e69cb2011-04-22 15:03:19 -0700100
Stephen Hines24e79f62010-12-13 12:55:57 -0800101 // Attempt to use the type declaration first (if we have one).
102 // Fall back to the variable definition, if we are looking at something
103 // like an array declaration that can't be exported.
104 if (TopLevelRecord) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800105 DiagEngine->Report(
106 clang::FullSourceLoc(TopLevelRecord->getLocation(), SM),
107 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700108 << TopLevelRecord->getName() << TargetAPI;
Stephen Hines24e79f62010-12-13 12:55:57 -0800109 } else if (VD) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800110 DiagEngine->Report(
111 clang::FullSourceLoc(VD->getLocation(), SM),
112 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700113 << VD->getName() << TargetAPI;
Stephen Hines24e79f62010-12-13 12:55:57 -0800114 } else {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800115 slangAssert(false && "Variables should be validated before exporting");
Stephen Hines24e79f62010-12-13 12:55:57 -0800116 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800117}
118
119static const clang::Type *ConstantArrayTypeExportableHelper(
120 const clang::ConstantArrayType *CAT,
121 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Logan Chien9207a2e2011-10-21 15:39:28 +0800122 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -0800123 const clang::VarDecl *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700124 const clang::RecordDecl *TopLevelRecord) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800125 // Check element type
126 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
127 if (ElementType->isArrayType()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800128 ReportTypeError(DiagEngine, VD, TopLevelRecord,
129 "multidimensional arrays cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800130 return NULL;
131 } else if (ElementType->isExtVectorType()) {
132 const clang::ExtVectorType *EVT =
133 static_cast<const clang::ExtVectorType*>(ElementType);
134 unsigned numElements = EVT->getNumElements();
135
136 const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
137 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800138 ReportTypeError(DiagEngine, VD, TopLevelRecord,
139 "vectors of non-primitive types cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800140 return NULL;
141 }
142
143 if (numElements == 3 && CAT->getSize() != 1) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800144 ReportTypeError(DiagEngine, VD, TopLevelRecord,
145 "arrays of width 3 vector types cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800146 return NULL;
147 }
148 }
149
Logan Chien9207a2e2011-10-21 15:39:28 +0800150 if (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700151 TopLevelRecord) == NULL) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800152 return NULL;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700153 } else {
Stephen Hines24e79f62010-12-13 12:55:57 -0800154 return CAT;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700155 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800156}
157
158static const clang::Type *TypeExportableHelper(
Stephen Hinese67239d2012-02-24 15:08:36 -0800159 clang::Type const *T,
160 llvm::SmallPtrSet<clang::Type const *, 8> &SPS,
161 clang::DiagnosticsEngine *DiagEngine,
162 clang::VarDecl const *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700163 clang::RecordDecl const *TopLevelRecord) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800164 // Normalize first
165 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
166 return NULL;
167
168 if (SPS.count(T))
169 return T;
170
171 switch (T->getTypeClass()) {
172 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800173 const clang::BuiltinType *BT =
174 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800175
176 switch (BT->getKind()) {
177#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
178 case builtin_type:
179#include "RSClangBuiltinEnums.inc"
180 return T;
181 default: {
182 return NULL;
183 }
184 }
185 }
186 case clang::Type::Record: {
187 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700188 RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800189 return T; // RS object type, no further checks are needed
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700190 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800191
192 // Check internal struct
Stephen Hinescd440ee2010-12-06 14:57:04 -0800193 if (T->isUnionType()) {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700194 ReportTypeError(DiagEngine, VD, T->getAsUnionType()->getDecl(),
Logan Chien9207a2e2011-10-21 15:39:28 +0800195 "unions cannot be exported: '%0'");
Stephen Hinescd440ee2010-12-06 14:57:04 -0800196 return NULL;
197 } else if (!T->isStructureType()) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800198 slangAssert(false && "Unknown type cannot be exported");
Stephen Hinescd440ee2010-12-06 14:57:04 -0800199 return NULL;
200 }
201
Stephen Hines24e79f62010-12-13 12:55:57 -0800202 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800203 if (RD != NULL) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800204 RD = RD->getDefinition();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800205 if (RD == NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800206 ReportTypeError(DiagEngine, NULL, T->getAsStructureType()->getDecl(),
207 "struct is not defined in this module");
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800208 return NULL;
209 }
210 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800211
212 if (!TopLevelRecord) {
213 TopLevelRecord = RD;
214 }
215 if (RD->getName().empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800216 ReportTypeError(DiagEngine, NULL, RD,
217 "anonymous structures cannot be exported");
Stephen Hinese5e64432010-12-02 18:48:20 -0800218 return NULL;
219 }
220
221 // Fast check
222 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
223 return NULL;
224
225 // Insert myself into checking set
226 SPS.insert(T);
227
228 // Check all element
229 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
230 FE = RD->field_end();
231 FI != FE;
232 FI++) {
233 const clang::FieldDecl *FD = *FI;
234 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
235 FT = GET_CANONICAL_TYPE(FT);
236
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700237 if (!TypeExportableHelper(FT, SPS, DiagEngine, VD, TopLevelRecord)) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800238 return NULL;
239 }
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800240
241 // We don't support bit fields yet
242 //
243 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32
244 if (FD->isBitField()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800245 if (DiagEngine) {
246 DiagEngine->Report(
247 clang::FullSourceLoc(FD->getLocation(),
248 DiagEngine->getSourceManager()),
249 DiagEngine->getCustomDiagID(
250 clang::DiagnosticsEngine::Error,
251 "bit fields are not able to be exported: '%0.%1'"))
252 << RD->getName()
253 << FD->getName();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800254 }
255 return NULL;
256 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800257 }
258
259 return T;
260 }
261 case clang::Type::Pointer: {
262 if (TopLevelRecord) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800263 ReportTypeError(DiagEngine, NULL, TopLevelRecord,
264 "structures containing pointers cannot be exported: '%0'");
Stephen Hinese5e64432010-12-02 18:48:20 -0800265 return NULL;
266 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800267
Loganbe274822011-02-16 22:02:54 +0800268 const clang::PointerType *PT =
269 UNSAFE_CAST_TYPE(const clang::PointerType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800270 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
271
272 if (PointeeType->getTypeClass() == clang::Type::Pointer)
273 return T;
274 // We don't support pointer with array-type pointee or unsupported pointee
275 // type
276 if (PointeeType->isArrayType() ||
Logan Chien9207a2e2011-10-21 15:39:28 +0800277 (TypeExportableHelper(PointeeType, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700278 TopLevelRecord) == NULL))
Stephen Hinese5e64432010-12-02 18:48:20 -0800279 return NULL;
280 else
281 return T;
282 }
283 case clang::Type::ExtVector: {
284 const clang::ExtVectorType *EVT =
Loganbe274822011-02-16 22:02:54 +0800285 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800286 // Only vector with size 2, 3 and 4 are supported.
287 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
288 return NULL;
289
290 // Check base element type
291 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
292
293 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
Logan Chien9207a2e2011-10-21 15:39:28 +0800294 (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700295 TopLevelRecord) == NULL))
Stephen Hinese5e64432010-12-02 18:48:20 -0800296 return NULL;
297 else
298 return T;
299 }
300 case clang::Type::ConstantArray: {
301 const clang::ConstantArrayType *CAT =
Loganbe274822011-02-16 22:02:54 +0800302 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800303
Logan Chien9207a2e2011-10-21 15:39:28 +0800304 return ConstantArrayTypeExportableHelper(CAT, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700305 TopLevelRecord);
Stephen Hinese5e64432010-12-02 18:48:20 -0800306 }
307 default: {
308 return NULL;
309 }
310 }
311}
312
313// Return the type that can be used to create RSExportType, will always return
314// the canonical type
Logan Chien9207a2e2011-10-21 15:39:28 +0800315// If the Type T is not exportable, this function returns NULL. DiagEngine is
Stephen Hines78e69cb2011-04-22 15:03:19 -0700316// used to generate proper Clang diagnostic messages when a
Stephen Hinese5e64432010-12-02 18:48:20 -0800317// non-exportable type is detected. TopLevelRecord is used to capture the
318// highest struct (in the case of a nested hierarchy) for detecting other
319// types that cannot be exported (mostly pointers within a struct).
320static const clang::Type *TypeExportable(const clang::Type *T,
Logan Chien9207a2e2011-10-21 15:39:28 +0800321 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700322 const clang::VarDecl *VD) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700323 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
324 llvm::SmallPtrSet<const clang::Type*, 8>();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700325
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700326 return TypeExportableHelper(T, SPS, DiagEngine, VD, NULL);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700327}
328
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700329static bool ValidateRSObjectInVarDecl(clang::VarDecl *VD,
330 bool InCompositeType,
331 unsigned int TargetAPI) {
332 if (TargetAPI < SLANG_JB_TARGET_API) {
333 // Only if we are already in a composite type (like an array or structure).
334 if (InCompositeType) {
335 // Only if we are actually exported (i.e. non-static).
336 if (VD->getLinkage() == clang::ExternalLinkage) {
337 // Only if we are not a pointer to an object.
338 const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr());
339 if (T->getTypeClass() != clang::Type::Pointer) {
340 clang::ASTContext &C = VD->getASTContext();
341 ReportTypeError(&C.getDiagnostics(), VD, NULL,
342 "arrays/structures containing RS object types "
343 "cannot be exported in target API < %1: '%0'",
344 SLANG_JB_TARGET_API);
345 return false;
346 }
347 }
348 }
349 }
350
351 return true;
352}
353
354// Helper function for ValidateVarDecl(). We do a recursive descent on the
355// type hierarchy to ensure that we can properly export/handle the
356// declaration.
357// \return true if the variable declaration is valid,
358// false if it is invalid (along with proper diagnostics).
359//
360// VD - top-level variable declaration that we are validating.
361// T - sub-type of VD's type that we are validating.
362// SPS - set of types we have already seen/validated.
363// InCompositeType - true if we are within an outer composite type.
364// UnionDecl - set if we are in a sub-type of a union.
365// TargetAPI - target SDK API level.
Stephen Hines78e69cb2011-04-22 15:03:19 -0700366static bool ValidateVarDeclHelper(
367 clang::VarDecl *VD,
368 const clang::Type *&T,
369 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700370 bool InCompositeType,
371 clang::RecordDecl *UnionDecl,
372 unsigned int TargetAPI) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700373 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
374 return true;
375
376 if (SPS.count(T))
377 return true;
378
379 switch (T->getTypeClass()) {
380 case clang::Type::Record: {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700381 if (RSExportPrimitiveType::IsRSObjectType(T)) {
382 if (!ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) {
383 return false;
384 }
385 }
386
Stephen Hines78e69cb2011-04-22 15:03:19 -0700387 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
388 RSExportPrimitiveType::DataTypeUnknown) {
389 if (!UnionDecl) {
390 return true;
391 } else if (RSExportPrimitiveType::IsRSObjectType(T)) {
392 clang::ASTContext &C = VD->getASTContext();
393 ReportTypeError(&C.getDiagnostics(), VD, UnionDecl,
394 "unions containing RS object types are not allowed");
395 return false;
396 }
397 }
398
399 clang::RecordDecl *RD = NULL;
400
401 // Check internal struct
402 if (T->isUnionType()) {
403 RD = T->getAsUnionType()->getDecl();
404 UnionDecl = RD;
405 } else if (T->isStructureType()) {
406 RD = T->getAsStructureType()->getDecl();
407 } else {
408 slangAssert(false && "Unknown type cannot be exported");
409 return false;
410 }
411
412 if (RD != NULL) {
413 RD = RD->getDefinition();
414 if (RD == NULL) {
415 // FIXME
416 return true;
417 }
418 }
419
420 // Fast check
421 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
422 return false;
423
424 // Insert myself into checking set
425 SPS.insert(T);
426
427 // Check all elements
428 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
429 FE = RD->field_end();
430 FI != FE;
431 FI++) {
432 const clang::FieldDecl *FD = *FI;
433 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
434 FT = GET_CANONICAL_TYPE(FT);
435
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700436 if (!ValidateVarDeclHelper(VD, FT, SPS, true, UnionDecl, TargetAPI)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700437 return false;
438 }
439 }
440
441 return true;
442 }
443
444 case clang::Type::Builtin: {
445 break;
446 }
447
448 case clang::Type::Pointer: {
449 const clang::PointerType *PT =
450 UNSAFE_CAST_TYPE(const clang::PointerType, T);
451 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
452
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700453 return ValidateVarDeclHelper(VD, PointeeType, SPS, InCompositeType,
454 UnionDecl, TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700455 }
456
457 case clang::Type::ExtVector: {
458 const clang::ExtVectorType *EVT =
459 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
460 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700461 return ValidateVarDeclHelper(VD, ElementType, SPS, true, UnionDecl,
462 TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700463 }
464
465 case clang::Type::ConstantArray: {
466 const clang::ConstantArrayType *CAT =
467 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
468 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700469 return ValidateVarDeclHelper(VD, ElementType, SPS, true, UnionDecl,
470 TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700471 }
472
473 default: {
474 break;
475 }
476 }
477
478 return true;
Stephen Hinese5e64432010-12-02 18:48:20 -0800479}
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700480
Stephen Hinese5e64432010-12-02 18:48:20 -0800481} // namespace
482
483/****************************** RSExportType ******************************/
484bool RSExportType::NormalizeType(const clang::Type *&T,
485 llvm::StringRef &TypeName,
Logan Chien9207a2e2011-10-21 15:39:28 +0800486 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700487 const clang::VarDecl *VD) {
488 if ((T = TypeExportable(T, DiagEngine, VD)) == NULL) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800489 return false;
490 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700491 // Get type name
492 TypeName = RSExportType::GetTypeName(T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800493 if (TypeName.empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800494 if (DiagEngine) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800495 if (VD) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800496 DiagEngine->Report(
497 clang::FullSourceLoc(VD->getLocation(),
498 DiagEngine->getSourceManager()),
499 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
500 "anonymous types cannot be exported"));
Stephen Hines24e79f62010-12-13 12:55:57 -0800501 } else {
Logan Chien9207a2e2011-10-21 15:39:28 +0800502 DiagEngine->Report(
503 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
504 "anonymous types cannot be exported"));
Stephen Hines24e79f62010-12-13 12:55:57 -0800505 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800506 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700507 return false;
Stephen Hinese5e64432010-12-02 18:48:20 -0800508 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700509
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700510 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700511}
512
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700513bool RSExportType::ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700514 const clang::Type *T = VD->getType().getTypePtr();
515 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
516 llvm::SmallPtrSet<const clang::Type*, 8>();
517
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700518 return ValidateVarDeclHelper(VD, T, SPS, false, NULL, TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700519}
520
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700521const clang::Type
522*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800523 if (DD) {
524 clang::QualType T;
525 if (DD->getTypeSourceInfo())
526 T = DD->getTypeSourceInfo()->getType();
527 else
528 T = DD->getType();
529
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700530 if (T.isNull())
531 return NULL;
532 else
533 return T.getTypePtr();
534 }
535 return NULL;
536}
537
538llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
539 T = GET_CANONICAL_TYPE(T);
540 if (T == NULL)
541 return llvm::StringRef();
542
543 switch (T->getTypeClass()) {
544 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800545 const clang::BuiltinType *BT =
546 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700547
548 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800549#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
550 case builtin_type: \
551 return cname; \
552 break;
553#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800554 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800555 slangAssert(false && "Unknown data type of the builtin");
Zonr Changa65ec162010-10-17 01:53:05 +0800556 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700557 }
Zonr Changa65ec162010-10-17 01:53:05 +0800558 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700559 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700560 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700561 case clang::Type::Record: {
Stephen Hinescd440ee2010-12-06 14:57:04 -0800562 clang::RecordDecl *RD;
563 if (T->isStructureType()) {
564 RD = T->getAsStructureType()->getDecl();
Stephen Hinesdd6206b2010-12-09 19:39:22 -0800565 } else {
Stephen Hinescd440ee2010-12-06 14:57:04 -0800566 break;
567 }
568
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700569 llvm::StringRef Name = RD->getName();
570 if (Name.empty()) {
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700571 if (RD->getTypedefNameForAnonDecl() != NULL) {
572 Name = RD->getTypedefNameForAnonDecl()->getName();
573 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700574
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700575 if (Name.empty()) {
576 // Try to find a name from redeclaration (i.e. typedef)
577 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
578 RE = RD->redecls_end();
579 RI != RE;
580 RI++) {
581 slangAssert(*RI != NULL && "cannot be NULL object");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700582
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700583 Name = (*RI)->getName();
584 if (!Name.empty())
585 break;
586 }
587 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700588 }
589 return Name;
590 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700591 case clang::Type::Pointer: {
592 // "*" plus pointee name
zonr6315f762010-10-05 15:35:14 +0800593 const clang::Type *PT = GET_POINTEE_TYPE(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700594 llvm::StringRef PointeeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700595 if (NormalizeType(PT, PointeeName, NULL, NULL)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700596 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
597 Name[0] = '*';
598 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
599 Name[PointeeName.size() + 1] = '\0';
600 return Name;
601 }
602 break;
603 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700604 case clang::Type::ExtVector: {
605 const clang::ExtVectorType *EVT =
Loganbe274822011-02-16 22:02:54 +0800606 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700607 return RSExportVectorType::GetTypeName(EVT);
608 break;
609 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800610 case clang::Type::ConstantArray : {
611 // Construct name for a constant array is too complicated.
612 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE;
613 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700614 default: {
615 break;
616 }
617 }
618
619 return llvm::StringRef();
620}
621
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700622
623RSExportType *RSExportType::Create(RSContext *Context,
624 const clang::Type *T,
625 const llvm::StringRef &TypeName) {
626 // Lookup the context to see whether the type was processed before.
627 // Newly created RSExportType will insert into context
628 // in RSExportType::RSExportType()
629 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
630
631 if (ETI != Context->export_types_end())
632 return ETI->second;
633
634 RSExportType *ET = NULL;
635 switch (T->getTypeClass()) {
636 case clang::Type::Record: {
637 RSExportPrimitiveType::DataType dt =
Zonr Changb1771ef2010-10-22 18:03:46 +0800638 RSExportPrimitiveType::GetRSSpecificType(TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700639 switch (dt) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800640 case RSExportPrimitiveType::DataTypeUnknown: {
641 // User-defined types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700642 ET = RSExportRecordType::Create(Context,
643 T->getAsStructureType(),
644 TypeName);
645 break;
646 }
Zonr Chang92b344a2010-10-05 20:39:03 +0800647 case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
648 // 2 x 2 Matrix type
649 ET = RSExportMatrixType::Create(Context,
650 T->getAsStructureType(),
651 TypeName,
652 2);
653 break;
654 }
655 case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
656 // 3 x 3 Matrix type
657 ET = RSExportMatrixType::Create(Context,
658 T->getAsStructureType(),
659 TypeName,
660 3);
661 break;
662 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700663 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800664 // 4 x 4 Matrix type
665 ET = RSExportMatrixType::Create(Context,
666 T->getAsStructureType(),
667 TypeName,
668 4);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700669 break;
670 }
671 default: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800672 // Others are primitive types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700673 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
674 break;
675 }
676 }
677 break;
678 }
679 case clang::Type::Builtin: {
680 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
681 break;
682 }
683 case clang::Type::Pointer: {
684 ET = RSExportPointerType::Create(Context,
Stephen Hines5baf6322011-04-25 17:21:15 -0700685 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName);
Zonr Chang92b344a2010-10-05 20:39:03 +0800686 // FIXME: free the name (allocated in RSExportType::GetTypeName)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700687 delete [] TypeName.data();
688 break;
689 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700690 case clang::Type::ExtVector: {
691 ET = RSExportVectorType::Create(Context,
Stephen Hines5baf6322011-04-25 17:21:15 -0700692 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700693 break;
694 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800695 case clang::Type::ConstantArray: {
696 ET = RSExportConstantArrayType::Create(
697 Context,
Loganbe274822011-02-16 22:02:54 +0800698 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T));
Zonr Chang2e1dba62010-10-05 22:20:11 +0800699 break;
700 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700701 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800702 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
703 DiagEngine->Report(
704 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
705 "unknown type cannot be exported: '%0'"))
706 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700707 break;
708 }
709 }
710
711 return ET;
712}
713
zonr6315f762010-10-05 15:35:14 +0800714RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700715 llvm::StringRef TypeName;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700716 if (NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700717 return Create(Context, T, TypeName);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700718 } else {
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700719 return NULL;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700720 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700721}
722
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700723RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
724 const clang::VarDecl *VD) {
725 return RSExportType::Create(Context, GetTypeOfDecl(VD));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700726}
727
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700728size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
729 return ET->getRSContext()->getTargetData()->getTypeStoreSize(
zonr6315f762010-10-05 15:35:14 +0800730 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700731}
732
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700733size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
734 if (ET->getClass() == RSExportType::ExportClassRecord)
735 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
736 else
737 return ET->getRSContext()->getTargetData()->getTypeAllocSize(
zonr6315f762010-10-05 15:35:14 +0800738 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700739}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700740
Zonr Chang6b6320a2010-10-05 22:42:01 +0800741RSExportType::RSExportType(RSContext *Context,
742 ExportClass Class,
743 const llvm::StringRef &Name)
Zonr Changa41ce1d2010-10-06 02:23:12 +0800744 : RSExportable(Context, RSExportable::EX_TYPE),
Zonr Chang6b6320a2010-10-05 22:42:01 +0800745 mClass(Class),
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800746 // Make a copy on Name since memory stored @Name is either allocated in
747 // ASTContext or allocated in GetTypeName which will be destroyed later.
zonr6315f762010-10-05 15:35:14 +0800748 mName(Name.data(), Name.size()),
Zonr Changa7a828d2010-10-22 03:44:27 +0800749 mLLVMType(NULL),
750 mSpecType(NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800751 // Don't cache the type whose name start with '<'. Those type failed to
752 // get their name since constructing their name in GetTypeName() requiring
753 // complicated work.
754 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
755 // TODO(zonr): Need to check whether the insertion is successful or not.
756 Context->insertExportType(llvm::StringRef(Name), this);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700757 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700758}
759
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800760bool RSExportType::keep() {
761 if (!RSExportable::keep())
762 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800763 // Invalidate converted LLVM type.
764 mLLVMType = NULL;
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800765 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800766}
767
768bool RSExportType::equals(const RSExportable *E) const {
769 CHECK_PARENT_EQUALITY(RSExportable, E);
770 return (static_cast<const RSExportType*>(E)->getClass() == getClass());
771}
772
Zonr Changa7a828d2010-10-22 03:44:27 +0800773RSExportType::~RSExportType() {
774 delete mSpecType;
775}
776
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700777/************************** RSExportPrimitiveType **************************/
Zonr Changb1771ef2010-10-22 18:03:46 +0800778llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy>
779RSExportPrimitiveType::RSSpecificTypeMap;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700780
zonr6315f762010-10-05 15:35:14 +0800781llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700782
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700783bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
784 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
785 return true;
786 else
787 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700788}
789
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700790RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800791RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700792 if (TypeName.empty())
793 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700794
Zonr Changb1771ef2010-10-22 18:03:46 +0800795 if (RSSpecificTypeMap->empty()) {
796#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \
797 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
798#include "RSMatrixTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800799#define ENUM_RS_OBJECT_TYPE(type, cname) \
Zonr Changb1771ef2010-10-22 18:03:46 +0800800 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
Zonr Changa65ec162010-10-17 01:53:05 +0800801#include "RSObjectTypeEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700802 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700803
Zonr Changb1771ef2010-10-22 18:03:46 +0800804 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName);
805 if (I == RSSpecificTypeMap->end())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700806 return DataTypeUnknown;
807 else
808 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700809}
810
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700811RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800812RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700813 T = GET_CANONICAL_TYPE(T);
814 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
815 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700816
Zonr Changb1771ef2010-10-22 18:03:46 +0800817 return GetRSSpecificType( RSExportType::GetTypeName(T) );
818}
819
820bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) {
821 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType));
822}
823
824bool RSExportPrimitiveType::IsRSObjectType(DataType DT) {
825 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700826}
827
Stephen Hinesfeaca062011-02-04 14:08:13 -0800828bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) {
829 bool RSObjectTypeSeen = false;
830 while (T && T->isArrayType()) {
831 T = T->getArrayElementTypeNoTypeQual();
832 }
833
834 const clang::RecordType *RT = T->getAsStructureType();
835 if (!RT) {
836 return false;
837 }
838 const clang::RecordDecl *RD = RT->getDecl();
839 RD = RD->getDefinition();
840 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
841 FE = RD->field_end();
842 FI != FE;
843 FI++) {
844 // We just look through all field declarations to see if we find a
845 // declaration for an RS object type (or an array of one).
846 const clang::FieldDecl *FD = *FI;
847 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
848 while (FT && FT->isArrayType()) {
849 FT = FT->getArrayElementTypeNoTypeQual();
850 }
851
852 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT);
853 if (IsRSObjectType(DT)) {
854 // RS object types definitely need to be zero-initialized
855 RSObjectTypeSeen = true;
856 } else {
857 switch (DT) {
858 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
859 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
860 case RSExportPrimitiveType::DataTypeRSMatrix4x4:
861 // Matrix types should get zero-initialized as well
862 RSObjectTypeSeen = true;
863 break;
864 default:
865 // Ignore all other primitive types
866 break;
867 }
868 while (FT && FT->isArrayType()) {
869 FT = FT->getArrayElementTypeNoTypeQual();
870 }
871 if (FT->isStructureType()) {
872 // Recursively handle structs of structs (even though these can't
873 // be exported, it is possible for a user to have them internally).
874 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT);
875 }
876 }
877 }
878
879 return RSObjectTypeSeen;
880}
881
Zonr Changa65ec162010-10-17 01:53:05 +0800882const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
883#define ENUM_RS_DATA_TYPE(type, cname, bits) \
884 bits,
885#include "RSDataTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800886 0 // DataTypeMax
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700887};
888
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700889size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800890 slangAssert(((EPT->getType() > DataTypeUnknown) &&
891 (EPT->getType() < DataTypeMax)) &&
892 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700893 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700894}
895
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700896RSExportPrimitiveType::DataType
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800897RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700898 if (T == NULL)
899 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700900
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700901 switch (T->getTypeClass()) {
902 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800903 const clang::BuiltinType *BT =
904 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700905 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800906#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
907 case builtin_type: { \
908 return DataType ## type; \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700909 }
Zonr Changa65ec162010-10-17 01:53:05 +0800910#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800911 // The size of type WChar depend on platform so we abandon the support
912 // to them.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700913 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800914 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
915 DiagEngine->Report(
916 DiagEngine->getCustomDiagID(
917 clang::DiagnosticsEngine::Error,
918 "built-in type cannot be exported: '%0'"))
919 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700920 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700921 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700922 }
923 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700924 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700925 case clang::Type::Record: {
926 // must be RS object type
Zonr Changb1771ef2010-10-22 18:03:46 +0800927 return RSExportPrimitiveType::GetRSSpecificType(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700928 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700929 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800930 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
931 DiagEngine->Report(
932 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
933 "primitive type cannot be exported: '%0'"))
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800934 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700935 break;
936 }
937 }
938
939 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700940}
941
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700942RSExportPrimitiveType
943*RSExportPrimitiveType::Create(RSContext *Context,
944 const clang::Type *T,
945 const llvm::StringRef &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700946 bool Normalized) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800947 DataType DT = GetDataType(Context, T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700948
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700949 if ((DT == DataTypeUnknown) || TypeName.empty())
950 return NULL;
951 else
Zonr Chang6b6320a2010-10-05 22:42:01 +0800952 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
Stephen Hines2b8fb642012-03-09 00:12:47 -0800953 DT, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700954}
955
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700956RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
Stephen Hines2b8fb642012-03-09 00:12:47 -0800957 const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700958 llvm::StringRef TypeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700959 if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)
Stephen Hines78e69cb2011-04-22 15:03:19 -0700960 && IsPrimitiveType(T)) {
Stephen Hines2b8fb642012-03-09 00:12:47 -0800961 return Create(Context, T, TypeName);
Stephen Hinese5e64432010-12-02 18:48:20 -0800962 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700963 return NULL;
Stephen Hinese5e64432010-12-02 18:48:20 -0800964 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700965}
966
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700967llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700968 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700969
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700970 if (isRSObjectType()) {
971 // struct {
972 // int *p;
973 // } __attribute__((packed, aligned(pointer_size)))
974 //
975 // which is
976 //
977 // <{ [1 x i32] }> in LLVM
978 //
979 if (RSObjectLLVMType == NULL) {
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700980 std::vector<llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +0800981 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Stephen Hinesa67e4452011-07-19 15:39:26 -0700982 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700983 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700984 return RSObjectLLVMType;
985 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700986
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700987 switch (mType) {
988 case DataTypeFloat32: {
989 return llvm::Type::getFloatTy(C);
990 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700991 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700992 case DataTypeFloat64: {
993 return llvm::Type::getDoubleTy(C);
994 break;
995 }
Shih-wei Liao91a37832010-10-03 19:11:51 -0700996 case DataTypeBoolean: {
997 return llvm::Type::getInt1Ty(C);
998 break;
999 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001000 case DataTypeSigned8:
1001 case DataTypeUnsigned8: {
1002 return llvm::Type::getInt8Ty(C);
1003 break;
1004 }
1005 case DataTypeSigned16:
1006 case DataTypeUnsigned16:
1007 case DataTypeUnsigned565:
1008 case DataTypeUnsigned5551:
1009 case DataTypeUnsigned4444: {
1010 return llvm::Type::getInt16Ty(C);
1011 break;
1012 }
1013 case DataTypeSigned32:
1014 case DataTypeUnsigned32: {
1015 return llvm::Type::getInt32Ty(C);
1016 break;
1017 }
Stephen Hinesa5d2c232010-10-11 16:10:02 -07001018 case DataTypeSigned64:
1019 case DataTypeUnsigned64: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001020 return llvm::Type::getInt64Ty(C);
1021 break;
1022 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001023 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001024 slangAssert(false && "Unknown data type");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001025 }
1026 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001027
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001028 return NULL;
1029}
1030
Zonr Changa7a828d2010-10-22 03:44:27 +08001031union RSType *RSExportPrimitiveType::convertToSpecType() const {
1032 llvm::OwningPtr<union RSType> ST(new union RSType);
1033 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
1034 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
1035 // slang_rs_type_spec.h
1036 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
1037 return ST.take();
1038}
1039
Zonr Chang641558f2010-10-12 21:07:06 +08001040bool RSExportPrimitiveType::equals(const RSExportable *E) const {
1041 CHECK_PARENT_EQUALITY(RSExportType, E);
1042 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
1043}
1044
Stephen Hinesfdd1ba12012-03-08 17:26:32 -08001045RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) {
1046 if (DT > DataTypeUnknown && DT < DataTypeMax) {
1047 return &gReflectionTypes[DT];
1048 } else {
1049 return NULL;
1050 }
1051}
1052
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001053/**************************** RSExportPointerType ****************************/
1054
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001055RSExportPointerType
1056*RSExportPointerType::Create(RSContext *Context,
1057 const clang::PointerType *PT,
1058 const llvm::StringRef &TypeName) {
1059 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
1060 const RSExportType *PointeeET;
1061
1062 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
1063 PointeeET = RSExportType::Create(Context, PointeeType);
1064 } else {
1065 // Double or higher dimension of pointer, export as int*
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001066 PointeeET = RSExportPrimitiveType::Create(Context,
1067 Context->getASTContext().IntTy.getTypePtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001068 }
1069
1070 if (PointeeET == NULL) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001071 // Error diagnostic is emitted for corresponding pointee type
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001072 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001073 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001074
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001075 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001076}
1077
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001078llvm::Type *RSExportPointerType::convertToLLVMType() const {
1079 llvm::Type *PointeeType = mPointeeType->getLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001080 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001081}
1082
Zonr Changa7a828d2010-10-22 03:44:27 +08001083union RSType *RSExportPointerType::convertToSpecType() const {
1084 llvm::OwningPtr<union RSType> ST(new union RSType);
1085
1086 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
1087 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
1088
1089 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
1090 return ST.take();
1091 else
1092 return NULL;
1093}
1094
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001095bool RSExportPointerType::keep() {
1096 if (!RSExportType::keep())
1097 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001098 const_cast<RSExportType*>(mPointeeType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001099 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001100}
1101
1102bool RSExportPointerType::equals(const RSExportable *E) const {
1103 CHECK_PARENT_EQUALITY(RSExportType, E);
1104 return (static_cast<const RSExportPointerType*>(E)
1105 ->getPointeeType()->equals(getPointeeType()));
1106}
1107
zonr6315f762010-10-05 15:35:14 +08001108/***************************** RSExportVectorType *****************************/
zonr6315f762010-10-05 15:35:14 +08001109llvm::StringRef
1110RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001111 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001112
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001113 if ((ElementType->getTypeClass() != clang::Type::Builtin))
1114 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001115
Loganbe274822011-02-16 22:02:54 +08001116 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001117 ElementType);
Zonr Changa65ec162010-10-17 01:53:05 +08001118 if ((EVT->getNumElements() < 1) ||
1119 (EVT->getNumElements() > 4))
1120 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001121
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001122 switch (BT->getKind()) {
1123 // Compiler is smart enough to optimize following *big if branches* since
1124 // they all become "constant comparison" after macro expansion
Zonr Changa65ec162010-10-17 01:53:05 +08001125#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
1126 case builtin_type: { \
1127 const char *Name[] = { cname"2", cname"3", cname"4" }; \
1128 return Name[EVT->getNumElements() - 2]; \
1129 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001130 }
Zonr Changa65ec162010-10-17 01:53:05 +08001131#include "RSClangBuiltinEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001132 default: {
1133 return llvm::StringRef();
1134 }
1135 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001136}
1137
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001138RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
1139 const clang::ExtVectorType *EVT,
1140 const llvm::StringRef &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001141 bool Normalized) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001142 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001143
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001144 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1145 RSExportPrimitiveType::DataType DT =
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001146 RSExportPrimitiveType::GetDataType(Context, ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001147
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001148 if (DT != RSExportPrimitiveType::DataTypeUnknown)
1149 return new RSExportVectorType(Context,
1150 TypeName,
1151 DT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001152 Normalized,
1153 EVT->getNumElements());
1154 else
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001155 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001156}
1157
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001158llvm::Type *RSExportVectorType::convertToLLVMType() const {
1159 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001160 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001161}
1162
Zonr Changa7a828d2010-10-22 03:44:27 +08001163union RSType *RSExportVectorType::convertToSpecType() const {
1164 llvm::OwningPtr<union RSType> ST(new union RSType);
1165
1166 RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
1167 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
1168 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
1169
1170 return ST.take();
1171}
1172
Zonr Chang641558f2010-10-12 21:07:06 +08001173bool RSExportVectorType::equals(const RSExportable *E) const {
1174 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
1175 return (static_cast<const RSExportVectorType*>(E)->getNumElement()
1176 == getNumElement());
1177}
1178
Zonr Chang92b344a2010-10-05 20:39:03 +08001179/***************************** RSExportMatrixType *****************************/
1180RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
1181 const clang::RecordType *RT,
1182 const llvm::StringRef &TypeName,
1183 unsigned Dim) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001184 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
1185 slangAssert((Dim > 1) && "Invalid dimension of matrix");
Zonr Chang92b344a2010-10-05 20:39:03 +08001186
1187 // Check whether the struct rs_matrix is in our expected form (but assume it's
1188 // correct if we're not sure whether it's correct or not)
1189 const clang::RecordDecl* RD = RT->getDecl();
1190 RD = RD->getDefinition();
1191 if (RD != NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001192 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001193 const clang::SourceManager *SM = Context->getSourceManager();
Zonr Chang92b344a2010-10-05 20:39:03 +08001194 // Find definition, perform further examination
1195 if (RD->field_empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001196 DiagEngine->Report(
1197 clang::FullSourceLoc(RD->getLocation(), *SM),
1198 DiagEngine->getCustomDiagID(
1199 clang::DiagnosticsEngine::Error,
1200 "invalid matrix struct: must have 1 field for saving values: '%0'"))
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001201 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001202 return NULL;
1203 }
1204
1205 clang::RecordDecl::field_iterator FIT = RD->field_begin();
1206 const clang::FieldDecl *FD = *FIT;
1207 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1208 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001209 DiagEngine->Report(
1210 clang::FullSourceLoc(RD->getLocation(), *SM),
1211 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1212 "invalid matrix struct: first field should"
1213 " be an array with constant size: '%0'"))
1214 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001215 return NULL;
1216 }
1217 const clang::ConstantArrayType *CAT =
1218 static_cast<const clang::ConstantArrayType *>(FT);
Zonr Chang2e1dba62010-10-05 22:20:11 +08001219 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Zonr Chang92b344a2010-10-05 20:39:03 +08001220 if ((ElementType == NULL) ||
1221 (ElementType->getTypeClass() != clang::Type::Builtin) ||
Logan Chien9207a2e2011-10-21 15:39:28 +08001222 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() !=
1223 clang::BuiltinType::Float)) {
1224 DiagEngine->Report(
1225 clang::FullSourceLoc(RD->getLocation(), *SM),
1226 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1227 "invalid matrix struct: first field "
1228 "should be a float array: '%0'"))
1229 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001230 return NULL;
1231 }
1232
1233 if (CAT->getSize() != Dim * Dim) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001234 DiagEngine->Report(
1235 clang::FullSourceLoc(RD->getLocation(), *SM),
1236 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1237 "invalid matrix struct: first field "
1238 "should be an array with size %0: '%1'"))
1239 << (Dim * Dim) << (RD->getName());
Zonr Chang92b344a2010-10-05 20:39:03 +08001240 return NULL;
1241 }
1242
1243 FIT++;
1244 if (FIT != RD->field_end()) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001245 DiagEngine->Report(
1246 clang::FullSourceLoc(RD->getLocation(), *SM),
1247 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1248 "invalid matrix struct: must have "
1249 "exactly 1 field: '%0'"))
1250 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001251 return NULL;
1252 }
1253 }
1254
1255 return new RSExportMatrixType(Context, TypeName, Dim);
1256}
1257
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001258llvm::Type *RSExportMatrixType::convertToLLVMType() const {
Zonr Chang92b344a2010-10-05 20:39:03 +08001259 // Construct LLVM type:
1260 // struct {
1261 // float X[mDim * mDim];
1262 // }
1263
1264 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
1265 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
1266 mDim * mDim);
Stephen Hinesa67e4452011-07-19 15:39:26 -07001267 return llvm::StructType::get(C, X, false);
Zonr Chang92b344a2010-10-05 20:39:03 +08001268}
1269
Zonr Changa7a828d2010-10-22 03:44:27 +08001270union RSType *RSExportMatrixType::convertToSpecType() const {
1271 llvm::OwningPtr<union RSType> ST(new union RSType);
1272 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
1273 switch (getDim()) {
1274 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
1275 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
1276 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
Stephen Hines6e6578a2011-02-07 18:05:48 -08001277 default: slangAssert(false && "Matrix type with unsupported dimension.");
Zonr Changa7a828d2010-10-22 03:44:27 +08001278 }
1279 return ST.take();
1280}
1281
Zonr Chang641558f2010-10-12 21:07:06 +08001282bool RSExportMatrixType::equals(const RSExportable *E) const {
1283 CHECK_PARENT_EQUALITY(RSExportType, E);
1284 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
1285}
1286
Zonr Chang2e1dba62010-10-05 22:20:11 +08001287/************************* RSExportConstantArrayType *************************/
1288RSExportConstantArrayType
1289*RSExportConstantArrayType::Create(RSContext *Context,
1290 const clang::ConstantArrayType *CAT) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001291 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
Zonr Chang2e1dba62010-10-05 22:20:11 +08001292
Stephen Hines6e6578a2011-02-07 18:05:48 -08001293 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large");
Zonr Chang2e1dba62010-10-05 22:20:11 +08001294
1295 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
Stephen Hines6e6578a2011-02-07 18:05:48 -08001296 slangAssert((Size > 0) && "Constant array should have size greater than 0");
Zonr Chang2e1dba62010-10-05 22:20:11 +08001297
1298 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1299 RSExportType *ElementET = RSExportType::Create(Context, ElementType);
1300
1301 if (ElementET == NULL) {
Zonr Chang2e1dba62010-10-05 22:20:11 +08001302 return NULL;
1303 }
1304
1305 return new RSExportConstantArrayType(Context,
1306 ElementET,
1307 Size);
1308}
1309
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001310llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
Zonr Chang2e1dba62010-10-05 22:20:11 +08001311 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
1312}
1313
Zonr Changa7a828d2010-10-22 03:44:27 +08001314union RSType *RSExportConstantArrayType::convertToSpecType() const {
1315 llvm::OwningPtr<union RSType> ST(new union RSType);
1316
1317 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
1318 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
1319 ST, getElementType()->getSpecType());
1320 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
1321
1322 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
1323 return ST.take();
1324 else
1325 return NULL;
1326}
1327
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001328bool RSExportConstantArrayType::keep() {
1329 if (!RSExportType::keep())
1330 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001331 const_cast<RSExportType*>(mElementType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001332 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001333}
1334
1335bool RSExportConstantArrayType::equals(const RSExportable *E) const {
1336 CHECK_PARENT_EQUALITY(RSExportType, E);
Stephen Hinesa7b75182010-12-07 15:49:49 -08001337 const RSExportConstantArrayType *RHS =
1338 static_cast<const RSExportConstantArrayType*>(E);
1339 return ((getSize() == RHS->getSize()) &&
1340 (getElementType()->equals(RHS->getElementType())));
Zonr Chang641558f2010-10-12 21:07:06 +08001341}
1342
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001343/**************************** RSExportRecordType ****************************/
1344RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
1345 const clang::RecordType *RT,
1346 const llvm::StringRef &TypeName,
1347 bool mIsArtificial) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001348 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001349
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001350 const clang::RecordDecl *RD = RT->getDecl();
Stephen Hines6e6578a2011-02-07 18:05:48 -08001351 slangAssert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001352
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001353 RD = RD->getDefinition();
1354 if (RD == NULL) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001355 slangAssert(false && "struct is not defined in this module");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001356 return NULL;
1357 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001358
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001359 // Struct layout construct by clang. We rely on this for obtaining the
1360 // alloc size of a struct and offset of every field in that struct.
1361 const clang::ASTRecordLayout *RL =
Stephen Hines9e5b5032010-11-03 13:19:14 -07001362 &Context->getASTContext().getASTRecordLayout(RD);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001363 slangAssert((RL != NULL) &&
1364 "Failed to retrieve the struct layout from Clang.");
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001365
1366 RSExportRecordType *ERT =
1367 new RSExportRecordType(Context,
1368 TypeName,
1369 RD->hasAttr<clang::PackedAttr>(),
1370 mIsArtificial,
Shih-wei Liao68318a12011-03-11 05:56:15 -08001371 RL->getSize().getQuantity());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001372 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001373
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001374 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1375 FE = RD->field_end();
1376 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -07001377 FI++, Index++) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001378 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001379
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001380 // FIXME: All fields should be primitive type
Stephen Hines6e6578a2011-02-07 18:05:48 -08001381 slangAssert((*FI)->getKind() == clang::Decl::Field);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001382 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001383
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001384 if (FD->isBitField()) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001385 return NULL;
1386 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001387
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001388 // Type
zonr6315f762010-10-05 15:35:14 +08001389 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001390
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001391 if (ET != NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001392 ERT->mFields.push_back(
1393 new Field(ET, FD->getName(), ERT,
1394 static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001395 } else {
Logan Chien9207a2e2011-10-21 15:39:28 +08001396 DiagEngine->Report(
1397 clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()),
1398 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1399 "field type cannot be exported: '%0.%1'"))
1400 << RD->getName() << FD->getName();
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001401 return NULL;
1402 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001403 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001404
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001405 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001406}
1407
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001408llvm::Type *RSExportRecordType::convertToLLVMType() const {
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001409 // Create an opaque type since struct may reference itself recursively.
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001410
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001411 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to?
1412 std::vector<llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001413
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001414 for (const_field_iterator FI = fields_begin(), FE = fields_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001415 FI != FE;
1416 FI++) {
1417 const Field *F = *FI;
1418 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -07001419
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001420 FieldTypes.push_back(FET->getLLVMType());
1421 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001422
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001423 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
1424 FieldTypes,
1425 mIsPacked);
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001426 if (ST != NULL) {
1427 return ST;
1428 } else {
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001429 return NULL;
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001430 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001431}
Zonr Chang641558f2010-10-12 21:07:06 +08001432
Zonr Changa7a828d2010-10-22 03:44:27 +08001433union RSType *RSExportRecordType::convertToSpecType() const {
1434 unsigned NumFields = getFields().size();
1435 unsigned AllocSize = sizeof(union RSType) +
1436 sizeof(struct RSRecordField) * NumFields;
1437 llvm::OwningPtr<union RSType> ST(
Stephen Hinese639eb52010-11-08 19:27:20 -08001438 reinterpret_cast<union RSType*>(operator new(AllocSize)));
Zonr Changa7a828d2010-10-22 03:44:27 +08001439
1440 ::memset(ST.get(), 0, AllocSize);
1441
1442 RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1443 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1444 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1445
1446 setSpecTypeTemporarily(ST.get());
1447
1448 unsigned FieldIdx = 0;
1449 for (const_field_iterator FI = fields_begin(), FE = fields_end();
1450 FI != FE;
1451 FI++, FieldIdx++) {
1452 const Field *F = *FI;
1453
1454 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1455 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
Zonr Changa7a828d2010-10-22 03:44:27 +08001456 }
1457
Stephen Hinese639eb52010-11-08 19:27:20 -08001458 // TODO(slang): Check whether all fields were created normally.
Zonr Changa7a828d2010-10-22 03:44:27 +08001459
1460 return ST.take();
1461}
1462
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001463bool RSExportRecordType::keep() {
1464 if (!RSExportType::keep())
1465 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001466 for (std::list<const Field*>::iterator I = mFields.begin(),
1467 E = mFields.end();
1468 I != E;
1469 I++) {
1470 const_cast<RSExportType*>((*I)->getType())->keep();
1471 }
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001472 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001473}
1474
1475bool RSExportRecordType::equals(const RSExportable *E) const {
1476 CHECK_PARENT_EQUALITY(RSExportType, E);
1477
1478 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1479
1480 if (ERT->getFields().size() != getFields().size())
1481 return false;
1482
1483 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1484
1485 for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1486 if (!(*AI)->getType()->equals((*BI)->getType()))
1487 return false;
1488 AI++;
1489 BI++;
1490 }
1491
1492 return true;
1493}
Stephen Hinese639eb52010-11-08 19:27:20 -08001494
Jason Sams1b6a0882012-03-12 15:07:58 -07001495void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
1496 memset(rtd, 0, sizeof(*rtd));
1497 rtd->vecSize = 1;
1498
1499 switch(getClass()) {
1500 case RSExportType::ExportClassPrimitive: {
1501 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
1502 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
1503 return;
1504 }
1505 case RSExportType::ExportClassPointer: {
1506 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
1507 const RSExportType *PointeeType = EPT->getPointeeType();
1508 PointeeType->convertToRTD(rtd);
1509 rtd->isPointer = true;
1510 return;
1511 }
1512 case RSExportType::ExportClassVector: {
1513 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
1514 rtd->type = EVT->getRSReflectionType(EVT);
1515 rtd->vecSize = EVT->getNumElement();
1516 return;
1517 }
1518 case RSExportType::ExportClassMatrix: {
1519 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
1520 unsigned Dim = EMT->getDim();
1521 slangAssert((Dim >= 2) && (Dim <= 4));
1522 rtd->type = &gReflectionTypes[15 + Dim-2];
1523 return;
1524 }
1525 case RSExportType::ExportClassConstantArray: {
1526 const RSExportConstantArrayType* CAT =
1527 static_cast<const RSExportConstantArrayType*>(this);
1528 CAT->getElementType()->convertToRTD(rtd);
1529 rtd->arraySize = CAT->getSize();
1530 return;
1531 }
1532 case RSExportType::ExportClassRecord: {
1533 slangAssert(!"RSExportType::ExportClassRecord not implemented");
1534 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
1535 }
1536 default: {
1537 slangAssert(false && "Unknown class of type");
1538 }
1539 }
1540}
1541
1542
Stephen Hinese639eb52010-11-08 19:27:20 -08001543} // namespace slang