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