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