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