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() && (VD->getLinkage() == clang::ExternalLinkage)) {
    339         // Only if we are not a pointer to an object.
    340         const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr());
    341         if (T->getTypeClass() != clang::Type::Pointer) {
    342           clang::ASTContext &C = VD->getASTContext();
    343           ReportTypeError(&C.getDiagnostics(), VD, NULL,
    344                           "arrays/structures containing RS object types "
    345                           "cannot be exported in target API < %1: '%0'",
    346                           SLANG_JB_TARGET_API);
    347           return false;
    348         }
    349       }
    350     }
    351   }
    352 
    353   return true;
    354 }
    355 
    356 // Helper function for ValidateType(). We do a recursive descent on the
    357 // type hierarchy to ensure that we can properly export/handle the
    358 // declaration.
    359 // \return true if the variable declaration is valid,
    360 //         false if it is invalid (along with proper diagnostics).
    361 //
    362 // C - ASTContext (for diagnostics + builtin types).
    363 // T - sub-type that we are validating.
    364 // ND - (optional) top-level named declaration that we are validating.
    365 // SPS - set of types we have already seen/validated.
    366 // InCompositeType - true if we are within an outer composite type.
    367 // UnionDecl - set if we are in a sub-type of a union.
    368 // TargetAPI - target SDK API level.
    369 // IsFilterscript - whether or not we are compiling for Filterscript
    370 static bool ValidateTypeHelper(
    371     clang::ASTContext &C,
    372     const clang::Type *&T,
    373     clang::NamedDecl *ND,
    374     clang::SourceLocation Loc,
    375     llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
    376     bool InCompositeType,
    377     clang::RecordDecl *UnionDecl,
    378     unsigned int TargetAPI,
    379     bool IsFilterscript) {
    380   if ((T = GET_CANONICAL_TYPE(T)) == NULL)
    381     return true;
    382 
    383   if (SPS.count(T))
    384     return true;
    385 
    386   switch (T->getTypeClass()) {
    387     case clang::Type::Record: {
    388       if (RSExportPrimitiveType::IsRSObjectType(T)) {
    389         clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL);
    390         if (VD && !ValidateRSObjectInVarDecl(VD, InCompositeType, TargetAPI)) {
    391           return false;
    392         }
    393       }
    394 
    395       if (RSExportPrimitiveType::GetRSSpecificType(T) !=
    396           RSExportPrimitiveType::DataTypeUnknown) {
    397         if (!UnionDecl) {
    398           return true;
    399         } else if (RSExportPrimitiveType::IsRSObjectType(T)) {
    400           ReportTypeError(&C.getDiagnostics(), NULL, UnionDecl,
    401               "unions containing RS object types are not allowed");
    402           return false;
    403         }
    404       }
    405 
    406       clang::RecordDecl *RD = NULL;
    407 
    408       // Check internal struct
    409       if (T->isUnionType()) {
    410         RD = T->getAsUnionType()->getDecl();
    411         UnionDecl = RD;
    412       } else if (T->isStructureType()) {
    413         RD = T->getAsStructureType()->getDecl();
    414       } else {
    415         slangAssert(false && "Unknown type cannot be exported");
    416         return false;
    417       }
    418 
    419       if (RD != NULL) {
    420         RD = RD->getDefinition();
    421         if (RD == NULL) {
    422           // FIXME
    423           return true;
    424         }
    425       }
    426 
    427       // Fast check
    428       if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
    429         return false;
    430 
    431       // Insert myself into checking set
    432       SPS.insert(T);
    433 
    434       // Check all elements
    435       for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    436                FE = RD->field_end();
    437            FI != FE;
    438            FI++) {
    439         const clang::FieldDecl *FD = *FI;
    440         const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    441         FT = GET_CANONICAL_TYPE(FT);
    442 
    443         if (!ValidateTypeHelper(C, FT, ND, Loc, SPS, true, UnionDecl,
    444                                 TargetAPI, IsFilterscript)) {
    445           return false;
    446         }
    447       }
    448 
    449       return true;
    450     }
    451 
    452     case clang::Type::Builtin: {
    453       if (IsFilterscript) {
    454         clang::QualType QT = T->getCanonicalTypeInternal();
    455         if (QT == C.DoubleTy ||
    456             QT == C.LongDoubleTy ||
    457             QT == C.LongTy ||
    458             QT == C.LongLongTy) {
    459           clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
    460           if (ND) {
    461             DiagEngine.Report(
    462               clang::FullSourceLoc(Loc, C.getSourceManager()),
    463               DiagEngine.getCustomDiagID(
    464                 clang::DiagnosticsEngine::Error,
    465                 "Builtin types > 32 bits in size are forbidden in "
    466                 "Filterscript: '%0'")) << ND->getName();
    467           } else {
    468             DiagEngine.Report(
    469               clang::FullSourceLoc(Loc, C.getSourceManager()),
    470               DiagEngine.getCustomDiagID(
    471                 clang::DiagnosticsEngine::Error,
    472                 "Builtin types > 32 bits in size are forbidden in "
    473                 "Filterscript"));
    474           }
    475           return false;
    476         }
    477       }
    478       break;
    479     }
    480 
    481     case clang::Type::Pointer: {
    482       if (IsFilterscript) {
    483         if (ND) {
    484           clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
    485           DiagEngine.Report(
    486             clang::FullSourceLoc(Loc, C.getSourceManager()),
    487             DiagEngine.getCustomDiagID(
    488               clang::DiagnosticsEngine::Error,
    489               "Pointers are forbidden in Filterscript: '%0'")) << ND->getName();
    490           return false;
    491         } else {
    492           // TODO(srhines): Find a better way to handle expressions (i.e. no
    493           // NamedDecl) involving pointers in FS that should be allowed.
    494           // An example would be calls to library functions like
    495           // rsMatrixMultiply() that take rs_matrixNxN * types.
    496         }
    497       }
    498 
    499       const clang::PointerType *PT =
    500         UNSAFE_CAST_TYPE(const clang::PointerType, T);
    501       const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
    502 
    503       return ValidateTypeHelper(C, PointeeType, ND, Loc, SPS, InCompositeType,
    504                                 UnionDecl, TargetAPI, IsFilterscript);
    505     }
    506 
    507     case clang::Type::ExtVector: {
    508       const clang::ExtVectorType *EVT =
    509           UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
    510       const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
    511       if (TargetAPI < SLANG_ICS_TARGET_API &&
    512           InCompositeType &&
    513           EVT->getNumElements() == 3 &&
    514           ND &&
    515           ND->getLinkage() == clang::ExternalLinkage) {
    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()->getDataLayout()->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()->getDataLayout()->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 
    909   const clang::RecordDecl *RD = RT->getDecl();
    910   if (RD) {
    911     RD = RD->getDefinition();
    912   }
    913   if (!RD) {
    914     return false;
    915   }
    916 
    917   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    918          FE = RD->field_end();
    919        FI != FE;
    920        FI++) {
    921     // We just look through all field declarations to see if we find a
    922     // declaration for an RS object type (or an array of one).
    923     const clang::FieldDecl *FD = *FI;
    924     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    925     while (FT && FT->isArrayType()) {
    926       FT = FT->getArrayElementTypeNoTypeQual();
    927     }
    928 
    929     RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT);
    930     if (IsRSObjectType(DT)) {
    931       // RS object types definitely need to be zero-initialized
    932       RSObjectTypeSeen = true;
    933     } else {
    934       switch (DT) {
    935         case RSExportPrimitiveType::DataTypeRSMatrix2x2:
    936         case RSExportPrimitiveType::DataTypeRSMatrix3x3:
    937         case RSExportPrimitiveType::DataTypeRSMatrix4x4:
    938           // Matrix types should get zero-initialized as well
    939           RSObjectTypeSeen = true;
    940           break;
    941         default:
    942           // Ignore all other primitive types
    943           break;
    944       }
    945       while (FT && FT->isArrayType()) {
    946         FT = FT->getArrayElementTypeNoTypeQual();
    947       }
    948       if (FT->isStructureType()) {
    949         // Recursively handle structs of structs (even though these can't
    950         // be exported, it is possible for a user to have them internally).
    951         RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT);
    952       }
    953     }
    954   }
    955 
    956   return RSObjectTypeSeen;
    957 }
    958 
    959 const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = {
    960 #define ENUM_RS_DATA_TYPE(type, cname, bits)  \
    961   bits,
    962 #include "RSDataTypeEnums.inc"
    963   0   // DataTypeMax
    964 };
    965 
    966 size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
    967   slangAssert(((EPT->getType() > DataTypeUnknown) &&
    968                (EPT->getType() < DataTypeMax)) &&
    969               "RSExportPrimitiveType::GetSizeInBits : unknown data type");
    970   return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
    971 }
    972 
    973 RSExportPrimitiveType::DataType
    974 RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) {
    975   if (T == NULL)
    976     return DataTypeUnknown;
    977 
    978   switch (T->getTypeClass()) {
    979     case clang::Type::Builtin: {
    980       const clang::BuiltinType *BT =
    981         UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
    982       switch (BT->getKind()) {
    983 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
    984         case builtin_type: {                                  \
    985           return DataType ## type;                            \
    986         }
    987 #include "RSClangBuiltinEnums.inc"
    988         // The size of type WChar depend on platform so we abandon the support
    989         // to them.
    990         default: {
    991           clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
    992           DiagEngine->Report(
    993             DiagEngine->getCustomDiagID(
    994               clang::DiagnosticsEngine::Error,
    995               "built-in type cannot be exported: '%0'"))
    996             << T->getTypeClassName();
    997           break;
    998         }
    999       }
   1000       break;
   1001     }
   1002     case clang::Type::Record: {
   1003       // must be RS object type
   1004       return RSExportPrimitiveType::GetRSSpecificType(T);
   1005     }
   1006     default: {
   1007       clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
   1008       DiagEngine->Report(
   1009         DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
   1010                                     "primitive type cannot be exported: '%0'"))
   1011           << T->getTypeClassName();
   1012       break;
   1013     }
   1014   }
   1015 
   1016   return DataTypeUnknown;
   1017 }
   1018 
   1019 RSExportPrimitiveType
   1020 *RSExportPrimitiveType::Create(RSContext *Context,
   1021                                const clang::Type *T,
   1022                                const llvm::StringRef &TypeName,
   1023                                bool Normalized) {
   1024   DataType DT = GetDataType(Context, T);
   1025 
   1026   if ((DT == DataTypeUnknown) || TypeName.empty())
   1027     return NULL;
   1028   else
   1029     return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
   1030                                      DT, Normalized);
   1031 }
   1032 
   1033 RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
   1034                                                      const clang::Type *T) {
   1035   llvm::StringRef TypeName;
   1036   if (RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(), NULL)
   1037       && IsPrimitiveType(T)) {
   1038     return Create(Context, T, TypeName);
   1039   } else {
   1040     return NULL;
   1041   }
   1042 }
   1043 
   1044 llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
   1045   llvm::LLVMContext &C = getRSContext()->getLLVMContext();
   1046 
   1047   if (isRSObjectType()) {
   1048     // struct {
   1049     //   int *p;
   1050     // } __attribute__((packed, aligned(pointer_size)))
   1051     //
   1052     // which is
   1053     //
   1054     // <{ [1 x i32] }> in LLVM
   1055     //
   1056     if (RSObjectLLVMType == NULL) {
   1057       std::vector<llvm::Type *> Elements;
   1058       Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
   1059       RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
   1060     }
   1061     return RSObjectLLVMType;
   1062   }
   1063 
   1064   switch (mType) {
   1065     case DataTypeFloat32: {
   1066       return llvm::Type::getFloatTy(C);
   1067       break;
   1068     }
   1069     case DataTypeFloat64: {
   1070       return llvm::Type::getDoubleTy(C);
   1071       break;
   1072     }
   1073     case DataTypeBoolean: {
   1074       return llvm::Type::getInt1Ty(C);
   1075       break;
   1076     }
   1077     case DataTypeSigned8:
   1078     case DataTypeUnsigned8: {
   1079       return llvm::Type::getInt8Ty(C);
   1080       break;
   1081     }
   1082     case DataTypeSigned16:
   1083     case DataTypeUnsigned16:
   1084     case DataTypeUnsigned565:
   1085     case DataTypeUnsigned5551:
   1086     case DataTypeUnsigned4444: {
   1087       return llvm::Type::getInt16Ty(C);
   1088       break;
   1089     }
   1090     case DataTypeSigned32:
   1091     case DataTypeUnsigned32: {
   1092       return llvm::Type::getInt32Ty(C);
   1093       break;
   1094     }
   1095     case DataTypeSigned64:
   1096     case DataTypeUnsigned64: {
   1097       return llvm::Type::getInt64Ty(C);
   1098       break;
   1099     }
   1100     default: {
   1101       slangAssert(false && "Unknown data type");
   1102     }
   1103   }
   1104 
   1105   return NULL;
   1106 }
   1107 
   1108 union RSType *RSExportPrimitiveType::convertToSpecType() const {
   1109   llvm::OwningPtr<union RSType> ST(new union RSType);
   1110   RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
   1111   // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
   1112   // slang_rs_type_spec.h
   1113   RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
   1114   return ST.take();
   1115 }
   1116 
   1117 bool RSExportPrimitiveType::equals(const RSExportable *E) const {
   1118   CHECK_PARENT_EQUALITY(RSExportType, E);
   1119   return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
   1120 }
   1121 
   1122 RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) {
   1123   if (DT > DataTypeUnknown && DT < DataTypeMax) {
   1124     return &gReflectionTypes[DT];
   1125   } else {
   1126     return NULL;
   1127   }
   1128 }
   1129 
   1130 /**************************** RSExportPointerType ****************************/
   1131 
   1132 RSExportPointerType
   1133 *RSExportPointerType::Create(RSContext *Context,
   1134                              const clang::PointerType *PT,
   1135                              const llvm::StringRef &TypeName) {
   1136   const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
   1137   const RSExportType *PointeeET;
   1138 
   1139   if (PointeeType->getTypeClass() != clang::Type::Pointer) {
   1140     PointeeET = RSExportType::Create(Context, PointeeType);
   1141   } else {
   1142     // Double or higher dimension of pointer, export as int*
   1143     PointeeET = RSExportPrimitiveType::Create(Context,
   1144                     Context->getASTContext().IntTy.getTypePtr());
   1145   }
   1146 
   1147   if (PointeeET == NULL) {
   1148     // Error diagnostic is emitted for corresponding pointee type
   1149     return NULL;
   1150   }
   1151 
   1152   return new RSExportPointerType(Context, TypeName, PointeeET);
   1153 }
   1154 
   1155 llvm::Type *RSExportPointerType::convertToLLVMType() const {
   1156   llvm::Type *PointeeType = mPointeeType->getLLVMType();
   1157   return llvm::PointerType::getUnqual(PointeeType);
   1158 }
   1159 
   1160 union RSType *RSExportPointerType::convertToSpecType() const {
   1161   llvm::OwningPtr<union RSType> ST(new union RSType);
   1162 
   1163   RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
   1164   RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
   1165 
   1166   if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
   1167     return ST.take();
   1168   else
   1169     return NULL;
   1170 }
   1171 
   1172 bool RSExportPointerType::keep() {
   1173   if (!RSExportType::keep())
   1174     return false;
   1175   const_cast<RSExportType*>(mPointeeType)->keep();
   1176   return true;
   1177 }
   1178 
   1179 bool RSExportPointerType::equals(const RSExportable *E) const {
   1180   CHECK_PARENT_EQUALITY(RSExportType, E);
   1181   return (static_cast<const RSExportPointerType*>(E)
   1182               ->getPointeeType()->equals(getPointeeType()));
   1183 }
   1184 
   1185 /***************************** RSExportVectorType *****************************/
   1186 llvm::StringRef
   1187 RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
   1188   const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
   1189 
   1190   if ((ElementType->getTypeClass() != clang::Type::Builtin))
   1191     return llvm::StringRef();
   1192 
   1193   const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType,
   1194                                                   ElementType);
   1195   if ((EVT->getNumElements() < 1) ||
   1196       (EVT->getNumElements() > 4))
   1197     return llvm::StringRef();
   1198 
   1199   switch (BT->getKind()) {
   1200     // Compiler is smart enough to optimize following *big if branches* since
   1201     // they all become "constant comparison" after macro expansion
   1202 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
   1203     case builtin_type: {                                      \
   1204       const char *Name[] = { cname"2", cname"3", cname"4" };  \
   1205       return Name[EVT->getNumElements() - 2];                 \
   1206       break;                                                  \
   1207     }
   1208 #include "RSClangBuiltinEnums.inc"
   1209     default: {
   1210       return llvm::StringRef();
   1211     }
   1212   }
   1213 }
   1214 
   1215 RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
   1216                                                const clang::ExtVectorType *EVT,
   1217                                                const llvm::StringRef &TypeName,
   1218                                                bool Normalized) {
   1219   slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
   1220 
   1221   const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
   1222   RSExportPrimitiveType::DataType DT =
   1223       RSExportPrimitiveType::GetDataType(Context, ElementType);
   1224 
   1225   if (DT != RSExportPrimitiveType::DataTypeUnknown)
   1226     return new RSExportVectorType(Context,
   1227                                   TypeName,
   1228                                   DT,
   1229                                   Normalized,
   1230                                   EVT->getNumElements());
   1231   else
   1232     return NULL;
   1233 }
   1234 
   1235 llvm::Type *RSExportVectorType::convertToLLVMType() const {
   1236   llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
   1237   return llvm::VectorType::get(ElementType, getNumElement());
   1238 }
   1239 
   1240 union RSType *RSExportVectorType::convertToSpecType() const {
   1241   llvm::OwningPtr<union RSType> ST(new union RSType);
   1242 
   1243   RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
   1244   RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
   1245   RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
   1246 
   1247   return ST.take();
   1248 }
   1249 
   1250 bool RSExportVectorType::equals(const RSExportable *E) const {
   1251   CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
   1252   return (static_cast<const RSExportVectorType*>(E)->getNumElement()
   1253               == getNumElement());
   1254 }
   1255 
   1256 /***************************** RSExportMatrixType *****************************/
   1257 RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
   1258                                                const clang::RecordType *RT,
   1259                                                const llvm::StringRef &TypeName,
   1260                                                unsigned Dim) {
   1261   slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
   1262   slangAssert((Dim > 1) && "Invalid dimension of matrix");
   1263 
   1264   // Check whether the struct rs_matrix is in our expected form (but assume it's
   1265   // correct if we're not sure whether it's correct or not)
   1266   const clang::RecordDecl* RD = RT->getDecl();
   1267   RD = RD->getDefinition();
   1268   if (RD != NULL) {
   1269     clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
   1270     const clang::SourceManager *SM = Context->getSourceManager();
   1271     // Find definition, perform further examination
   1272     if (RD->field_empty()) {
   1273       DiagEngine->Report(
   1274         clang::FullSourceLoc(RD->getLocation(), *SM),
   1275         DiagEngine->getCustomDiagID(
   1276           clang::DiagnosticsEngine::Error,
   1277           "invalid matrix struct: must have 1 field for saving values: '%0'"))
   1278            << RD->getName();
   1279       return NULL;
   1280     }
   1281 
   1282     clang::RecordDecl::field_iterator FIT = RD->field_begin();
   1283     const clang::FieldDecl *FD = *FIT;
   1284     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
   1285     if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
   1286       DiagEngine->Report(
   1287         clang::FullSourceLoc(RD->getLocation(), *SM),
   1288         DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
   1289                                     "invalid matrix struct: first field should"
   1290                                     " be an array with constant size: '%0'"))
   1291         << RD->getName();
   1292       return NULL;
   1293     }
   1294     const clang::ConstantArrayType *CAT =
   1295       static_cast<const clang::ConstantArrayType *>(FT);
   1296     const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
   1297     if ((ElementType == NULL) ||
   1298         (ElementType->getTypeClass() != clang::Type::Builtin) ||
   1299         (static_cast<const clang::BuiltinType *>(ElementType)->getKind() !=
   1300          clang::BuiltinType::Float)) {
   1301       DiagEngine->Report(
   1302         clang::FullSourceLoc(RD->getLocation(), *SM),
   1303         DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
   1304                                     "invalid matrix struct: first field "
   1305                                     "should be a float array: '%0'"))
   1306         << RD->getName();
   1307       return NULL;
   1308     }
   1309 
   1310     if (CAT->getSize() != Dim * Dim) {
   1311       DiagEngine->Report(
   1312         clang::FullSourceLoc(RD->getLocation(), *SM),
   1313         DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
   1314                                     "invalid matrix struct: first field "
   1315                                     "should be an array with size %0: '%1'"))
   1316         << (Dim * Dim) << (RD->getName());
   1317       return NULL;
   1318     }
   1319 
   1320     FIT++;
   1321     if (FIT != RD->field_end()) {
   1322       DiagEngine->Report(
   1323         clang::FullSourceLoc(RD->getLocation(), *SM),
   1324         DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
   1325                                     "invalid matrix struct: must have "
   1326                                     "exactly 1 field: '%0'"))
   1327         << RD->getName();
   1328       return NULL;
   1329     }
   1330   }
   1331 
   1332   return new RSExportMatrixType(Context, TypeName, Dim);
   1333 }
   1334 
   1335 llvm::Type *RSExportMatrixType::convertToLLVMType() const {
   1336   // Construct LLVM type:
   1337   // struct {
   1338   //  float X[mDim * mDim];
   1339   // }
   1340 
   1341   llvm::LLVMContext &C = getRSContext()->getLLVMContext();
   1342   llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
   1343                                             mDim * mDim);
   1344   return llvm::StructType::get(C, X, false);
   1345 }
   1346 
   1347 union RSType *RSExportMatrixType::convertToSpecType() const {
   1348   llvm::OwningPtr<union RSType> ST(new union RSType);
   1349   RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
   1350   switch (getDim()) {
   1351     case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
   1352     case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
   1353     case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
   1354     default: slangAssert(false && "Matrix type with unsupported dimension.");
   1355   }
   1356   return ST.take();
   1357 }
   1358 
   1359 bool RSExportMatrixType::equals(const RSExportable *E) const {
   1360   CHECK_PARENT_EQUALITY(RSExportType, E);
   1361   return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
   1362 }
   1363 
   1364 /************************* RSExportConstantArrayType *************************/
   1365 RSExportConstantArrayType
   1366 *RSExportConstantArrayType::Create(RSContext *Context,
   1367                                    const clang::ConstantArrayType *CAT) {
   1368   slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
   1369 
   1370   slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large");
   1371 
   1372   unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
   1373   slangAssert((Size > 0) && "Constant array should have size greater than 0");
   1374 
   1375   const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
   1376   RSExportType *ElementET = RSExportType::Create(Context, ElementType);
   1377 
   1378   if (ElementET == NULL) {
   1379     return NULL;
   1380   }
   1381 
   1382   return new RSExportConstantArrayType(Context,
   1383                                        ElementET,
   1384                                        Size);
   1385 }
   1386 
   1387 llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
   1388   return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
   1389 }
   1390 
   1391 union RSType *RSExportConstantArrayType::convertToSpecType() const {
   1392   llvm::OwningPtr<union RSType> ST(new union RSType);
   1393 
   1394   RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
   1395   RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
   1396       ST, getElementType()->getSpecType());
   1397   RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
   1398 
   1399   if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
   1400     return ST.take();
   1401   else
   1402     return NULL;
   1403 }
   1404 
   1405 bool RSExportConstantArrayType::keep() {
   1406   if (!RSExportType::keep())
   1407     return false;
   1408   const_cast<RSExportType*>(mElementType)->keep();
   1409   return true;
   1410 }
   1411 
   1412 bool RSExportConstantArrayType::equals(const RSExportable *E) const {
   1413   CHECK_PARENT_EQUALITY(RSExportType, E);
   1414   const RSExportConstantArrayType *RHS =
   1415       static_cast<const RSExportConstantArrayType*>(E);
   1416   return ((getSize() == RHS->getSize()) &&
   1417           (getElementType()->equals(RHS->getElementType())));
   1418 }
   1419 
   1420 /**************************** RSExportRecordType ****************************/
   1421 RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
   1422                                                const clang::RecordType *RT,
   1423                                                const llvm::StringRef &TypeName,
   1424                                                bool mIsArtificial) {
   1425   slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
   1426 
   1427   const clang::RecordDecl *RD = RT->getDecl();
   1428   slangAssert(RD->isStruct());
   1429 
   1430   RD = RD->getDefinition();
   1431   if (RD == NULL) {
   1432     slangAssert(false && "struct is not defined in this module");
   1433     return NULL;
   1434   }
   1435 
   1436   // Struct layout construct by clang. We rely on this for obtaining the
   1437   // alloc size of a struct and offset of every field in that struct.
   1438   const clang::ASTRecordLayout *RL =
   1439       &Context->getASTContext().getASTRecordLayout(RD);
   1440   slangAssert((RL != NULL) &&
   1441       "Failed to retrieve the struct layout from Clang.");
   1442 
   1443   RSExportRecordType *ERT =
   1444       new RSExportRecordType(Context,
   1445                              TypeName,
   1446                              RD->hasAttr<clang::PackedAttr>(),
   1447                              mIsArtificial,
   1448                              RL->getSize().getQuantity());
   1449   unsigned int Index = 0;
   1450 
   1451   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
   1452            FE = RD->field_end();
   1453        FI != FE;
   1454        FI++, Index++) {
   1455     clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
   1456 
   1457     // FIXME: All fields should be primitive type
   1458     slangAssert(FI->getKind() == clang::Decl::Field);
   1459     clang::FieldDecl *FD = *FI;
   1460 
   1461     if (FD->isBitField()) {
   1462       return NULL;
   1463     }
   1464 
   1465     // Type
   1466     RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
   1467 
   1468     if (ET != NULL) {
   1469       ERT->mFields.push_back(
   1470           new Field(ET, FD->getName(), ERT,
   1471                     static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
   1472     } else {
   1473       DiagEngine->Report(
   1474         clang::FullSourceLoc(RD->getLocation(), DiagEngine->getSourceManager()),
   1475         DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
   1476                                     "field type cannot be exported: '%0.%1'"))
   1477         << RD->getName() << FD->getName();
   1478       return NULL;
   1479     }
   1480   }
   1481 
   1482   return ERT;
   1483 }
   1484 
   1485 llvm::Type *RSExportRecordType::convertToLLVMType() const {
   1486   // Create an opaque type since struct may reference itself recursively.
   1487 
   1488   // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to?
   1489   std::vector<llvm::Type*> FieldTypes;
   1490 
   1491   for (const_field_iterator FI = fields_begin(), FE = fields_end();
   1492        FI != FE;
   1493        FI++) {
   1494     const Field *F = *FI;
   1495     const RSExportType *FET = F->getType();
   1496 
   1497     FieldTypes.push_back(FET->getLLVMType());
   1498   }
   1499 
   1500   llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
   1501                                                FieldTypes,
   1502                                                mIsPacked);
   1503   if (ST != NULL) {
   1504     return ST;
   1505   } else {
   1506     return NULL;
   1507   }
   1508 }
   1509 
   1510 union RSType *RSExportRecordType::convertToSpecType() const {
   1511   unsigned NumFields = getFields().size();
   1512   unsigned AllocSize = sizeof(union RSType) +
   1513                        sizeof(struct RSRecordField) * NumFields;
   1514   llvm::OwningPtr<union RSType> ST(
   1515       reinterpret_cast<union RSType*>(operator new(AllocSize)));
   1516 
   1517   ::memset(ST.get(), 0, AllocSize);
   1518 
   1519   RS_TYPE_SET_CLASS(ST, RS_TC_Record);
   1520   RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
   1521   RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
   1522 
   1523   setSpecTypeTemporarily(ST.get());
   1524 
   1525   unsigned FieldIdx = 0;
   1526   for (const_field_iterator FI = fields_begin(), FE = fields_end();
   1527        FI != FE;
   1528        FI++, FieldIdx++) {
   1529     const Field *F = *FI;
   1530 
   1531     RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
   1532     RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
   1533   }
   1534 
   1535   // TODO(slang): Check whether all fields were created normally.
   1536 
   1537   return ST.take();
   1538 }
   1539 
   1540 bool RSExportRecordType::keep() {
   1541   if (!RSExportType::keep())
   1542     return false;
   1543   for (std::list<const Field*>::iterator I = mFields.begin(),
   1544           E = mFields.end();
   1545        I != E;
   1546        I++) {
   1547     const_cast<RSExportType*>((*I)->getType())->keep();
   1548   }
   1549   return true;
   1550 }
   1551 
   1552 bool RSExportRecordType::equals(const RSExportable *E) const {
   1553   CHECK_PARENT_EQUALITY(RSExportType, E);
   1554 
   1555   const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
   1556 
   1557   if (ERT->getFields().size() != getFields().size())
   1558     return false;
   1559 
   1560   const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
   1561 
   1562   for (unsigned i = 0, e = getFields().size(); i != e; i++) {
   1563     if (!(*AI)->getType()->equals((*BI)->getType()))
   1564       return false;
   1565     AI++;
   1566     BI++;
   1567   }
   1568 
   1569   return true;
   1570 }
   1571 
   1572 void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
   1573     memset(rtd, 0, sizeof(*rtd));
   1574     rtd->vecSize = 1;
   1575 
   1576     switch(getClass()) {
   1577     case RSExportType::ExportClassPrimitive: {
   1578             const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
   1579             rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
   1580             return;
   1581         }
   1582     case RSExportType::ExportClassPointer: {
   1583             const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
   1584             const RSExportType *PointeeType = EPT->getPointeeType();
   1585             PointeeType->convertToRTD(rtd);
   1586             rtd->isPointer = true;
   1587             return;
   1588         }
   1589     case RSExportType::ExportClassVector: {
   1590             const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
   1591             rtd->type = EVT->getRSReflectionType(EVT);
   1592             rtd->vecSize = EVT->getNumElement();
   1593             return;
   1594         }
   1595     case RSExportType::ExportClassMatrix: {
   1596             const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
   1597             unsigned Dim = EMT->getDim();
   1598             slangAssert((Dim >= 2) && (Dim <= 4));
   1599             rtd->type = &gReflectionTypes[15 + Dim-2];
   1600             return;
   1601         }
   1602     case RSExportType::ExportClassConstantArray: {
   1603             const RSExportConstantArrayType* CAT =
   1604               static_cast<const RSExportConstantArrayType*>(this);
   1605             CAT->getElementType()->convertToRTD(rtd);
   1606             rtd->arraySize = CAT->getSize();
   1607             return;
   1608         }
   1609     case RSExportType::ExportClassRecord: {
   1610             slangAssert(!"RSExportType::ExportClassRecord not implemented");
   1611             return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
   1612         }
   1613     default: {
   1614             slangAssert(false && "Unknown class of type");
   1615         }
   1616     }
   1617 }
   1618 
   1619 
   1620 }  // namespace slang
   1621