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