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