1/*
2 * Copyright 2010-2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "slang_rs_export_type.h"
18
19#include <list>
20#include <vector>
21
22#include "clang/AST/ASTContext.h"
23#include "clang/AST/RecordLayout.h"
24
25#include "llvm/ADT/StringExtras.h"
26
27#include "llvm/DerivedTypes.h"
28
29#include "llvm/Target/TargetData.h"
30
31#include "llvm/Type.h"
32
33#include "slang_assert.h"
34#include "slang_rs_context.h"
35#include "slang_rs_export_element.h"
36#include "slang_rs_type_spec.h"
37#include "slang_version.h"
38
39#define CHECK_PARENT_EQUALITY(ParentClass, E) \
40  if (!ParentClass::equals(E))                \
41    return false;
42
43namespace slang {
44
45namespace {
46
47static RSReflectionType gReflectionTypes[] = {
48    {"FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false},
49    {"FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false},
50    {"FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false},
51    {"SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false},
52    {"SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false},
53    {"SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false},
54    {"SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false},
55    {"UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true},
56    {"UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true},
57    {"UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true},
58    {"UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false},
59
60    {"BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false},
61
62    {"UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false},
63    {"UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false},
64    {"UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false},
65
66    {"MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false},
67    {"MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false},
68    {"MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false},
69
70    {"RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false},
71    {"RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false},
72    {"RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false},
73    {"RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false},
74    {"RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false},
75    {"RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false},
76    {"RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false},
77    {"RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false},
78    {"RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false},
79    {"RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false},
80    {"RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false},
81    {"RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false}
82};
83
84static const clang::Type *TypeExportableHelper(
85    const clang::Type *T,
86    llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
87    clang::DiagnosticsEngine *DiagEngine,
88    const clang::VarDecl *VD,
89    const clang::RecordDecl *TopLevelRecord);
90
91static void ReportTypeError(clang::DiagnosticsEngine *DiagEngine,
92                            const clang::NamedDecl *ND,
93                            const clang::RecordDecl *TopLevelRecord,
94                            const char *Message,
95                            unsigned int TargetAPI = 0) {
96  if (!DiagEngine) {
97    return;
98  }
99
100  const clang::SourceManager &SM = DiagEngine->getSourceManager();
101
102  // Attempt to use the type declaration first (if we have one).
103  // Fall back to the variable definition, if we are looking at something
104  // like an array declaration that can't be exported.
105  if (TopLevelRecord) {
106    DiagEngine->Report(
107      clang::FullSourceLoc(TopLevelRecord->getLocation(), SM),
108      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
109      << TopLevelRecord->getName() << TargetAPI;
110  } else if (ND) {
111    DiagEngine->Report(
112      clang::FullSourceLoc(ND->getLocation(), SM),
113      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message))
114      << ND->getName() << TargetAPI;
115  } else {
116    slangAssert(false && "Variables should be validated before exporting");
117  }
118}
119
120static const clang::Type *ConstantArrayTypeExportableHelper(
121    const clang::ConstantArrayType *CAT,
122    llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
123    clang::DiagnosticsEngine *DiagEngine,
124    const clang::VarDecl *VD,
125    const clang::RecordDecl *TopLevelRecord) {
126  // Check element type
127  const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
128  if (ElementType->isArrayType()) {
129    ReportTypeError(DiagEngine, VD, TopLevelRecord,
130                    "multidimensional arrays cannot be exported: '%0'");
131    return NULL;
132  } else if (ElementType->isExtVectorType()) {
133    const clang::ExtVectorType *EVT =
134        static_cast<const clang::ExtVectorType*>(ElementType);
135    unsigned numElements = EVT->getNumElements();
136
137    const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
138    if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) {
139      ReportTypeError(DiagEngine, VD, TopLevelRecord,
140        "vectors of non-primitive types cannot be exported: '%0'");
141      return NULL;
142    }
143
144    if (numElements == 3 && CAT->getSize() != 1) {
145      ReportTypeError(DiagEngine, VD, TopLevelRecord,
146        "arrays of width 3 vector types cannot be exported: '%0'");
147      return NULL;
148    }
149  }
150
151  if (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
152                           TopLevelRecord) == NULL) {
153    return NULL;
154  } else {
155    return CAT;
156  }
157}
158
159static const clang::Type *TypeExportableHelper(
160    clang::Type const *T,
161    llvm::SmallPtrSet<clang::Type const *, 8> &SPS,
162    clang::DiagnosticsEngine *DiagEngine,
163    clang::VarDecl const *VD,
164    clang::RecordDecl const *TopLevelRecord) {
165  // Normalize first
166  if ((T = GET_CANONICAL_TYPE(T)) == NULL)
167    return NULL;
168
169  if (SPS.count(T))
170    return T;
171
172  switch (T->getTypeClass()) {
173    case clang::Type::Builtin: {
174      const clang::BuiltinType *BT =
175        UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
176
177      switch (BT->getKind()) {
178#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
179        case builtin_type:
180#include "RSClangBuiltinEnums.inc"
181          return T;
182        default: {
183          return NULL;
184        }
185      }
186    }
187    case clang::Type::Record: {
188      if (RSExportPrimitiveType::GetRSSpecificType(T) !=
189          RSExportPrimitiveType::DataTypeUnknown) {
190        return T;  // RS object type, no further checks are needed
191      }
192
193      // Check internal struct
194      if (T->isUnionType()) {
195        ReportTypeError(DiagEngine, VD, T->getAsUnionType()->getDecl(),
196                        "unions cannot be exported: '%0'");
197        return NULL;
198      } else if (!T->isStructureType()) {
199        slangAssert(false && "Unknown type cannot be exported");
200        return NULL;
201      }
202
203      clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
204      if (RD != NULL) {
205        RD = RD->getDefinition();
206        if (RD == NULL) {
207          ReportTypeError(DiagEngine, NULL, T->getAsStructureType()->getDecl(),
208                          "struct is not defined in this module");
209          return NULL;
210        }
211      }
212
213      if (!TopLevelRecord) {
214        TopLevelRecord = RD;
215      }
216      if (RD->getName().empty()) {
217        ReportTypeError(DiagEngine, NULL, RD,
218                        "anonymous structures cannot be exported");
219        return NULL;
220      }
221
222      // Fast check
223      if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
224        return NULL;
225
226      // Insert myself into checking set
227      SPS.insert(T);
228
229      // Check all element
230      for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
231               FE = RD->field_end();
232           FI != FE;
233           FI++) {
234        const clang::FieldDecl *FD = *FI;
235        const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
236        FT = GET_CANONICAL_TYPE(FT);
237
238        if (!TypeExportableHelper(FT, SPS, DiagEngine, VD, TopLevelRecord)) {
239          return NULL;
240        }
241
242        // We don't support bit fields yet
243        //
244        // TODO(zonr/srhines): allow bit fields of size 8, 16, 32
245        if (FD->isBitField()) {
246          if (DiagEngine) {
247            DiagEngine->Report(
248              clang::FullSourceLoc(FD->getLocation(),
249                                   DiagEngine->getSourceManager()),
250              DiagEngine->getCustomDiagID(
251                clang::DiagnosticsEngine::Error,
252                "bit fields are not able to be exported: '%0.%1'"))
253              << RD->getName()
254              << FD->getName();
255          }
256          return NULL;
257        }
258      }
259
260      return T;
261    }
262    case clang::Type::Pointer: {
263      if (TopLevelRecord) {
264        ReportTypeError(DiagEngine, VD, TopLevelRecord,
265            "structures containing pointers cannot be exported: '%0'");
266        return NULL;
267      }
268
269      const clang::PointerType *PT =
270        UNSAFE_CAST_TYPE(const clang::PointerType, T);
271      const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
272
273      if (PointeeType->getTypeClass() == clang::Type::Pointer) {
274        ReportTypeError(DiagEngine, VD, TopLevelRecord,
275            "multiple levels of pointers cannot be exported: '%0'");
276        return NULL;
277      }
278      // We don't support pointer with array-type pointee or unsupported pointee
279      // type
280      if (PointeeType->isArrayType() ||
281          (TypeExportableHelper(PointeeType, SPS, DiagEngine, VD,
282                                TopLevelRecord) == NULL))
283        return NULL;
284      else
285        return T;
286    }
287    case clang::Type::ExtVector: {
288      const clang::ExtVectorType *EVT =
289          UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
290      // Only vector with size 2, 3 and 4 are supported.
291      if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
292        return NULL;
293
294      // Check base element type
295      const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
296
297      if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
298          (TypeExportableHelper(ElementType, SPS, DiagEngine, VD,
299                                TopLevelRecord) == NULL))
300        return NULL;
301      else
302        return T;
303    }
304    case clang::Type::ConstantArray: {
305      const clang::ConstantArrayType *CAT =
306          UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
307
308      return ConstantArrayTypeExportableHelper(CAT, SPS, DiagEngine, VD,
309                                               TopLevelRecord);
310    }
311    default: {
312      return NULL;
313    }
314  }
315}
316
317// Return the type that can be used to create RSExportType, will always return
318// the canonical type
319// If the Type T is not exportable, this function returns NULL. DiagEngine is
320// used to generate proper Clang diagnostic messages when a
321// non-exportable type is detected. TopLevelRecord is used to capture the
322// highest struct (in the case of a nested hierarchy) for detecting other
323// types that cannot be exported (mostly pointers within a struct).
324static const clang::Type *TypeExportable(const clang::Type *T,
325                                         clang::DiagnosticsEngine *DiagEngine,
326                                         const clang::VarDecl *VD) {
327  llvm::SmallPtrSet<const clang::Type*, 8> SPS =
328      llvm::SmallPtrSet<const clang::Type*, 8>();
329
330  return TypeExportableHelper(T, SPS, DiagEngine, VD, NULL);
331}
332
333static bool ValidateRSObjectInVarDecl(clang::VarDecl *VD,
334                                      bool InCompositeType,
335                                      unsigned int TargetAPI) {
336  if (TargetAPI < SLANG_JB_TARGET_API) {
337    // Only if we are already in a composite type (like an array or structure).
338    if (InCompositeType) {
339      // Only if we are actually exported (i.e. non-static).
340      if (VD->hasLinkage() && (VD->getLinkage() == clang::ExternalLinkage)) {
341        // Only if we are not a pointer to an object.
342        const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr());
343        if (T->getTypeClass() != clang::Type::Pointer) {
344          clang::ASTContext &C = VD->getASTContext();
345          ReportTypeError(&C.getDiagnostics(), VD, NULL,
346                          "arrays/structures containing RS object types "
347                          "cannot be exported in target API < %1: '%0'",
348                          SLANG_JB_TARGET_API);
349          return false;
350        }
351      }
352    }
353  }
354
355  return true;
356}
357
358// Helper function for ValidateType(). We do a recursive descent on the
359// type hierarchy to ensure that we can properly export/handle the
360// declaration.
361// \return true if the variable declaration is valid,
362//         false if it is invalid (along with proper diagnostics).
363//
364// C - ASTContext (for diagnostics + builtin types).
365// T - sub-type that we are validating.
366// ND - (optional) top-level named declaration that we are validating.
367// SPS - set of types we have already seen/validated.
368// InCompositeType - true if we are within an outer composite type.
369// UnionDecl - set if we are in a sub-type of a union.
370// TargetAPI - target SDK API level.
371// IsFilterscript - whether or not we are compiling for Filterscript
372static bool ValidateTypeHelper(
373    clang::ASTContext &C,
374    const clang::Type *&T,
375    clang::NamedDecl *ND,
376    clang::SourceLocation Loc,
377    llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
378    bool InCompositeType,
379    clang::RecordDecl *UnionDecl,
380    unsigned int TargetAPI,
381    bool IsFilterscript) {
382  if ((T = GET_CANONICAL_TYPE(T)) == NULL)
383    return true;
384
385  if (SPS.count(T))
386    return true;
387
388  switch (T->getTypeClass()) {
389    case clang::Type::Record: {
390      if (RSExportPrimitiveType::IsRSObjectType(T)) {
391        clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL);
392        if (VD && !ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) {
393          return false;
394        }
395      }
396
397      if (RSExportPrimitiveType::GetRSSpecificType(T) !=
398          RSExportPrimitiveType::DataTypeUnknown) {
399        if (!UnionDecl) {
400          return true;
401        } else if (RSExportPrimitiveType::IsRSObjectType(T)) {
402          ReportTypeError(&C.getDiagnostics(), NULL, UnionDecl,
403              "unions containing RS object types are not allowed");
404          return false;
405        }
406      }
407
408      clang::RecordDecl *RD = NULL;
409
410      // Check internal struct
411      if (T->isUnionType()) {
412        RD = T->getAsUnionType()->getDecl();
413        UnionDecl = RD;
414      } else if (T->isStructureType()) {
415        RD = T->getAsStructureType()->getDecl();
416      } else {
417        slangAssert(false && "Unknown type cannot be exported");
418        return false;
419      }
420
421      if (RD != NULL) {
422        RD = RD->getDefinition();
423        if (RD == NULL) {
424          // FIXME
425          return true;
426        }
427      }
428
429      // Fast check
430      if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
431        return false;
432
433      // Insert myself into checking set
434      SPS.insert(T);
435
436      // Check all elements
437      for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
438               FE = RD->field_end();
439           FI != FE;
440           FI++) {
441        const clang::FieldDecl *FD = *FI;
442        const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
443        FT = GET_CANONICAL_TYPE(FT);
444
445        if (!ValidateTypeHelper(C, FT, ND, Loc, SPS, true, UnionDecl,
446                                TargetAPI, IsFilterscript)) {
447          return false;
448        }
449      }
450
451      return true;
452    }
453
454    case clang::Type::Builtin: {
455      if (IsFilterscript) {
456        clang::QualType QT = T->getCanonicalTypeInternal();
457        if (QT == C.DoubleTy ||
458            QT == C.LongDoubleTy ||
459            QT == C.LongTy ||
460            QT == C.LongLongTy) {
461          clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
462          if (ND) {
463            DiagEngine.Report(
464              clang::FullSourceLoc(Loc, C.getSourceManager()),
465              DiagEngine.getCustomDiagID(
466                clang::DiagnosticsEngine::Error,
467                "Builtin types > 32 bits in size are forbidden in "
468                "Filterscript: '%0'")) << ND->getName();
469          } else {
470            DiagEngine.Report(
471              clang::FullSourceLoc(Loc, C.getSourceManager()),
472              DiagEngine.getCustomDiagID(
473                clang::DiagnosticsEngine::Error,
474                "Builtin types > 32 bits in size are forbidden in "
475                "Filterscript"));
476          }
477          return false;
478        }
479      }
480      break;
481    }
482
483    case clang::Type::Pointer: {
484      if (IsFilterscript) {
485        if (ND) {
486          clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
487          DiagEngine.Report(
488            clang::FullSourceLoc(Loc, C.getSourceManager()),
489            DiagEngine.getCustomDiagID(
490              clang::DiagnosticsEngine::Error,
491              "Pointers are forbidden in Filterscript: '%0'")) << ND->getName();
492          return false;
493        } else {
494          // TODO(srhines): Find a better way to handle expressions (i.e. no
495          // NamedDecl) involving pointers in FS that should be allowed.
496          // An example would be calls to library functions like
497          // rsMatrixMultiply() that take rs_matrixNxN * types.
498        }
499      }
500
501      const clang::PointerType *PT =
502        UNSAFE_CAST_TYPE(const clang::PointerType, T);
503      const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
504
505      return ValidateTypeHelper(C, PointeeType, ND, Loc, SPS, InCompositeType,
506                                UnionDecl, TargetAPI, IsFilterscript);
507    }
508
509    case clang::Type::ExtVector: {
510      const clang::ExtVectorType *EVT =
511          UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
512      const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
513      if (TargetAPI < SLANG_ICS_TARGET_API &&
514          InCompositeType &&
515          EVT->getNumElements() == 3 &&
516          ND &&
517          ND->getLinkage() == clang::ExternalLinkage) {
518        ReportTypeError(&C.getDiagnostics(), ND, NULL,
519                        "structs containing vectors of dimension 3 cannot "
520                        "be exported at this API level: '%0'");
521        return false;
522      }
523      return ValidateTypeHelper(C, ElementType, ND, Loc, SPS, true, UnionDecl,
524                                TargetAPI, IsFilterscript);
525    }
526
527    case clang::Type::ConstantArray: {
528      const clang::ConstantArrayType *CAT =
529          UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
530      const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
531      return ValidateTypeHelper(C, ElementType, ND, Loc, SPS, true, UnionDecl,
532                                TargetAPI, IsFilterscript);
533    }
534
535    default: {
536      break;
537    }
538  }
539
540  return true;
541}
542
543}  // namespace
544
545/****************************** RSExportType ******************************/
546bool RSExportType::NormalizeType(const clang::Type *&T,
547                                 llvm::StringRef &TypeName,
548                                 clang::DiagnosticsEngine *DiagEngine,
549                                 const clang::VarDecl *VD) {
550  if ((T = TypeExportable(T, DiagEngine, VD)) == NULL) {
551    return false;
552  }
553  // Get type name
554  TypeName = RSExportType::GetTypeName(T);
555  if (TypeName.empty()) {
556    if (DiagEngine) {
557      if (VD) {
558        DiagEngine->Report(
559          clang::FullSourceLoc(VD->getLocation(),
560                               DiagEngine->getSourceManager()),
561          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
562                                      "anonymous types cannot be exported"));
563      } else {
564        DiagEngine->Report(
565          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
566                                      "anonymous types cannot be exported"));
567      }
568    }
569    return false;
570  }
571
572  return true;
573}
574
575bool RSExportType::ValidateType(clang::ASTContext &C, clang::QualType QT,
576    clang::NamedDecl *ND, clang::SourceLocation Loc, unsigned int TargetAPI,
577    bool IsFilterscript) {
578  const clang::Type *T = QT.getTypePtr();
579  llvm::SmallPtrSet<const clang::Type*, 8> SPS =
580      llvm::SmallPtrSet<const clang::Type*, 8>();
581
582  return ValidateTypeHelper(C, T, ND, Loc, SPS, false, NULL, TargetAPI,
583                            IsFilterscript);
584  return true;
585}
586
587bool RSExportType::ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI,
588                                   bool IsFilterscript) {
589  return ValidateType(VD->getASTContext(), VD->getType(), VD,
590                      VD->getLocation(), TargetAPI, IsFilterscript);
591}
592
593const clang::Type
594*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
595  if (DD) {
596    clang::QualType T;
597    if (DD->getTypeSourceInfo())
598      T = DD->getTypeSourceInfo()->getType();
599    else
600      T = DD->getType();
601
602    if (T.isNull())
603      return NULL;
604    else
605      return T.getTypePtr();
606  }
607  return NULL;
608}
609
610llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
611  T = GET_CANONICAL_TYPE(T);
612  if (T == NULL)
613    return llvm::StringRef();
614
615  switch (T->getTypeClass()) {
616    case clang::Type::Builtin: {
617      const clang::BuiltinType *BT =
618        UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
619
620      switch (BT->getKind()) {
621#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
622        case builtin_type:                                    \
623          return cname;                                       \
624        break;
625#include "RSClangBuiltinEnums.inc"
626        default: {
627          slangAssert(false && "Unknown data type of the builtin");
628          break;
629        }
630      }
631      break;
632    }
633    case clang::Type::Record: {
634      clang::RecordDecl *RD;
635      if (T->isStructureType()) {
636        RD = T->getAsStructureType()->getDecl();
637      } else {
638        break;
639      }
640
641      llvm::StringRef Name = RD->getName();
642      if (Name.empty()) {
643        if (RD->getTypedefNameForAnonDecl() != NULL) {
644          Name = RD->getTypedefNameForAnonDecl()->getName();
645        }
646
647        if (Name.empty()) {
648          // Try to find a name from redeclaration (i.e. typedef)
649          for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
650                   RE = RD->redecls_end();
651               RI != RE;
652               RI++) {
653            slangAssert(*RI != NULL && "cannot be NULL object");
654
655            Name = (*RI)->getName();
656            if (!Name.empty())
657              break;
658          }
659        }
660      }
661      return Name;
662    }
663    case clang::Type::Pointer: {
664      // "*" plus pointee name
665      const clang::Type *PT = GET_POINTEE_TYPE(T);
666      llvm::StringRef PointeeName;
667      if (NormalizeType(PT, PointeeName, NULL, NULL)) {
668        char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
669        Name[0] = '*';
670        memcpy(Name + 1, PointeeName.data(), PointeeName.size());
671        Name[PointeeName.size() + 1] = '\0';
672        return Name;
673      }
674      break;
675    }
676    case clang::Type::ExtVector: {
677      const clang::ExtVectorType *EVT =
678          UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
679      return RSExportVectorType::GetTypeName(EVT);
680      break;
681    }
682    case clang::Type::ConstantArray : {
683      // Construct name for a constant array is too complicated.
684      return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE;
685    }
686    default: {
687      break;
688    }
689  }
690
691  return llvm::StringRef();
692}
693
694
695RSExportType *RSExportType::Create(RSContext *Context,
696                                   const clang::Type *T,
697                                   const llvm::StringRef &TypeName) {
698  // Lookup the context to see whether the type was processed before.
699  // Newly created RSExportType will insert into context
700  // in RSExportType::RSExportType()
701  RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
702
703  if (ETI != Context->export_types_end())
704    return ETI->second;
705
706  RSExportType *ET = NULL;
707  switch (T->getTypeClass()) {
708    case clang::Type::Record: {
709      RSExportPrimitiveType::DataType dt =
710          RSExportPrimitiveType::GetRSSpecificType(TypeName);
711      switch (dt) {
712        case RSExportPrimitiveType::DataTypeUnknown: {
713          // User-defined types
714          ET = RSExportRecordType::Create(Context,
715                                          T->getAsStructureType(),
716                                          TypeName);
717          break;
718        }
719        case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
720          // 2 x 2 Matrix type
721          ET = RSExportMatrixType::Create(Context,
722                                          T->getAsStructureType(),
723                                          TypeName,
724                                          2);
725          break;
726        }
727        case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
728          // 3 x 3 Matrix type
729          ET = RSExportMatrixType::Create(Context,
730                                          T->getAsStructureType(),
731                                          TypeName,
732                                          3);
733          break;
734        }
735        case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
736          // 4 x 4 Matrix type
737          ET = RSExportMatrixType::Create(Context,
738                                          T->getAsStructureType(),
739                                          TypeName,
740                                          4);
741          break;
742        }
743        default: {
744          // Others are primitive types
745          ET = RSExportPrimitiveType::Create(Context, T, TypeName);
746          break;
747        }
748      }
749      break;
750    }
751    case clang::Type::Builtin: {
752      ET = RSExportPrimitiveType::Create(Context, T, TypeName);
753      break;
754    }
755    case clang::Type::Pointer: {
756      ET = RSExportPointerType::Create(Context,
757               UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName);
758      // FIXME: free the name (allocated in RSExportType::GetTypeName)
759      delete [] TypeName.data();
760      break;
761    }
762    case clang::Type::ExtVector: {
763      ET = RSExportVectorType::Create(Context,
764               UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName);
765      break;
766    }
767    case clang::Type::ConstantArray: {
768      ET = RSExportConstantArrayType::Create(
769              Context,
770              UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T));
771      break;
772    }
773    default: {
774      clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
775      DiagEngine->Report(
776        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
777                                    "unknown type cannot be exported: '%0'"))
778        << T->getTypeClassName();
779      break;
780    }
781  }
782
783  return ET;
784}
785
786RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
787  llvm::StringRef TypeName;
788  if (NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)) {
789    return Create(Context, T, TypeName);
790  } else {
791    return NULL;
792  }
793}
794
795RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
796                                           const clang::VarDecl *VD) {
797  return RSExportType::Create(Context, GetTypeOfDecl(VD));
798}
799
800size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
801  return ET->getRSContext()->getTargetData()->getTypeStoreSize(
802      ET->getLLVMType());
803}
804
805size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
806  if (ET->getClass() == RSExportType::ExportClassRecord)
807    return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
808  else
809    return ET->getRSContext()->getTargetData()->getTypeAllocSize(
810        ET->getLLVMType());
811}
812
813RSExportType::RSExportType(RSContext *Context,
814                           ExportClass Class,
815                           const llvm::StringRef &Name)
816    : RSExportable(Context, RSExportable::EX_TYPE),
817      mClass(Class),
818      // Make a copy on Name since memory stored @Name is either allocated in
819      // ASTContext or allocated in GetTypeName which will be destroyed later.
820      mName(Name.data(), Name.size()),
821      mLLVMType(NULL),
822      mSpecType(NULL) {
823  // Don't cache the type whose name start with '<'. Those type failed to
824  // get their name since constructing their name in GetTypeName() requiring
825  // complicated work.
826  if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
827    // TODO(zonr): Need to check whether the insertion is successful or not.
828    Context->insertExportType(llvm::StringRef(Name), this);
829  return;
830}
831
832bool RSExportType::keep() {
833  if (!RSExportable::keep())
834    return false;
835  // Invalidate converted LLVM type.
836  mLLVMType = NULL;
837  return true;
838}
839
840bool RSExportType::equals(const RSExportable *E) const {
841  CHECK_PARENT_EQUALITY(RSExportable, E);
842  return (static_cast<const RSExportType*>(E)->getClass() == getClass());
843}
844
845RSExportType::~RSExportType() {
846  delete mSpecType;
847}
848
849/************************** RSExportPrimitiveType **************************/
850llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy>
851RSExportPrimitiveType::RSSpecificTypeMap;
852
853llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
854
855bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
856  if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
857    return true;
858  else
859    return false;
860}
861
862RSExportPrimitiveType::DataType
863RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) {
864  if (TypeName.empty())
865    return DataTypeUnknown;
866
867  if (RSSpecificTypeMap->empty()) {
868#define ENUM_RS_MATRIX_TYPE(type, cname, dim)                       \
869    RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
870#include "RSMatrixTypeEnums.inc"
871#define ENUM_RS_OBJECT_TYPE(type, cname)                            \
872    RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type);
873#include "RSObjectTypeEnums.inc"
874  }
875
876  RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName);
877  if (I == RSSpecificTypeMap->end())
878    return DataTypeUnknown;
879  else
880    return I->getValue();
881}
882
883RSExportPrimitiveType::DataType
884RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) {
885  T = GET_CANONICAL_TYPE(T);
886  if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
887    return DataTypeUnknown;
888
889  return GetRSSpecificType( RSExportType::GetTypeName(T) );
890}
891
892bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) {
893  return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType));
894}
895
896bool RSExportPrimitiveType::IsRSObjectType(DataType DT) {
897  return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType));
898}
899
900bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) {
901  bool RSObjectTypeSeen = false;
902  while (T && T->isArrayType()) {
903    T = T->getArrayElementTypeNoTypeQual();
904  }
905
906  const clang::RecordType *RT = T->getAsStructureType();
907  if (!RT) {
908    return false;
909  }
910  const clang::RecordDecl *RD = RT->getDecl();
911  RD = RD->getDefinition();
912  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
913         FE = RD->field_end();
914       FI != FE;
915       FI++) {
916    // We just look through all field declarations to see if we find a
917    // declaration for an RS object type (or an array of one).
918    const clang::FieldDecl *FD = *FI;
919    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
920    while (FT && FT->isArrayType()) {
921      FT = FT->getArrayElementTypeNoTypeQual();
922    }
923
924    RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT);
925    if (IsRSObjectType(DT)) {
926      // RS object types definitely need to be zero-initialized
927      RSObjectTypeSeen = true;
928    } else {
929      switch (DT) {
930        case RSExportPrimitiveType::DataTypeRSMatrix2x2:
931        case RSExportPrimitiveType::DataTypeRSMatrix3x3:
932        case RSExportPrimitiveType::DataTypeRSMatrix4x4:
933          // Matrix types should get zero-initialized as well
934          RSObjectTypeSeen = true;
935          break;
936        default:
937          // Ignore all other primitive types
938          break;
939      }
940      while (FT && FT->isArrayType()) {
941        FT = FT->getArrayElementTypeNoTypeQual();
942      }
943      if (FT->isStructureType()) {
944        // Recursively handle structs of structs (even though these can't
945        // be exported, it is possible for a user to have them internally).
946        RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT);
947      }
948    }
949  }
950
951  return RSObjectTypeSeen;
952}
953
954const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
955#define ENUM_RS_DATA_TYPE(type, cname, bits)  \
956  bits,
957#include "RSDataTypeEnums.inc"
958  0   // DataTypeMax
959};
960
961size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
962  slangAssert(((EPT->getType() > DataTypeUnknown) &&
963               (EPT->getType() < DataTypeMax)) &&
964              "RSExportPrimitiveType::GetSizeInBits : unknown data type");
965  return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
966}
967
968RSExportPrimitiveType::DataType
969RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) {
970  if (T == NULL)
971    return DataTypeUnknown;
972
973  switch (T->getTypeClass()) {
974    case clang::Type::Builtin: {
975      const clang::BuiltinType *BT =
976        UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
977      switch (BT->getKind()) {
978#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
979        case builtin_type: {                                  \
980          return DataType ## type;                            \
981        }
982#include "RSClangBuiltinEnums.inc"
983        // The size of type WChar depend on platform so we abandon the support
984        // to them.
985        default: {
986          clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
987          DiagEngine->Report(
988            DiagEngine->getCustomDiagID(
989              clang::DiagnosticsEngine::Error,
990              "built-in type cannot be exported: '%0'"))
991            << T->getTypeClassName();
992          break;
993        }
994      }
995      break;
996    }
997    case clang::Type::Record: {
998      // must be RS object type
999      return RSExportPrimitiveType::GetRSSpecificType(T);
1000    }
1001    default: {
1002      clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
1003      DiagEngine->Report(
1004        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1005                                    "primitive type cannot be exported: '%0'"))
1006          << T->getTypeClassName();
1007      break;
1008    }
1009  }
1010
1011  return DataTypeUnknown;
1012}
1013
1014RSExportPrimitiveType
1015*RSExportPrimitiveType::Create(RSContext *Context,
1016                               const clang::Type *T,
1017                               const llvm::StringRef &TypeName,
1018                               bool Normalized) {
1019  DataType DT = GetDataType(Context, T);
1020
1021  if ((DT == DataTypeUnknown) || TypeName.empty())
1022    return NULL;
1023  else
1024    return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
1025                                     DT, Normalized);
1026}
1027
1028RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
1029                                                     const clang::Type *T) {
1030  llvm::StringRef TypeName;
1031  if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)
1032      && IsPrimitiveType(T)) {
1033    return Create(Context, T, TypeName);
1034  } else {
1035    return NULL;
1036  }
1037}
1038
1039llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
1040  llvm::LLVMContext &C = getRSContext()->getLLVMContext();
1041
1042  if (isRSObjectType()) {
1043    // struct {
1044    //   int *p;
1045    // } __attribute__((packed, aligned(pointer_size)))
1046    //
1047    // which is
1048    //
1049    // <{ [1 x i32] }> in LLVM
1050    //
1051    if (RSObjectLLVMType == NULL) {
1052      std::vector<llvm::Type *> Elements;
1053      Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
1054      RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
1055    }
1056    return RSObjectLLVMType;
1057  }
1058
1059  switch (mType) {
1060    case DataTypeFloat32: {
1061      return llvm::Type::getFloatTy(C);
1062      break;
1063    }
1064    case DataTypeFloat64: {
1065      return llvm::Type::getDoubleTy(C);
1066      break;
1067    }
1068    case DataTypeBoolean: {
1069      return llvm::Type::getInt1Ty(C);
1070      break;
1071    }
1072    case DataTypeSigned8:
1073    case DataTypeUnsigned8: {
1074      return llvm::Type::getInt8Ty(C);
1075      break;
1076    }
1077    case DataTypeSigned16:
1078    case DataTypeUnsigned16:
1079    case DataTypeUnsigned565:
1080    case DataTypeUnsigned5551:
1081    case DataTypeUnsigned4444: {
1082      return llvm::Type::getInt16Ty(C);
1083      break;
1084    }
1085    case DataTypeSigned32:
1086    case DataTypeUnsigned32: {
1087      return llvm::Type::getInt32Ty(C);
1088      break;
1089    }
1090    case DataTypeSigned64:
1091    case DataTypeUnsigned64: {
1092      return llvm::Type::getInt64Ty(C);
1093      break;
1094    }
1095    default: {
1096      slangAssert(false && "Unknown data type");
1097    }
1098  }
1099
1100  return NULL;
1101}
1102
1103union RSType *RSExportPrimitiveType::convertToSpecType() const {
1104  llvm::OwningPtr<union RSType> ST(new union RSType);
1105  RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
1106  // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
1107  // slang_rs_type_spec.h
1108  RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
1109  return ST.take();
1110}
1111
1112bool RSExportPrimitiveType::equals(const RSExportable *E) const {
1113  CHECK_PARENT_EQUALITY(RSExportType, E);
1114  return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
1115}
1116
1117RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) {
1118  if (DT > DataTypeUnknown && DT < DataTypeMax) {
1119    return &gReflectionTypes[DT];
1120  } else {
1121    return NULL;
1122  }
1123}
1124
1125/**************************** RSExportPointerType ****************************/
1126
1127RSExportPointerType
1128*RSExportPointerType::Create(RSContext *Context,
1129                             const clang::PointerType *PT,
1130                             const llvm::StringRef &TypeName) {
1131  const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
1132  const RSExportType *PointeeET;
1133
1134  if (PointeeType->getTypeClass() != clang::Type::Pointer) {
1135    PointeeET = RSExportType::Create(Context, PointeeType);
1136  } else {
1137    // Double or higher dimension of pointer, export as int*
1138    PointeeET = RSExportPrimitiveType::Create(Context,
1139                    Context->getASTContext().IntTy.getTypePtr());
1140  }
1141
1142  if (PointeeET == NULL) {
1143    // Error diagnostic is emitted for corresponding pointee type
1144    return NULL;
1145  }
1146
1147  return new RSExportPointerType(Context, TypeName, PointeeET);
1148}
1149
1150llvm::Type *RSExportPointerType::convertToLLVMType() const {
1151  llvm::Type *PointeeType = mPointeeType->getLLVMType();
1152  return llvm::PointerType::getUnqual(PointeeType);
1153}
1154
1155union RSType *RSExportPointerType::convertToSpecType() const {
1156  llvm::OwningPtr<union RSType> ST(new union RSType);
1157
1158  RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
1159  RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
1160
1161  if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
1162    return ST.take();
1163  else
1164    return NULL;
1165}
1166
1167bool RSExportPointerType::keep() {
1168  if (!RSExportType::keep())
1169    return false;
1170  const_cast<RSExportType*>(mPointeeType)->keep();
1171  return true;
1172}
1173
1174bool RSExportPointerType::equals(const RSExportable *E) const {
1175  CHECK_PARENT_EQUALITY(RSExportType, E);
1176  return (static_cast<const RSExportPointerType*>(E)
1177              ->getPointeeType()->equals(getPointeeType()));
1178}
1179
1180/***************************** RSExportVectorType *****************************/
1181llvm::StringRef
1182RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
1183  const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1184
1185  if ((ElementType->getTypeClass() != clang::Type::Builtin))
1186    return llvm::StringRef();
1187
1188  const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType,
1189                                                  ElementType);
1190  if ((EVT->getNumElements() < 1) ||
1191      (EVT->getNumElements() > 4))
1192    return llvm::StringRef();
1193
1194  switch (BT->getKind()) {
1195    // Compiler is smart enough to optimize following *big if branches* since
1196    // they all become "constant comparison" after macro expansion
1197#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
1198    case builtin_type: {                                      \
1199      const char *Name[] = { cname"2", cname"3", cname"4" };  \
1200      return Name[EVT->getNumElements() - 2];                 \
1201      break;                                                  \
1202    }
1203#include "RSClangBuiltinEnums.inc"
1204    default: {
1205      return llvm::StringRef();
1206    }
1207  }
1208}
1209
1210RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
1211                                               const clang::ExtVectorType *EVT,
1212                                               const llvm::StringRef &TypeName,
1213                                               bool Normalized) {
1214  slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
1215
1216  const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1217  RSExportPrimitiveType::DataType DT =
1218      RSExportPrimitiveType::GetDataType(Context, ElementType);
1219
1220  if (DT != RSExportPrimitiveType::DataTypeUnknown)
1221    return new RSExportVectorType(Context,
1222                                  TypeName,
1223                                  DT,
1224                                  Normalized,
1225                                  EVT->getNumElements());
1226  else
1227    return NULL;
1228}
1229
1230llvm::Type *RSExportVectorType::convertToLLVMType() const {
1231  llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
1232  return llvm::VectorType::get(ElementType, getNumElement());
1233}
1234
1235union RSType *RSExportVectorType::convertToSpecType() const {
1236  llvm::OwningPtr<union RSType> ST(new union RSType);
1237
1238  RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
1239  RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
1240  RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
1241
1242  return ST.take();
1243}
1244
1245bool RSExportVectorType::equals(const RSExportable *E) const {
1246  CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
1247  return (static_cast<const RSExportVectorType*>(E)->getNumElement()
1248              == getNumElement());
1249}
1250
1251/***************************** RSExportMatrixType *****************************/
1252RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
1253                                               const clang::RecordType *RT,
1254                                               const llvm::StringRef &TypeName,
1255                                               unsigned Dim) {
1256  slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
1257  slangAssert((Dim > 1) && "Invalid dimension of matrix");
1258
1259  // Check whether the struct rs_matrix is in our expected form (but assume it's
1260  // correct if we're not sure whether it's correct or not)
1261  const clang::RecordDecl* RD = RT->getDecl();
1262  RD = RD->getDefinition();
1263  if (RD != NULL) {
1264    clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
1265    const clang::SourceManager *SM = Context->getSourceManager();
1266    // Find definition, perform further examination
1267    if (RD->field_empty()) {
1268      DiagEngine->Report(
1269        clang::FullSourceLoc(RD->getLocation(), *SM),
1270        DiagEngine->getCustomDiagID(
1271          clang::DiagnosticsEngine::Error,
1272          "invalid matrix struct: must have 1 field for saving values: '%0'"))
1273           << RD->getName();
1274      return NULL;
1275    }
1276
1277    clang::RecordDecl::field_iterator FIT = RD->field_begin();
1278    const clang::FieldDecl *FD = *FIT;
1279    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1280    if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
1281      DiagEngine->Report(
1282        clang::FullSourceLoc(RD->getLocation(), *SM),
1283        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1284                                    "invalid matrix struct: first field should"
1285                                    " be an array with constant size: '%0'"))
1286        << RD->getName();
1287      return NULL;
1288    }
1289    const clang::ConstantArrayType *CAT =
1290      static_cast<const clang::ConstantArrayType *>(FT);
1291    const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1292    if ((ElementType == NULL) ||
1293        (ElementType->getTypeClass() != clang::Type::Builtin) ||
1294        (static_cast<const clang::BuiltinType *>(ElementType)->getKind() !=
1295         clang::BuiltinType::Float)) {
1296      DiagEngine->Report(
1297        clang::FullSourceLoc(RD->getLocation(), *SM),
1298        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1299                                    "invalid matrix struct: first field "
1300                                    "should be a float array: '%0'"))
1301        << RD->getName();
1302      return NULL;
1303    }
1304
1305    if (CAT->getSize() != Dim * Dim) {
1306      DiagEngine->Report(
1307        clang::FullSourceLoc(RD->getLocation(), *SM),
1308        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1309                                    "invalid matrix struct: first field "
1310                                    "should be an array with size %0: '%1'"))
1311        << (Dim * Dim) << (RD->getName());
1312      return NULL;
1313    }
1314
1315    FIT++;
1316    if (FIT != RD->field_end()) {
1317      DiagEngine->Report(
1318        clang::FullSourceLoc(RD->getLocation(), *SM),
1319        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1320                                    "invalid matrix struct: must have "
1321                                    "exactly 1 field: '%0'"))
1322        << RD->getName();
1323      return NULL;
1324    }
1325  }
1326
1327  return new RSExportMatrixType(Context, TypeName, Dim);
1328}
1329
1330llvm::Type *RSExportMatrixType::convertToLLVMType() const {
1331  // Construct LLVM type:
1332  // struct {
1333  //  float X[mDim * mDim];
1334  // }
1335
1336  llvm::LLVMContext &C = getRSContext()->getLLVMContext();
1337  llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
1338                                            mDim * mDim);
1339  return llvm::StructType::get(C, X, false);
1340}
1341
1342union RSType *RSExportMatrixType::convertToSpecType() const {
1343  llvm::OwningPtr<union RSType> ST(new union RSType);
1344  RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
1345  switch (getDim()) {
1346    case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
1347    case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
1348    case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
1349    default: slangAssert(false && "Matrix type with unsupported dimension.");
1350  }
1351  return ST.take();
1352}
1353
1354bool RSExportMatrixType::equals(const RSExportable *E) const {
1355  CHECK_PARENT_EQUALITY(RSExportType, E);
1356  return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
1357}
1358
1359/************************* RSExportConstantArrayType *************************/
1360RSExportConstantArrayType
1361*RSExportConstantArrayType::Create(RSContext *Context,
1362                                   const clang::ConstantArrayType *CAT) {
1363  slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
1364
1365  slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large");
1366
1367  unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
1368  slangAssert((Size > 0) && "Constant array should have size greater than 0");
1369
1370  const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1371  RSExportType *ElementET = RSExportType::Create(Context, ElementType);
1372
1373  if (ElementET == NULL) {
1374    return NULL;
1375  }
1376
1377  return new RSExportConstantArrayType(Context,
1378                                       ElementET,
1379                                       Size);
1380}
1381
1382llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
1383  return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
1384}
1385
1386union RSType *RSExportConstantArrayType::convertToSpecType() const {
1387  llvm::OwningPtr<union RSType> ST(new union RSType);
1388
1389  RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
1390  RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
1391      ST, getElementType()->getSpecType());
1392  RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
1393
1394  if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
1395    return ST.take();
1396  else
1397    return NULL;
1398}
1399
1400bool RSExportConstantArrayType::keep() {
1401  if (!RSExportType::keep())
1402    return false;
1403  const_cast<RSExportType*>(mElementType)->keep();
1404  return true;
1405}
1406
1407bool RSExportConstantArrayType::equals(const RSExportable *E) const {
1408  CHECK_PARENT_EQUALITY(RSExportType, E);
1409  const RSExportConstantArrayType *RHS =
1410      static_cast<const RSExportConstantArrayType*>(E);
1411  return ((getSize() == RHS->getSize()) &&
1412          (getElementType()->equals(RHS->getElementType())));
1413}
1414
1415/**************************** RSExportRecordType ****************************/
1416RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
1417                                               const clang::RecordType *RT,
1418                                               const llvm::StringRef &TypeName,
1419                                               bool mIsArtificial) {
1420  slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
1421
1422  const clang::RecordDecl *RD = RT->getDecl();
1423  slangAssert(RD->isStruct());
1424
1425  RD = RD->getDefinition();
1426  if (RD == NULL) {
1427    slangAssert(false && "struct is not defined in this module");
1428    return NULL;
1429  }
1430
1431  // Struct layout construct by clang. We rely on this for obtaining the
1432  // alloc size of a struct and offset of every field in that struct.
1433  const clang::ASTRecordLayout *RL =
1434      &Context->getASTContext().getASTRecordLayout(RD);
1435  slangAssert((RL != NULL) &&
1436      "Failed to retrieve the struct layout from Clang.");
1437
1438  RSExportRecordType *ERT =
1439      new RSExportRecordType(Context,
1440                             TypeName,
1441                             RD->hasAttr<clang::PackedAttr>(),
1442                             mIsArtificial,
1443                             RL->getSize().getQuantity());
1444  unsigned int Index = 0;
1445
1446  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1447           FE = RD->field_end();
1448       FI != FE;
1449       FI++, Index++) {
1450    clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
1451
1452    // FIXME: All fields should be primitive type
1453    slangAssert(FI->getKind() == clang::Decl::Field);
1454    clang::FieldDecl *FD = *FI;
1455
1456    if (FD->isBitField()) {
1457      return NULL;
1458    }
1459
1460    // Type
1461    RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
1462
1463    if (ET != NULL) {
1464      ERT->mFields.push_back(
1465          new Field(ET, FD->getName(), ERT,
1466                    static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
1467    } else {
1468      DiagEngine->Report(
1469        clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()),
1470        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1471                                    "field type cannot be exported: '%0.%1'"))
1472        << RD->getName() << FD->getName();
1473      return NULL;
1474    }
1475  }
1476
1477  return ERT;
1478}
1479
1480llvm::Type *RSExportRecordType::convertToLLVMType() const {
1481  // Create an opaque type since struct may reference itself recursively.
1482
1483  // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to?
1484  std::vector<llvm::Type*> FieldTypes;
1485
1486  for (const_field_iterator FI = fields_begin(), FE = fields_end();
1487       FI != FE;
1488       FI++) {
1489    const Field *F = *FI;
1490    const RSExportType *FET = F->getType();
1491
1492    FieldTypes.push_back(FET->getLLVMType());
1493  }
1494
1495  llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
1496                                               FieldTypes,
1497                                               mIsPacked);
1498  if (ST != NULL) {
1499    return ST;
1500  } else {
1501    return NULL;
1502  }
1503}
1504
1505union RSType *RSExportRecordType::convertToSpecType() const {
1506  unsigned NumFields = getFields().size();
1507  unsigned AllocSize = sizeof(union RSType) +
1508                       sizeof(struct RSRecordField) * NumFields;
1509  llvm::OwningPtr<union RSType> ST(
1510      reinterpret_cast<union RSType*>(operator new(AllocSize)));
1511
1512  ::memset(ST.get(), 0, AllocSize);
1513
1514  RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1515  RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1516  RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1517
1518  setSpecTypeTemporarily(ST.get());
1519
1520  unsigned FieldIdx = 0;
1521  for (const_field_iterator FI = fields_begin(), FE = fields_end();
1522       FI != FE;
1523       FI++, FieldIdx++) {
1524    const Field *F = *FI;
1525
1526    RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1527    RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
1528  }
1529
1530  // TODO(slang): Check whether all fields were created normally.
1531
1532  return ST.take();
1533}
1534
1535bool RSExportRecordType::keep() {
1536  if (!RSExportType::keep())
1537    return false;
1538  for (std::list<const Field*>::iterator I = mFields.begin(),
1539          E = mFields.end();
1540       I != E;
1541       I++) {
1542    const_cast<RSExportType*>((*I)->getType())->keep();
1543  }
1544  return true;
1545}
1546
1547bool RSExportRecordType::equals(const RSExportable *E) const {
1548  CHECK_PARENT_EQUALITY(RSExportType, E);
1549
1550  const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1551
1552  if (ERT->getFields().size() != getFields().size())
1553    return false;
1554
1555  const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1556
1557  for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1558    if (!(*AI)->getType()->equals((*BI)->getType()))
1559      return false;
1560    AI++;
1561    BI++;
1562  }
1563
1564  return true;
1565}
1566
1567void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
1568    memset(rtd, 0, sizeof(*rtd));
1569    rtd->vecSize = 1;
1570
1571    switch(getClass()) {
1572    case RSExportType::ExportClassPrimitive: {
1573            const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
1574            rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
1575            return;
1576        }
1577    case RSExportType::ExportClassPointer: {
1578            const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
1579            const RSExportType *PointeeType = EPT->getPointeeType();
1580            PointeeType->convertToRTD(rtd);
1581            rtd->isPointer = true;
1582            return;
1583        }
1584    case RSExportType::ExportClassVector: {
1585            const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
1586            rtd->type = EVT->getRSReflectionType(EVT);
1587            rtd->vecSize = EVT->getNumElement();
1588            return;
1589        }
1590    case RSExportType::ExportClassMatrix: {
1591            const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
1592            unsigned Dim = EMT->getDim();
1593            slangAssert((Dim >= 2) && (Dim <= 4));
1594            rtd->type = &gReflectionTypes[15 + Dim-2];
1595            return;
1596        }
1597    case RSExportType::ExportClassConstantArray: {
1598            const RSExportConstantArrayType* CAT =
1599              static_cast<const RSExportConstantArrayType*>(this);
1600            CAT->getElementType()->convertToRTD(rtd);
1601            rtd->arraySize = CAT->getSize();
1602            return;
1603        }
1604    case RSExportType::ExportClassRecord: {
1605            slangAssert(!"RSExportType::ExportClassRecord not implemented");
1606            return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
1607        }
1608    default: {
1609            slangAssert(false && "Unknown class of type");
1610        }
1611    }
1612}
1613
1614
1615}  // namespace slang
1616