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