blob: 771d82198e4408a4cfb3ee9370b4e546294dcec9 [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 Hines23c43582013-01-09 20:02:04 -080023#include "clang/AST/Attr.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080024#include "clang/AST/RecordLayout.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070025
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070026#include "llvm/ADT/StringExtras.h"
Stephen Hines23c43582013-01-09 20:02:04 -080027#include "llvm/IR/DataLayout.h"
28#include "llvm/IR/DerivedTypes.h"
29#include "llvm/IR/Type.h"
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070030
Stephen Hines6e6578a2011-02-07 18:05:48 -080031#include "slang_assert.h"
zonr6315f762010-10-05 15:35:14 +080032#include "slang_rs_context.h"
33#include "slang_rs_export_element.h"
Zonr Changa7a828d2010-10-22 03:44:27 +080034#include "slang_rs_type_spec.h"
Stephen Hinesd5a84f62012-04-04 17:44:38 -070035#include "slang_version.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070036
Zonr Chang641558f2010-10-12 21:07:06 +080037#define CHECK_PARENT_EQUALITY(ParentClass, E) \
38 if (!ParentClass::equals(E)) \
39 return false;
40
Stephen Hinese639eb52010-11-08 19:27:20 -080041namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070042
Stephen Hinese5e64432010-12-02 18:48:20 -080043namespace {
44
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080045static RSReflectionType gReflectionTypes[] = {
46 {"FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false},
47 {"FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false},
48 {"FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false},
49 {"SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false},
50 {"SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false},
51 {"SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false},
52 {"SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false},
Stephen Hines47aca4e2012-03-08 20:07:28 -080053 {"UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true},
54 {"UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true},
55 {"UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true},
56 {"UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false},
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080057
Stephen Hines47aca4e2012-03-08 20:07:28 -080058 {"BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false},
Stephen Hinesfdd1ba12012-03-08 17:26:32 -080059
60 {"UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false},
61 {"UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false},
62 {"UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false},
63
64 {"MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false},
65 {"MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false},
66 {"MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false},
67
68 {"RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false},
69 {"RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false},
70 {"RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false},
71 {"RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false},
72 {"RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false},
73 {"RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false},
74 {"RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false},
75 {"RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false},
76 {"RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false},
77 {"RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false},
78 {"RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false},
79 {"RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false}
80};
81
Stephen Hines24e79f62010-12-13 12:55:57 -080082static const clang::Type *TypeExportableHelper(
83 const clang::Type *T,
84 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Logan Chien9207a2e2011-10-21 15:39:28 +080085 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -080086 const clang::VarDecl *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -070087 const clang::RecordDecl *TopLevelRecord);
Stephen Hines24e79f62010-12-13 12:55:57 -080088
Logan Chien9207a2e2011-10-21 15:39:28 +080089static void ReportTypeError(clang::DiagnosticsEngine *DiagEngine,
Stephen Hines11274a72012-09-26 19:14:20 -070090 const clang::NamedDecl *ND,
Stephen Hines24e79f62010-12-13 12:55:57 -080091 const clang::RecordDecl *TopLevelRecord,
Stephen Hinesd5a84f62012-04-04 17:44:38 -070092 const char *Message,
93 unsigned int TargetAPI = 0) {
Logan Chien9207a2e2011-10-21 15:39:28 +080094 if (!DiagEngine) {
Stephen Hines24e79f62010-12-13 12:55:57 -080095 return;
96 }
97
Logan Chien9207a2e2011-10-21 15:39:28 +080098 const clang::SourceManager &SM = DiagEngine->getSourceManager();
Stephen Hines78e69cb2011-04-22 15:03:19 -070099
Stephen Hines24e79f62010-12-13 12:55:57 -0800100 // Attempt to use the type declaration first (if we have one).
101 // Fall back to the variable definition, if we are looking at something
102 // like an array declaration that can't be exported.
103 if (TopLevelRecord) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800104 DiagEngine->Report(
105 clang::FullSourceLoc(TopLevelRecord->getLocation(), SM),
106 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700107 << TopLevelRecord->getName() << TargetAPI;
Stephen Hines11274a72012-09-26 19:14:20 -0700108 } else if (ND) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800109 DiagEngine->Report(
Stephen Hines11274a72012-09-26 19:14:20 -0700110 clang::FullSourceLoc(ND->getLocation(), SM),
Logan Chien9207a2e2011-10-21 15:39:28 +0800111 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
Stephen Hines11274a72012-09-26 19:14:20 -0700112 << ND->getName() << TargetAPI;
Stephen Hines24e79f62010-12-13 12:55:57 -0800113 } else {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800114 slangAssert(false && "Variables should be validated before exporting");
Stephen Hines24e79f62010-12-13 12:55:57 -0800115 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800116}
117
118static const clang::Type *ConstantArrayTypeExportableHelper(
119 const clang::ConstantArrayType *CAT,
120 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Logan Chien9207a2e2011-10-21 15:39:28 +0800121 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines24e79f62010-12-13 12:55:57 -0800122 const clang::VarDecl *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700123 const clang::RecordDecl *TopLevelRecord) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800124 // Check element type
125 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
126 if (ElementType->isArrayType()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800127 ReportTypeError(DiagEngine, VD, TopLevelRecord,
128 "multidimensional arrays cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800129 return NULL;
130 } else if (ElementType->isExtVectorType()) {
131 const clang::ExtVectorType *EVT =
132 static_cast<const clang::ExtVectorType*>(ElementType);
133 unsigned numElements = EVT->getNumElements();
134
135 const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
136 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800137 ReportTypeError(DiagEngine, VD, TopLevelRecord,
138 "vectors of non-primitive types cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800139 return NULL;
140 }
141
142 if (numElements == 3 && CAT->getSize() != 1) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800143 ReportTypeError(DiagEngine, VD, TopLevelRecord,
144 "arrays of width 3 vector types cannot be exported: '%0'");
Stephen Hines24e79f62010-12-13 12:55:57 -0800145 return NULL;
146 }
147 }
148
Logan Chien9207a2e2011-10-21 15:39:28 +0800149 if (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700150 TopLevelRecord) == NULL) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800151 return NULL;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700152 } else {
Stephen Hines24e79f62010-12-13 12:55:57 -0800153 return CAT;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700154 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800155}
156
157static const clang::Type *TypeExportableHelper(
Stephen Hinese67239d2012-02-24 15:08:36 -0800158 clang::Type const *T,
159 llvm::SmallPtrSet<clang::Type const *, 8> &SPS,
160 clang::DiagnosticsEngine *DiagEngine,
161 clang::VarDecl const *VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700162 clang::RecordDecl const *TopLevelRecord) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800163 // Normalize first
164 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
165 return NULL;
166
167 if (SPS.count(T))
168 return T;
169
170 switch (T->getTypeClass()) {
171 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800172 const clang::BuiltinType *BT =
173 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800174
175 switch (BT->getKind()) {
176#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
177 case builtin_type:
178#include "RSClangBuiltinEnums.inc"
179 return T;
180 default: {
181 return NULL;
182 }
183 }
184 }
185 case clang::Type::Record: {
186 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700187 RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800188 return T; // RS object type, no further checks are needed
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700189 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800190
191 // Check internal struct
Stephen Hinescd440ee2010-12-06 14:57:04 -0800192 if (T->isUnionType()) {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700193 ReportTypeError(DiagEngine, VD, T->getAsUnionType()->getDecl(),
Logan Chien9207a2e2011-10-21 15:39:28 +0800194 "unions cannot be exported: '%0'");
Stephen Hinescd440ee2010-12-06 14:57:04 -0800195 return NULL;
196 } else if (!T->isStructureType()) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800197 slangAssert(false && "Unknown type cannot be exported");
Stephen Hinescd440ee2010-12-06 14:57:04 -0800198 return NULL;
199 }
200
Stephen Hines24e79f62010-12-13 12:55:57 -0800201 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800202 if (RD != NULL) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800203 RD = RD->getDefinition();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800204 if (RD == NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800205 ReportTypeError(DiagEngine, NULL, T->getAsStructureType()->getDecl(),
206 "struct is not defined in this module");
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800207 return NULL;
208 }
209 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800210
211 if (!TopLevelRecord) {
212 TopLevelRecord = RD;
213 }
214 if (RD->getName().empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800215 ReportTypeError(DiagEngine, NULL, RD,
216 "anonymous structures cannot be exported");
Stephen Hinese5e64432010-12-02 18:48:20 -0800217 return NULL;
218 }
219
220 // Fast check
221 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
222 return NULL;
223
224 // Insert myself into checking set
225 SPS.insert(T);
226
227 // Check all element
228 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
229 FE = RD->field_end();
230 FI != FE;
231 FI++) {
232 const clang::FieldDecl *FD = *FI;
233 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
234 FT = GET_CANONICAL_TYPE(FT);
235
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700236 if (!TypeExportableHelper(FT, SPS, DiagEngine, VD, TopLevelRecord)) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800237 return NULL;
238 }
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800239
240 // We don't support bit fields yet
241 //
242 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32
243 if (FD->isBitField()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800244 if (DiagEngine) {
245 DiagEngine->Report(
246 clang::FullSourceLoc(FD->getLocation(),
247 DiagEngine->getSourceManager()),
248 DiagEngine->getCustomDiagID(
249 clang::DiagnosticsEngine::Error,
250 "bit fields are not able to be exported: '%0.%1'"))
251 << RD->getName()
252 << FD->getName();
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800253 }
254 return NULL;
255 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800256 }
257
258 return T;
259 }
260 case clang::Type::Pointer: {
261 if (TopLevelRecord) {
Stephen Hinesaa82e742012-04-11 12:38:17 -0700262 ReportTypeError(DiagEngine, VD, TopLevelRecord,
263 "structures containing pointers cannot be exported: '%0'");
Stephen Hinese5e64432010-12-02 18:48:20 -0800264 return NULL;
265 }
Stephen Hines24e79f62010-12-13 12:55:57 -0800266
Loganbe274822011-02-16 22:02:54 +0800267 const clang::PointerType *PT =
268 UNSAFE_CAST_TYPE(const clang::PointerType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800269 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
270
Stephen Hinesaa82e742012-04-11 12:38:17 -0700271 if (PointeeType->getTypeClass() == clang::Type::Pointer) {
272 ReportTypeError(DiagEngine, VD, TopLevelRecord,
273 "multiple levels of pointers cannot be exported: '%0'");
274 return NULL;
275 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800276 // We don't support pointer with array-type pointee or unsupported pointee
277 // type
278 if (PointeeType->isArrayType() ||
Logan Chien9207a2e2011-10-21 15:39:28 +0800279 (TypeExportableHelper(PointeeType, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700280 TopLevelRecord) == NULL))
Stephen Hinese5e64432010-12-02 18:48:20 -0800281 return NULL;
282 else
283 return T;
284 }
285 case clang::Type::ExtVector: {
286 const clang::ExtVectorType *EVT =
Loganbe274822011-02-16 22:02:54 +0800287 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800288 // Only vector with size 2, 3 and 4 are supported.
289 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
290 return NULL;
291
292 // Check base element type
293 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
294
295 if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
Logan Chien9207a2e2011-10-21 15:39:28 +0800296 (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700297 TopLevelRecord) == NULL))
Stephen Hinese5e64432010-12-02 18:48:20 -0800298 return NULL;
299 else
300 return T;
301 }
302 case clang::Type::ConstantArray: {
303 const clang::ConstantArrayType *CAT =
Loganbe274822011-02-16 22:02:54 +0800304 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800305
Logan Chien9207a2e2011-10-21 15:39:28 +0800306 return ConstantArrayTypeExportableHelper(CAT, SPS, DiagEngine, VD,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700307 TopLevelRecord);
Stephen Hinese5e64432010-12-02 18:48:20 -0800308 }
309 default: {
310 return NULL;
311 }
312 }
313}
314
315// Return the type that can be used to create RSExportType, will always return
316// the canonical type
Logan Chien9207a2e2011-10-21 15:39:28 +0800317// If the Type T is not exportable, this function returns NULL. DiagEngine is
Stephen Hines78e69cb2011-04-22 15:03:19 -0700318// used to generate proper Clang diagnostic messages when a
Stephen Hinese5e64432010-12-02 18:48:20 -0800319// non-exportable type is detected. TopLevelRecord is used to capture the
320// highest struct (in the case of a nested hierarchy) for detecting other
321// types that cannot be exported (mostly pointers within a struct).
322static const clang::Type *TypeExportable(const clang::Type *T,
Logan Chien9207a2e2011-10-21 15:39:28 +0800323 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700324 const clang::VarDecl *VD) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700325 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
326 llvm::SmallPtrSet<const clang::Type*, 8>();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700327
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700328 return TypeExportableHelper(T, SPS, DiagEngine, VD, NULL);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700329}
330
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700331static bool ValidateRSObjectInVarDecl(clang::VarDecl *VD,
332 bool InCompositeType,
333 unsigned int TargetAPI) {
334 if (TargetAPI < SLANG_JB_TARGET_API) {
335 // Only if we are already in a composite type (like an array or structure).
336 if (InCompositeType) {
337 // Only if we are actually exported (i.e. non-static).
Stephen Hines44f10062013-06-13 00:33:23 -0700338 if (VD->hasLinkage() &&
339 (VD->getFormalLinkage() == clang::ExternalLinkage)) {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700340 // Only if we are not a pointer to an object.
341 const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr());
342 if (T->getTypeClass() != clang::Type::Pointer) {
343 clang::ASTContext &C = VD->getASTContext();
344 ReportTypeError(&C.getDiagnostics(), VD, NULL,
345 "arrays/structures containing RS object types "
346 "cannot be exported in target API < %1: '%0'",
347 SLANG_JB_TARGET_API);
348 return false;
349 }
350 }
351 }
352 }
353
354 return true;
355}
356
Stephen Hines11274a72012-09-26 19:14:20 -0700357// Helper function for ValidateType(). We do a recursive descent on the
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700358// type hierarchy to ensure that we can properly export/handle the
359// declaration.
360// \return true if the variable declaration is valid,
361// false if it is invalid (along with proper diagnostics).
362//
Stephen Hines11274a72012-09-26 19:14:20 -0700363// C - ASTContext (for diagnostics + builtin types).
364// T - sub-type that we are validating.
365// ND - (optional) top-level named declaration that we are validating.
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700366// 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 Hines11274a72012-09-26 19:14:20 -0700370// IsFilterscript - whether or not we are compiling for Filterscript
371static bool ValidateTypeHelper(
372 clang::ASTContext &C,
Stephen Hines78e69cb2011-04-22 15:03:19 -0700373 const clang::Type *&T,
Stephen Hines11274a72012-09-26 19:14:20 -0700374 clang::NamedDecl *ND,
375 clang::SourceLocation Loc,
Stephen Hines78e69cb2011-04-22 15:03:19 -0700376 llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700377 bool InCompositeType,
378 clang::RecordDecl *UnionDecl,
Stephen Hines11274a72012-09-26 19:14:20 -0700379 unsigned int TargetAPI,
380 bool IsFilterscript) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700381 if ((T = GET_CANONICAL_TYPE(T)) == NULL)
382 return true;
383
384 if (SPS.count(T))
385 return true;
386
387 switch (T->getTypeClass()) {
388 case clang::Type::Record: {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700389 if (RSExportPrimitiveType::IsRSObjectType(T)) {
Stephen Hines11274a72012-09-26 19:14:20 -0700390 clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL);
391 if (VD && !ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) {
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700392 return false;
393 }
394 }
395
Stephen Hines78e69cb2011-04-22 15:03:19 -0700396 if (RSExportPrimitiveType::GetRSSpecificType(T) !=
397 RSExportPrimitiveType::DataTypeUnknown) {
398 if (!UnionDecl) {
399 return true;
400 } else if (RSExportPrimitiveType::IsRSObjectType(T)) {
Stephen Hines11274a72012-09-26 19:14:20 -0700401 ReportTypeError(&C.getDiagnostics(), NULL, UnionDecl,
Stephen Hines78e69cb2011-04-22 15:03:19 -0700402 "unions containing RS object types are not allowed");
403 return false;
404 }
405 }
406
407 clang::RecordDecl *RD = NULL;
408
409 // Check internal struct
410 if (T->isUnionType()) {
411 RD = T->getAsUnionType()->getDecl();
412 UnionDecl = RD;
413 } else if (T->isStructureType()) {
414 RD = T->getAsStructureType()->getDecl();
415 } else {
416 slangAssert(false && "Unknown type cannot be exported");
417 return false;
418 }
419
420 if (RD != NULL) {
421 RD = RD->getDefinition();
422 if (RD == NULL) {
423 // FIXME
424 return true;
425 }
426 }
427
428 // Fast check
429 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
430 return false;
431
432 // Insert myself into checking set
433 SPS.insert(T);
434
435 // Check all elements
436 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
437 FE = RD->field_end();
438 FI != FE;
439 FI++) {
440 const clang::FieldDecl *FD = *FI;
441 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
442 FT = GET_CANONICAL_TYPE(FT);
443
Stephen Hines11274a72012-09-26 19:14:20 -0700444 if (!ValidateTypeHelper(C, FT, ND, Loc, SPS, true, UnionDecl,
445 TargetAPI, IsFilterscript)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700446 return false;
447 }
448 }
449
450 return true;
451 }
452
453 case clang::Type::Builtin: {
Stephen Hines11274a72012-09-26 19:14:20 -0700454 if (IsFilterscript) {
455 clang::QualType QT = T->getCanonicalTypeInternal();
456 if (QT == C.DoubleTy ||
457 QT == C.LongDoubleTy ||
458 QT == C.LongTy ||
459 QT == C.LongLongTy) {
460 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
461 if (ND) {
462 DiagEngine.Report(
463 clang::FullSourceLoc(Loc, C.getSourceManager()),
464 DiagEngine.getCustomDiagID(
465 clang::DiagnosticsEngine::Error,
466 "Builtin types > 32 bits in size are forbidden in "
467 "Filterscript: '%0'")) << ND->getName();
468 } else {
469 DiagEngine.Report(
470 clang::FullSourceLoc(Loc, C.getSourceManager()),
471 DiagEngine.getCustomDiagID(
472 clang::DiagnosticsEngine::Error,
473 "Builtin types > 32 bits in size are forbidden in "
474 "Filterscript"));
475 }
476 return false;
477 }
478 }
Stephen Hines78e69cb2011-04-22 15:03:19 -0700479 break;
480 }
481
482 case clang::Type::Pointer: {
Stephen Hines11274a72012-09-26 19:14:20 -0700483 if (IsFilterscript) {
484 if (ND) {
485 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
486 DiagEngine.Report(
487 clang::FullSourceLoc(Loc, C.getSourceManager()),
488 DiagEngine.getCustomDiagID(
489 clang::DiagnosticsEngine::Error,
490 "Pointers are forbidden in Filterscript: '%0'")) << ND->getName();
491 return false;
492 } else {
493 // TODO(srhines): Find a better way to handle expressions (i.e. no
494 // NamedDecl) involving pointers in FS that should be allowed.
495 // An example would be calls to library functions like
496 // rsMatrixMultiply() that take rs_matrixNxN * types.
497 }
498 }
499
Stephen Hines78e69cb2011-04-22 15:03:19 -0700500 const clang::PointerType *PT =
501 UNSAFE_CAST_TYPE(const clang::PointerType, T);
502 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
503
Stephen Hines11274a72012-09-26 19:14:20 -0700504 return ValidateTypeHelper(C, PointeeType, ND, Loc, SPS, InCompositeType,
505 UnionDecl, TargetAPI, IsFilterscript);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700506 }
507
508 case clang::Type::ExtVector: {
509 const clang::ExtVectorType *EVT =
510 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
511 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Stephen Hinesb13b85e2012-08-31 19:27:48 -0700512 if (TargetAPI < SLANG_ICS_TARGET_API &&
513 InCompositeType &&
Stephen Hinesfdae63e2012-11-28 14:42:44 -0800514 EVT->getNumElements() == 3 &&
515 ND &&
Stephen Hines44f10062013-06-13 00:33:23 -0700516 ND->getFormalLinkage() == clang::ExternalLinkage) {
Stephen Hines11274a72012-09-26 19:14:20 -0700517 ReportTypeError(&C.getDiagnostics(), ND, NULL,
Stephen Hinesb13b85e2012-08-31 19:27:48 -0700518 "structs containing vectors of dimension 3 cannot "
519 "be exported at this API level: '%0'");
520 return false;
521 }
Stephen Hines11274a72012-09-26 19:14:20 -0700522 return ValidateTypeHelper(C, ElementType, ND, Loc, SPS, true, UnionDecl,
523 TargetAPI, IsFilterscript);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700524 }
525
526 case clang::Type::ConstantArray: {
527 const clang::ConstantArrayType *CAT =
528 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
529 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Stephen Hines11274a72012-09-26 19:14:20 -0700530 return ValidateTypeHelper(C, ElementType, ND, Loc, SPS, true, UnionDecl,
531 TargetAPI, IsFilterscript);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700532 }
533
534 default: {
535 break;
536 }
537 }
538
539 return true;
Stephen Hinese5e64432010-12-02 18:48:20 -0800540}
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700541
Stephen Hinese5e64432010-12-02 18:48:20 -0800542} // namespace
543
544/****************************** RSExportType ******************************/
545bool RSExportType::NormalizeType(const clang::Type *&T,
546 llvm::StringRef &TypeName,
Logan Chien9207a2e2011-10-21 15:39:28 +0800547 clang::DiagnosticsEngine *DiagEngine,
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700548 const clang::VarDecl *VD) {
549 if ((T = TypeExportable(T, DiagEngine, VD)) == NULL) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800550 return false;
551 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700552 // Get type name
553 TypeName = RSExportType::GetTypeName(T);
Stephen Hinese5e64432010-12-02 18:48:20 -0800554 if (TypeName.empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800555 if (DiagEngine) {
Stephen Hines24e79f62010-12-13 12:55:57 -0800556 if (VD) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800557 DiagEngine->Report(
558 clang::FullSourceLoc(VD->getLocation(),
559 DiagEngine->getSourceManager()),
560 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
561 "anonymous types cannot be exported"));
Stephen Hines24e79f62010-12-13 12:55:57 -0800562 } else {
Logan Chien9207a2e2011-10-21 15:39:28 +0800563 DiagEngine->Report(
564 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
565 "anonymous types cannot be exported"));
Stephen Hines24e79f62010-12-13 12:55:57 -0800566 }
Stephen Hinese5e64432010-12-02 18:48:20 -0800567 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700568 return false;
Stephen Hinese5e64432010-12-02 18:48:20 -0800569 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700570
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700571 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700572}
573
Stephen Hines11274a72012-09-26 19:14:20 -0700574bool RSExportType::ValidateType(clang::ASTContext &C, clang::QualType QT,
575 clang::NamedDecl *ND, clang::SourceLocation Loc, unsigned int TargetAPI,
576 bool IsFilterscript) {
577 const clang::Type *T = QT.getTypePtr();
Stephen Hines78e69cb2011-04-22 15:03:19 -0700578 llvm::SmallPtrSet<const clang::Type*, 8> SPS =
579 llvm::SmallPtrSet<const clang::Type*, 8>();
580
Stephen Hines11274a72012-09-26 19:14:20 -0700581 return ValidateTypeHelper(C, T, ND, Loc, SPS, false, NULL, TargetAPI,
582 IsFilterscript);
583 return true;
584}
585
586bool RSExportType::ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI,
587 bool IsFilterscript) {
588 return ValidateType(VD->getASTContext(), VD->getType(), VD,
589 VD->getLocation(), TargetAPI, IsFilterscript);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700590}
591
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700592const clang::Type
593*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800594 if (DD) {
595 clang::QualType T;
596 if (DD->getTypeSourceInfo())
597 T = DD->getTypeSourceInfo()->getType();
598 else
599 T = DD->getType();
600
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700601 if (T.isNull())
602 return NULL;
603 else
604 return T.getTypePtr();
605 }
606 return NULL;
607}
608
609llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
610 T = GET_CANONICAL_TYPE(T);
611 if (T == NULL)
612 return llvm::StringRef();
613
614 switch (T->getTypeClass()) {
615 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800616 const clang::BuiltinType *BT =
617 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700618
619 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800620#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
621 case builtin_type: \
622 return cname; \
623 break;
624#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800625 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800626 slangAssert(false && "Unknown data type of the builtin");
Zonr Changa65ec162010-10-17 01:53:05 +0800627 break;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700628 }
Zonr Changa65ec162010-10-17 01:53:05 +0800629 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700630 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700631 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700632 case clang::Type::Record: {
Stephen Hinescd440ee2010-12-06 14:57:04 -0800633 clang::RecordDecl *RD;
634 if (T->isStructureType()) {
635 RD = T->getAsStructureType()->getDecl();
Stephen Hinesdd6206b2010-12-09 19:39:22 -0800636 } else {
Stephen Hinescd440ee2010-12-06 14:57:04 -0800637 break;
638 }
639
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700640 llvm::StringRef Name = RD->getName();
641 if (Name.empty()) {
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700642 if (RD->getTypedefNameForAnonDecl() != NULL) {
643 Name = RD->getTypedefNameForAnonDecl()->getName();
644 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700645
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700646 if (Name.empty()) {
647 // Try to find a name from redeclaration (i.e. typedef)
648 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
649 RE = RD->redecls_end();
650 RI != RE;
651 RI++) {
652 slangAssert(*RI != NULL && "cannot be NULL object");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700653
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700654 Name = (*RI)->getName();
655 if (!Name.empty())
656 break;
657 }
658 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700659 }
660 return Name;
661 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700662 case clang::Type::Pointer: {
663 // "*" plus pointee name
zonr6315f762010-10-05 15:35:14 +0800664 const clang::Type *PT = GET_POINTEE_TYPE(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700665 llvm::StringRef PointeeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700666 if (NormalizeType(PT, PointeeName, NULL, NULL)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700667 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
668 Name[0] = '*';
669 memcpy(Name + 1, PointeeName.data(), PointeeName.size());
670 Name[PointeeName.size() + 1] = '\0';
671 return Name;
672 }
673 break;
674 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700675 case clang::Type::ExtVector: {
676 const clang::ExtVectorType *EVT =
Loganbe274822011-02-16 22:02:54 +0800677 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700678 return RSExportVectorType::GetTypeName(EVT);
679 break;
680 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800681 case clang::Type::ConstantArray : {
682 // Construct name for a constant array is too complicated.
683 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE;
684 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700685 default: {
686 break;
687 }
688 }
689
690 return llvm::StringRef();
691}
692
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700693
694RSExportType *RSExportType::Create(RSContext *Context,
695 const clang::Type *T,
696 const llvm::StringRef &TypeName) {
697 // Lookup the context to see whether the type was processed before.
698 // Newly created RSExportType will insert into context
699 // in RSExportType::RSExportType()
700 RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
701
702 if (ETI != Context->export_types_end())
703 return ETI->second;
704
705 RSExportType *ET = NULL;
706 switch (T->getTypeClass()) {
707 case clang::Type::Record: {
708 RSExportPrimitiveType::DataType dt =
Zonr Changb1771ef2010-10-22 18:03:46 +0800709 RSExportPrimitiveType::GetRSSpecificType(TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700710 switch (dt) {
Zonr Chang92b344a2010-10-05 20:39:03 +0800711 case RSExportPrimitiveType::DataTypeUnknown: {
712 // User-defined types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700713 ET = RSExportRecordType::Create(Context,
714 T->getAsStructureType(),
715 TypeName);
716 break;
717 }
Zonr Chang92b344a2010-10-05 20:39:03 +0800718 case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
719 // 2 x 2 Matrix type
720 ET = RSExportMatrixType::Create(Context,
721 T->getAsStructureType(),
722 TypeName,
723 2);
724 break;
725 }
726 case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
727 // 3 x 3 Matrix type
728 ET = RSExportMatrixType::Create(Context,
729 T->getAsStructureType(),
730 TypeName,
731 3);
732 break;
733 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700734 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800735 // 4 x 4 Matrix type
736 ET = RSExportMatrixType::Create(Context,
737 T->getAsStructureType(),
738 TypeName,
739 4);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700740 break;
741 }
742 default: {
Zonr Chang92b344a2010-10-05 20:39:03 +0800743 // Others are primitive types
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700744 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
745 break;
746 }
747 }
748 break;
749 }
750 case clang::Type::Builtin: {
751 ET = RSExportPrimitiveType::Create(Context, T, TypeName);
752 break;
753 }
754 case clang::Type::Pointer: {
755 ET = RSExportPointerType::Create(Context,
Stephen Hines5baf6322011-04-25 17:21:15 -0700756 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName);
Zonr Chang92b344a2010-10-05 20:39:03 +0800757 // FIXME: free the name (allocated in RSExportType::GetTypeName)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700758 delete [] TypeName.data();
759 break;
760 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700761 case clang::Type::ExtVector: {
762 ET = RSExportVectorType::Create(Context,
Stephen Hines5baf6322011-04-25 17:21:15 -0700763 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700764 break;
765 }
Zonr Chang2e1dba62010-10-05 22:20:11 +0800766 case clang::Type::ConstantArray: {
767 ET = RSExportConstantArrayType::Create(
768 Context,
Loganbe274822011-02-16 22:02:54 +0800769 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T));
Zonr Chang2e1dba62010-10-05 22:20:11 +0800770 break;
771 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700772 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800773 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
774 DiagEngine->Report(
775 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
776 "unknown type cannot be exported: '%0'"))
777 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700778 break;
779 }
780 }
781
782 return ET;
783}
784
zonr6315f762010-10-05 15:35:14 +0800785RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700786 llvm::StringRef TypeName;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700787 if (NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700788 return Create(Context, T, TypeName);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700789 } else {
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700790 return NULL;
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700791 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700792}
793
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700794RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
795 const clang::VarDecl *VD) {
796 return RSExportType::Create(Context, GetTypeOfDecl(VD));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700797}
798
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700799size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
Stephen Hines23c43582013-01-09 20:02:04 -0800800 return ET->getRSContext()->getDataLayout()->getTypeStoreSize(
zonr6315f762010-10-05 15:35:14 +0800801 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700802}
803
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700804size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
805 if (ET->getClass() == RSExportType::ExportClassRecord)
806 return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
807 else
Stephen Hines23c43582013-01-09 20:02:04 -0800808 return ET->getRSContext()->getDataLayout()->getTypeAllocSize(
zonr6315f762010-10-05 15:35:14 +0800809 ET->getLLVMType());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700810}
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -0700811
Zonr Chang6b6320a2010-10-05 22:42:01 +0800812RSExportType::RSExportType(RSContext *Context,
813 ExportClass Class,
814 const llvm::StringRef &Name)
Zonr Changa41ce1d2010-10-06 02:23:12 +0800815 : RSExportable(Context, RSExportable::EX_TYPE),
Zonr Chang6b6320a2010-10-05 22:42:01 +0800816 mClass(Class),
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800817 // Make a copy on Name since memory stored @Name is either allocated in
818 // ASTContext or allocated in GetTypeName which will be destroyed later.
zonr6315f762010-10-05 15:35:14 +0800819 mName(Name.data(), Name.size()),
Zonr Changa7a828d2010-10-22 03:44:27 +0800820 mLLVMType(NULL),
821 mSpecType(NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800822 // Don't cache the type whose name start with '<'. Those type failed to
823 // get their name since constructing their name in GetTypeName() requiring
824 // complicated work.
825 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
826 // TODO(zonr): Need to check whether the insertion is successful or not.
827 Context->insertExportType(llvm::StringRef(Name), this);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700828 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700829}
830
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800831bool RSExportType::keep() {
832 if (!RSExportable::keep())
833 return false;
Zonr Chang641558f2010-10-12 21:07:06 +0800834 // Invalidate converted LLVM type.
835 mLLVMType = NULL;
Zonr Chang3cd3dd32010-10-22 02:11:35 +0800836 return true;
Zonr Chang641558f2010-10-12 21:07:06 +0800837}
838
839bool RSExportType::equals(const RSExportable *E) const {
840 CHECK_PARENT_EQUALITY(RSExportable, E);
841 return (static_cast<const RSExportType*>(E)->getClass() == getClass());
842}
843
Zonr Changa7a828d2010-10-22 03:44:27 +0800844RSExportType::~RSExportType() {
845 delete mSpecType;
846}
847
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700848/************************** RSExportPrimitiveType **************************/
Zonr Changb1771ef2010-10-22 18:03:46 +0800849llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy>
850RSExportPrimitiveType::RSSpecificTypeMap;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700851
zonr6315f762010-10-05 15:35:14 +0800852llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700853
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700854bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
855 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
856 return true;
857 else
858 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700859}
860
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700861RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800862RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700863 if (TypeName.empty())
864 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700865
Zonr Changb1771ef2010-10-22 18:03:46 +0800866 if (RSSpecificTypeMap->empty()) {
867#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \
868 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
869#include "RSMatrixTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800870#define ENUM_RS_OBJECT_TYPE(type, cname) \
Zonr Changb1771ef2010-10-22 18:03:46 +0800871 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
Zonr Changa65ec162010-10-17 01:53:05 +0800872#include "RSObjectTypeEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700873 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700874
Zonr Changb1771ef2010-10-22 18:03:46 +0800875 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName);
876 if (I == RSSpecificTypeMap->end())
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700877 return DataTypeUnknown;
878 else
879 return I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700880}
881
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700882RSExportPrimitiveType::DataType
Zonr Changb1771ef2010-10-22 18:03:46 +0800883RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700884 T = GET_CANONICAL_TYPE(T);
885 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
886 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700887
Zonr Changb1771ef2010-10-22 18:03:46 +0800888 return GetRSSpecificType( RSExportType::GetTypeName(T) );
889}
890
891bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) {
892 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType));
893}
894
895bool RSExportPrimitiveType::IsRSObjectType(DataType DT) {
896 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700897}
898
Stephen Hinesfeaca062011-02-04 14:08:13 -0800899bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) {
900 bool RSObjectTypeSeen = false;
901 while (T && T->isArrayType()) {
902 T = T->getArrayElementTypeNoTypeQual();
903 }
904
905 const clang::RecordType *RT = T->getAsStructureType();
906 if (!RT) {
907 return false;
908 }
Stephen Hinesb0fabe52013-01-07 19:06:09 -0800909
Stephen Hinesfeaca062011-02-04 14:08:13 -0800910 const clang::RecordDecl *RD = RT->getDecl();
Stephen Hinesb0fabe52013-01-07 19:06:09 -0800911 if (RD) {
912 RD = RD->getDefinition();
913 }
914 if (!RD) {
915 return false;
916 }
917
Stephen Hinesfeaca062011-02-04 14:08:13 -0800918 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
919 FE = RD->field_end();
920 FI != FE;
921 FI++) {
922 // We just look through all field declarations to see if we find a
923 // declaration for an RS object type (or an array of one).
924 const clang::FieldDecl *FD = *FI;
925 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
926 while (FT && FT->isArrayType()) {
927 FT = FT->getArrayElementTypeNoTypeQual();
928 }
929
930 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT);
931 if (IsRSObjectType(DT)) {
932 // RS object types definitely need to be zero-initialized
933 RSObjectTypeSeen = true;
934 } else {
935 switch (DT) {
936 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
937 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
938 case RSExportPrimitiveType::DataTypeRSMatrix4x4:
939 // Matrix types should get zero-initialized as well
940 RSObjectTypeSeen = true;
941 break;
942 default:
943 // Ignore all other primitive types
944 break;
945 }
946 while (FT && FT->isArrayType()) {
947 FT = FT->getArrayElementTypeNoTypeQual();
948 }
949 if (FT->isStructureType()) {
950 // Recursively handle structs of structs (even though these can't
951 // be exported, it is possible for a user to have them internally).
952 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT);
953 }
954 }
955 }
956
957 return RSObjectTypeSeen;
958}
959
Zonr Changa65ec162010-10-17 01:53:05 +0800960const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
961#define ENUM_RS_DATA_TYPE(type, cname, bits) \
962 bits,
963#include "RSDataTypeEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800964 0 // DataTypeMax
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700965};
966
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700967size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800968 slangAssert(((EPT->getType() > DataTypeUnknown) &&
969 (EPT->getType() < DataTypeMax)) &&
970 "RSExportPrimitiveType::GetSizeInBits : unknown data type");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700971 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700972}
973
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700974RSExportPrimitiveType::DataType
Stephen Hines2ef9bc02010-12-13 18:33:23 -0800975RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700976 if (T == NULL)
977 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700978
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700979 switch (T->getTypeClass()) {
980 case clang::Type::Builtin: {
Loganbe274822011-02-16 22:02:54 +0800981 const clang::BuiltinType *BT =
982 UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700983 switch (BT->getKind()) {
Zonr Changa65ec162010-10-17 01:53:05 +0800984#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
985 case builtin_type: { \
986 return DataType ## type; \
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700987 }
Zonr Changa65ec162010-10-17 01:53:05 +0800988#include "RSClangBuiltinEnums.inc"
Zonr Changa65ec162010-10-17 01:53:05 +0800989 // The size of type WChar depend on platform so we abandon the support
990 // to them.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700991 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +0800992 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
993 DiagEngine->Report(
994 DiagEngine->getCustomDiagID(
995 clang::DiagnosticsEngine::Error,
996 "built-in type cannot be exported: '%0'"))
997 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700998 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700999 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001000 }
1001 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001002 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001003 case clang::Type::Record: {
1004 // must be RS object type
Zonr Changb1771ef2010-10-22 18:03:46 +08001005 return RSExportPrimitiveType::GetRSSpecificType(T);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001006 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001007 default: {
Logan Chien9207a2e2011-10-21 15:39:28 +08001008 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
1009 DiagEngine->Report(
1010 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1011 "primitive type cannot be exported: '%0'"))
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001012 << T->getTypeClassName();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001013 break;
1014 }
1015 }
1016
1017 return DataTypeUnknown;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001018}
1019
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001020RSExportPrimitiveType
1021*RSExportPrimitiveType::Create(RSContext *Context,
1022 const clang::Type *T,
1023 const llvm::StringRef &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001024 bool Normalized) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001025 DataType DT = GetDataType(Context, T);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001026
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001027 if ((DT == DataTypeUnknown) || TypeName.empty())
1028 return NULL;
1029 else
Zonr Chang6b6320a2010-10-05 22:42:01 +08001030 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
Stephen Hines2b8fb642012-03-09 00:12:47 -08001031 DT, Normalized);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001032}
1033
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001034RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
Stephen Hines2b8fb642012-03-09 00:12:47 -08001035 const clang::Type *T) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001036 llvm::StringRef TypeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -07001037 if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)
Stephen Hines78e69cb2011-04-22 15:03:19 -07001038 && IsPrimitiveType(T)) {
Stephen Hines2b8fb642012-03-09 00:12:47 -08001039 return Create(Context, T, TypeName);
Stephen Hinese5e64432010-12-02 18:48:20 -08001040 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001041 return NULL;
Stephen Hinese5e64432010-12-02 18:48:20 -08001042 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001043}
1044
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001045llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001046 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001047
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001048 if (isRSObjectType()) {
1049 // struct {
1050 // int *p;
1051 // } __attribute__((packed, aligned(pointer_size)))
1052 //
1053 // which is
1054 //
1055 // <{ [1 x i32] }> in LLVM
1056 //
1057 if (RSObjectLLVMType == NULL) {
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001058 std::vector<llvm::Type *> Elements;
zonr6315f762010-10-05 15:35:14 +08001059 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
Stephen Hinesa67e4452011-07-19 15:39:26 -07001060 RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001061 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001062 return RSObjectLLVMType;
1063 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001064
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001065 switch (mType) {
1066 case DataTypeFloat32: {
1067 return llvm::Type::getFloatTy(C);
1068 break;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001069 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001070 case DataTypeFloat64: {
1071 return llvm::Type::getDoubleTy(C);
1072 break;
1073 }
Shih-wei Liao91a37832010-10-03 19:11:51 -07001074 case DataTypeBoolean: {
1075 return llvm::Type::getInt1Ty(C);
1076 break;
1077 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001078 case DataTypeSigned8:
1079 case DataTypeUnsigned8: {
1080 return llvm::Type::getInt8Ty(C);
1081 break;
1082 }
1083 case DataTypeSigned16:
1084 case DataTypeUnsigned16:
1085 case DataTypeUnsigned565:
1086 case DataTypeUnsigned5551:
1087 case DataTypeUnsigned4444: {
1088 return llvm::Type::getInt16Ty(C);
1089 break;
1090 }
1091 case DataTypeSigned32:
1092 case DataTypeUnsigned32: {
1093 return llvm::Type::getInt32Ty(C);
1094 break;
1095 }
Stephen Hinesa5d2c232010-10-11 16:10:02 -07001096 case DataTypeSigned64:
1097 case DataTypeUnsigned64: {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001098 return llvm::Type::getInt64Ty(C);
1099 break;
1100 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001101 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001102 slangAssert(false && "Unknown data type");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001103 }
1104 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001105
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001106 return NULL;
1107}
1108
Zonr Changa7a828d2010-10-22 03:44:27 +08001109union RSType *RSExportPrimitiveType::convertToSpecType() const {
1110 llvm::OwningPtr<union RSType> ST(new union RSType);
1111 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
1112 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
1113 // slang_rs_type_spec.h
1114 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
1115 return ST.take();
1116}
1117
Zonr Chang641558f2010-10-12 21:07:06 +08001118bool RSExportPrimitiveType::equals(const RSExportable *E) const {
1119 CHECK_PARENT_EQUALITY(RSExportType, E);
1120 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
1121}
1122
Stephen Hinesfdd1ba12012-03-08 17:26:32 -08001123RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) {
1124 if (DT > DataTypeUnknown && DT < DataTypeMax) {
1125 return &gReflectionTypes[DT];
1126 } else {
1127 return NULL;
1128 }
1129}
1130
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001131/**************************** RSExportPointerType ****************************/
1132
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001133RSExportPointerType
1134*RSExportPointerType::Create(RSContext *Context,
1135 const clang::PointerType *PT,
1136 const llvm::StringRef &TypeName) {
1137 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
1138 const RSExportType *PointeeET;
1139
1140 if (PointeeType->getTypeClass() != clang::Type::Pointer) {
1141 PointeeET = RSExportType::Create(Context, PointeeType);
1142 } else {
1143 // Double or higher dimension of pointer, export as int*
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001144 PointeeET = RSExportPrimitiveType::Create(Context,
1145 Context->getASTContext().IntTy.getTypePtr());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001146 }
1147
1148 if (PointeeET == NULL) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001149 // Error diagnostic is emitted for corresponding pointee type
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001150 return NULL;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001151 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001152
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001153 return new RSExportPointerType(Context, TypeName, PointeeET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001154}
1155
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001156llvm::Type *RSExportPointerType::convertToLLVMType() const {
1157 llvm::Type *PointeeType = mPointeeType->getLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001158 return llvm::PointerType::getUnqual(PointeeType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001159}
1160
Zonr Changa7a828d2010-10-22 03:44:27 +08001161union RSType *RSExportPointerType::convertToSpecType() const {
1162 llvm::OwningPtr<union RSType> ST(new union RSType);
1163
1164 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
1165 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
1166
1167 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
1168 return ST.take();
1169 else
1170 return NULL;
1171}
1172
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001173bool RSExportPointerType::keep() {
1174 if (!RSExportType::keep())
1175 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001176 const_cast<RSExportType*>(mPointeeType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001177 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001178}
1179
1180bool RSExportPointerType::equals(const RSExportable *E) const {
1181 CHECK_PARENT_EQUALITY(RSExportType, E);
1182 return (static_cast<const RSExportPointerType*>(E)
1183 ->getPointeeType()->equals(getPointeeType()));
1184}
1185
zonr6315f762010-10-05 15:35:14 +08001186/***************************** RSExportVectorType *****************************/
zonr6315f762010-10-05 15:35:14 +08001187llvm::StringRef
1188RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001189 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001190
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001191 if ((ElementType->getTypeClass() != clang::Type::Builtin))
1192 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001193
Loganbe274822011-02-16 22:02:54 +08001194 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001195 ElementType);
Zonr Changa65ec162010-10-17 01:53:05 +08001196 if ((EVT->getNumElements() < 1) ||
1197 (EVT->getNumElements() > 4))
1198 return llvm::StringRef();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001199
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001200 switch (BT->getKind()) {
1201 // Compiler is smart enough to optimize following *big if branches* since
1202 // they all become "constant comparison" after macro expansion
Zonr Changa65ec162010-10-17 01:53:05 +08001203#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
1204 case builtin_type: { \
1205 const char *Name[] = { cname"2", cname"3", cname"4" }; \
1206 return Name[EVT->getNumElements() - 2]; \
1207 break; \
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001208 }
Zonr Changa65ec162010-10-17 01:53:05 +08001209#include "RSClangBuiltinEnums.inc"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001210 default: {
1211 return llvm::StringRef();
1212 }
1213 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001214}
1215
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001216RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
1217 const clang::ExtVectorType *EVT,
1218 const llvm::StringRef &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001219 bool Normalized) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001220 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001222 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1223 RSExportPrimitiveType::DataType DT =
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001224 RSExportPrimitiveType::GetDataType(Context, ElementType);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001225
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001226 if (DT != RSExportPrimitiveType::DataTypeUnknown)
1227 return new RSExportVectorType(Context,
1228 TypeName,
1229 DT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001230 Normalized,
1231 EVT->getNumElements());
1232 else
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001233 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001234}
1235
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001236llvm::Type *RSExportVectorType::convertToLLVMType() const {
1237 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001238 return llvm::VectorType::get(ElementType, getNumElement());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001239}
1240
Zonr Changa7a828d2010-10-22 03:44:27 +08001241union RSType *RSExportVectorType::convertToSpecType() const {
1242 llvm::OwningPtr<union RSType> ST(new union RSType);
1243
1244 RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
1245 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
1246 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
1247
1248 return ST.take();
1249}
1250
Zonr Chang641558f2010-10-12 21:07:06 +08001251bool RSExportVectorType::equals(const RSExportable *E) const {
1252 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
1253 return (static_cast<const RSExportVectorType*>(E)->getNumElement()
1254 == getNumElement());
1255}
1256
Zonr Chang92b344a2010-10-05 20:39:03 +08001257/***************************** RSExportMatrixType *****************************/
1258RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
1259 const clang::RecordType *RT,
1260 const llvm::StringRef &TypeName,
1261 unsigned Dim) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001262 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
1263 slangAssert((Dim > 1) && "Invalid dimension of matrix");
Zonr Chang92b344a2010-10-05 20:39:03 +08001264
1265 // Check whether the struct rs_matrix is in our expected form (but assume it's
1266 // correct if we're not sure whether it's correct or not)
1267 const clang::RecordDecl* RD = RT->getDecl();
1268 RD = RD->getDefinition();
1269 if (RD != NULL) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001270 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001271 const clang::SourceManager *SM = Context->getSourceManager();
Zonr Chang92b344a2010-10-05 20:39:03 +08001272 // Find definition, perform further examination
1273 if (RD->field_empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001274 DiagEngine->Report(
1275 clang::FullSourceLoc(RD->getLocation(), *SM),
1276 DiagEngine->getCustomDiagID(
1277 clang::DiagnosticsEngine::Error,
1278 "invalid matrix struct: must have 1 field for saving values: '%0'"))
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001279 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001280 return NULL;
1281 }
1282
1283 clang::RecordDecl::field_iterator FIT = RD->field_begin();
1284 const clang::FieldDecl *FD = *FIT;
1285 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1286 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001287 DiagEngine->Report(
1288 clang::FullSourceLoc(RD->getLocation(), *SM),
1289 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1290 "invalid matrix struct: first field should"
1291 " be an array with constant size: '%0'"))
1292 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001293 return NULL;
1294 }
1295 const clang::ConstantArrayType *CAT =
1296 static_cast<const clang::ConstantArrayType *>(FT);
Zonr Chang2e1dba62010-10-05 22:20:11 +08001297 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
Zonr Chang92b344a2010-10-05 20:39:03 +08001298 if ((ElementType == NULL) ||
1299 (ElementType->getTypeClass() != clang::Type::Builtin) ||
Logan Chien9207a2e2011-10-21 15:39:28 +08001300 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() !=
1301 clang::BuiltinType::Float)) {
1302 DiagEngine->Report(
1303 clang::FullSourceLoc(RD->getLocation(), *SM),
1304 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1305 "invalid matrix struct: first field "
1306 "should be a float array: '%0'"))
1307 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001308 return NULL;
1309 }
1310
1311 if (CAT->getSize() != Dim * Dim) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001312 DiagEngine->Report(
1313 clang::FullSourceLoc(RD->getLocation(), *SM),
1314 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1315 "invalid matrix struct: first field "
1316 "should be an array with size %0: '%1'"))
1317 << (Dim * Dim) << (RD->getName());
Zonr Chang92b344a2010-10-05 20:39:03 +08001318 return NULL;
1319 }
1320
1321 FIT++;
1322 if (FIT != RD->field_end()) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001323 DiagEngine->Report(
1324 clang::FullSourceLoc(RD->getLocation(), *SM),
1325 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1326 "invalid matrix struct: must have "
1327 "exactly 1 field: '%0'"))
1328 << RD->getName();
Zonr Chang92b344a2010-10-05 20:39:03 +08001329 return NULL;
1330 }
1331 }
1332
1333 return new RSExportMatrixType(Context, TypeName, Dim);
1334}
1335
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001336llvm::Type *RSExportMatrixType::convertToLLVMType() const {
Zonr Chang92b344a2010-10-05 20:39:03 +08001337 // Construct LLVM type:
1338 // struct {
1339 // float X[mDim * mDim];
1340 // }
1341
1342 llvm::LLVMContext &C = getRSContext()->getLLVMContext();
1343 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
1344 mDim * mDim);
Stephen Hinesa67e4452011-07-19 15:39:26 -07001345 return llvm::StructType::get(C, X, false);
Zonr Chang92b344a2010-10-05 20:39:03 +08001346}
1347
Zonr Changa7a828d2010-10-22 03:44:27 +08001348union RSType *RSExportMatrixType::convertToSpecType() const {
1349 llvm::OwningPtr<union RSType> ST(new union RSType);
1350 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
1351 switch (getDim()) {
1352 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
1353 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
1354 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
Stephen Hines6e6578a2011-02-07 18:05:48 -08001355 default: slangAssert(false && "Matrix type with unsupported dimension.");
Zonr Changa7a828d2010-10-22 03:44:27 +08001356 }
1357 return ST.take();
1358}
1359
Zonr Chang641558f2010-10-12 21:07:06 +08001360bool RSExportMatrixType::equals(const RSExportable *E) const {
1361 CHECK_PARENT_EQUALITY(RSExportType, E);
1362 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
1363}
1364
Zonr Chang2e1dba62010-10-05 22:20:11 +08001365/************************* RSExportConstantArrayType *************************/
1366RSExportConstantArrayType
1367*RSExportConstantArrayType::Create(RSContext *Context,
1368 const clang::ConstantArrayType *CAT) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001369 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
Zonr Chang2e1dba62010-10-05 22:20:11 +08001370
Stephen Hines6e6578a2011-02-07 18:05:48 -08001371 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large");
Zonr Chang2e1dba62010-10-05 22:20:11 +08001372
1373 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
Stephen Hines6e6578a2011-02-07 18:05:48 -08001374 slangAssert((Size > 0) && "Constant array should have size greater than 0");
Zonr Chang2e1dba62010-10-05 22:20:11 +08001375
1376 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1377 RSExportType *ElementET = RSExportType::Create(Context, ElementType);
1378
1379 if (ElementET == NULL) {
Zonr Chang2e1dba62010-10-05 22:20:11 +08001380 return NULL;
1381 }
1382
1383 return new RSExportConstantArrayType(Context,
1384 ElementET,
1385 Size);
1386}
1387
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001388llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
Zonr Chang2e1dba62010-10-05 22:20:11 +08001389 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
1390}
1391
Zonr Changa7a828d2010-10-22 03:44:27 +08001392union RSType *RSExportConstantArrayType::convertToSpecType() const {
1393 llvm::OwningPtr<union RSType> ST(new union RSType);
1394
1395 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
1396 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
1397 ST, getElementType()->getSpecType());
1398 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
1399
1400 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
1401 return ST.take();
1402 else
1403 return NULL;
1404}
1405
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001406bool RSExportConstantArrayType::keep() {
1407 if (!RSExportType::keep())
1408 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001409 const_cast<RSExportType*>(mElementType)->keep();
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001410 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001411}
1412
1413bool RSExportConstantArrayType::equals(const RSExportable *E) const {
1414 CHECK_PARENT_EQUALITY(RSExportType, E);
Stephen Hinesa7b75182010-12-07 15:49:49 -08001415 const RSExportConstantArrayType *RHS =
1416 static_cast<const RSExportConstantArrayType*>(E);
1417 return ((getSize() == RHS->getSize()) &&
1418 (getElementType()->equals(RHS->getElementType())));
Zonr Chang641558f2010-10-12 21:07:06 +08001419}
1420
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001421/**************************** RSExportRecordType ****************************/
1422RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
1423 const clang::RecordType *RT,
1424 const llvm::StringRef &TypeName,
1425 bool mIsArtificial) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001426 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001427
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001428 const clang::RecordDecl *RD = RT->getDecl();
Stephen Hines6e6578a2011-02-07 18:05:48 -08001429 slangAssert(RD->isStruct());
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001430
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001431 RD = RD->getDefinition();
1432 if (RD == NULL) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001433 slangAssert(false && "struct is not defined in this module");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001434 return NULL;
1435 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001436
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001437 // Struct layout construct by clang. We rely on this for obtaining the
1438 // alloc size of a struct and offset of every field in that struct.
1439 const clang::ASTRecordLayout *RL =
Stephen Hines9e5b5032010-11-03 13:19:14 -07001440 &Context->getASTContext().getASTRecordLayout(RD);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001441 slangAssert((RL != NULL) &&
1442 "Failed to retrieve the struct layout from Clang.");
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001443
1444 RSExportRecordType *ERT =
1445 new RSExportRecordType(Context,
1446 TypeName,
1447 RD->hasAttr<clang::PackedAttr>(),
1448 mIsArtificial,
Shih-wei Liao68318a12011-03-11 05:56:15 -08001449 RL->getSize().getQuantity());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001450 unsigned int Index = 0;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001451
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001452 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1453 FE = RD->field_end();
1454 FI != FE;
Shih-wei Liao91a37832010-10-03 19:11:51 -07001455 FI++, Index++) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001456 clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001457
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001458 // FIXME: All fields should be primitive type
Shih-wei Liao43730fe2012-08-02 23:06:18 -07001459 slangAssert(FI->getKind() == clang::Decl::Field);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001460 clang::FieldDecl *FD = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001461
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001462 if (FD->isBitField()) {
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001463 return NULL;
1464 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001465
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001466 // Type
zonr6315f762010-10-05 15:35:14 +08001467 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001468
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001469 if (ET != NULL) {
Zonr Chang0da0a7d2010-10-05 21:26:37 +08001470 ERT->mFields.push_back(
1471 new Field(ET, FD->getName(), ERT,
1472 static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001473 } else {
Logan Chien9207a2e2011-10-21 15:39:28 +08001474 DiagEngine->Report(
1475 clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()),
1476 DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1477 "field type cannot be exported: '%0.%1'"))
1478 << RD->getName() << FD->getName();
Stephen Hines2ef9bc02010-12-13 18:33:23 -08001479 return NULL;
1480 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001481 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001482
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001483 return ERT;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001484}
1485
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001486llvm::Type *RSExportRecordType::convertToLLVMType() const {
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001487 // Create an opaque type since struct may reference itself recursively.
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001488
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001489 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to?
1490 std::vector<llvm::Type*> FieldTypes;
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001491
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001492 for (const_field_iterator FI = fields_begin(), FE = fields_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001493 FI != FE;
1494 FI++) {
1495 const Field *F = *FI;
1496 const RSExportType *FET = F->getType();
Shih-wei Liao1f0d88f2010-06-25 00:15:24 -07001497
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07001498 FieldTypes.push_back(FET->getLLVMType());
1499 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001500
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001501 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
1502 FieldTypes,
1503 mIsPacked);
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001504 if (ST != NULL) {
1505 return ST;
1506 } else {
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001507 return NULL;
Shih-wei Liao7c67e572011-07-19 05:54:53 -07001508 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001509}
Zonr Chang641558f2010-10-12 21:07:06 +08001510
Zonr Changa7a828d2010-10-22 03:44:27 +08001511union RSType *RSExportRecordType::convertToSpecType() const {
1512 unsigned NumFields = getFields().size();
1513 unsigned AllocSize = sizeof(union RSType) +
1514 sizeof(struct RSRecordField) * NumFields;
1515 llvm::OwningPtr<union RSType> ST(
Stephen Hinese639eb52010-11-08 19:27:20 -08001516 reinterpret_cast<union RSType*>(operator new(AllocSize)));
Zonr Changa7a828d2010-10-22 03:44:27 +08001517
1518 ::memset(ST.get(), 0, AllocSize);
1519
1520 RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1521 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1522 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1523
1524 setSpecTypeTemporarily(ST.get());
1525
1526 unsigned FieldIdx = 0;
1527 for (const_field_iterator FI = fields_begin(), FE = fields_end();
1528 FI != FE;
1529 FI++, FieldIdx++) {
1530 const Field *F = *FI;
1531
1532 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1533 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
Zonr Changa7a828d2010-10-22 03:44:27 +08001534 }
1535
Stephen Hinese639eb52010-11-08 19:27:20 -08001536 // TODO(slang): Check whether all fields were created normally.
Zonr Changa7a828d2010-10-22 03:44:27 +08001537
1538 return ST.take();
1539}
1540
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001541bool RSExportRecordType::keep() {
1542 if (!RSExportType::keep())
1543 return false;
Zonr Chang641558f2010-10-12 21:07:06 +08001544 for (std::list<const Field*>::iterator I = mFields.begin(),
1545 E = mFields.end();
1546 I != E;
1547 I++) {
1548 const_cast<RSExportType*>((*I)->getType())->keep();
1549 }
Zonr Chang3cd3dd32010-10-22 02:11:35 +08001550 return true;
Zonr Chang641558f2010-10-12 21:07:06 +08001551}
1552
1553bool RSExportRecordType::equals(const RSExportable *E) const {
1554 CHECK_PARENT_EQUALITY(RSExportType, E);
1555
1556 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1557
1558 if (ERT->getFields().size() != getFields().size())
1559 return false;
1560
1561 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1562
1563 for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1564 if (!(*AI)->getType()->equals((*BI)->getType()))
1565 return false;
1566 AI++;
1567 BI++;
1568 }
1569
1570 return true;
1571}
Stephen Hinese639eb52010-11-08 19:27:20 -08001572
Jason Sams1b6a0882012-03-12 15:07:58 -07001573void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
1574 memset(rtd, 0, sizeof(*rtd));
1575 rtd->vecSize = 1;
1576
1577 switch(getClass()) {
1578 case RSExportType::ExportClassPrimitive: {
1579 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
1580 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
1581 return;
1582 }
1583 case RSExportType::ExportClassPointer: {
1584 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
1585 const RSExportType *PointeeType = EPT->getPointeeType();
1586 PointeeType->convertToRTD(rtd);
1587 rtd->isPointer = true;
1588 return;
1589 }
1590 case RSExportType::ExportClassVector: {
1591 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
1592 rtd->type = EVT->getRSReflectionType(EVT);
1593 rtd->vecSize = EVT->getNumElement();
1594 return;
1595 }
1596 case RSExportType::ExportClassMatrix: {
1597 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
1598 unsigned Dim = EMT->getDim();
1599 slangAssert((Dim >= 2) && (Dim <= 4));
1600 rtd->type = &gReflectionTypes[15 + Dim-2];
1601 return;
1602 }
1603 case RSExportType::ExportClassConstantArray: {
1604 const RSExportConstantArrayType* CAT =
1605 static_cast<const RSExportConstantArrayType*>(this);
1606 CAT->getElementType()->convertToRTD(rtd);
1607 rtd->arraySize = CAT->getSize();
1608 return;
1609 }
1610 case RSExportType::ExportClassRecord: {
1611 slangAssert(!"RSExportType::ExportClassRecord not implemented");
1612 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
1613 }
1614 default: {
1615 slangAssert(false && "Unknown class of type");
1616 }
1617 }
1618}
1619
1620
Stephen Hinese639eb52010-11-08 19:27:20 -08001621} // namespace slang