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 #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_  // NOLINT
     18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_
     19 
     20 #include <list>
     21 #include <set>
     22 #include <string>
     23 #include <sstream>
     24 
     25 #include "clang/AST/Decl.h"
     26 #include "clang/AST/Type.h"
     27 
     28 #include "llvm/ADT/SmallPtrSet.h"
     29 #include "llvm/ADT/StringMap.h"
     30 #include "llvm/ADT/StringRef.h"
     31 
     32 #include "llvm/Support/ManagedStatic.h"
     33 
     34 #include "slang_rs_exportable.h"
     35 
     36 
     37 inline const clang::Type* GetCanonicalType(const clang::Type* T) {
     38   if (T == NULL) {
     39     return  NULL;
     40   }
     41   return T->getCanonicalTypeInternal().getTypePtr();
     42 }
     43 
     44 inline const clang::Type* GetCanonicalType(clang::QualType QT) {
     45   return GetCanonicalType(QT.getTypePtr());
     46 }
     47 
     48 inline const clang::Type* GetExtVectorElementType(const clang::ExtVectorType *T) {
     49   if (T == NULL) {
     50     return NULL;
     51   }
     52   return GetCanonicalType(T->getElementType());
     53 }
     54 
     55 inline const clang::Type* GetPointeeType(const clang::PointerType *T) {
     56   if (T == NULL) {
     57     return NULL;
     58   }
     59   return GetCanonicalType(T->getPointeeType());
     60 }
     61 
     62 inline const clang::Type* GetConstantArrayElementType(const clang::ConstantArrayType *T) {
     63   if (T == NULL) {
     64     return NULL;
     65   }
     66   return GetCanonicalType(T->getElementType());
     67 }
     68 
     69 
     70 namespace llvm {
     71   class Type;
     72 }   // namespace llvm
     73 
     74 namespace slang {
     75 
     76 class RSContext;
     77 
     78 // Broad grouping of the data types
     79 enum DataTypeCategory {
     80     PrimitiveDataType,
     81     MatrixDataType,
     82     ObjectDataType
     83 };
     84 
     85 // From graphics/java/android/renderscript/Element.java: Element.DataType
     86 /* NOTE: The values of the enums are found compiled in the bit code (i.e. as
     87  * values, not symbolic.  When adding new types, you must add them to the end.
     88  * If removing types, you can't re-use the integer value.
     89  *
     90  * TODO: but if you do this, you won't be able to keep using First* & Last*
     91  * for validation.
     92  *
     93  * IMPORTANT: This enum should correspond one-for-one to the entries found in the
     94  * gReflectionsTypes table (except for the two negative numbers).  Don't edit one without
     95  * the other.
     96  */
     97 enum DataType {
     98     DataTypeIsStruct = -2,
     99     DataTypeUnknown = -1,
    100 
    101     DataTypeFloat16 = 0,
    102     DataTypeFloat32 = 1,
    103     DataTypeFloat64 = 2,
    104     DataTypeSigned8 = 3,
    105     DataTypeSigned16 = 4,
    106     DataTypeSigned32 = 5,
    107     DataTypeSigned64 = 6,
    108     DataTypeUnsigned8 = 7,
    109     DataTypeUnsigned16 = 8,
    110     DataTypeUnsigned32 = 9,
    111     DataTypeUnsigned64 = 10,
    112     DataTypeBoolean = 11,
    113     DataTypeUnsigned565 = 12,
    114     DataTypeUnsigned5551 = 13,
    115     DataTypeUnsigned4444 = 14,
    116 
    117     DataTypeRSMatrix2x2 = 15,
    118     DataTypeRSMatrix3x3 = 16,
    119     DataTypeRSMatrix4x4 = 17,
    120 
    121     DataTypeRSElement = 18,
    122     DataTypeRSType = 19,
    123     DataTypeRSAllocation = 20,
    124     DataTypeRSSampler = 21,
    125     DataTypeRSScript = 22,
    126     DataTypeRSMesh = 23,
    127     DataTypeRSPath = 24,
    128     DataTypeRSProgramFragment = 25,
    129     DataTypeRSProgramVertex = 26,
    130     DataTypeRSProgramRaster = 27,
    131     DataTypeRSProgramStore = 28,
    132     DataTypeRSFont = 29,
    133 
    134     // This should always be last and correspond to the size of the gReflectionTypes table.
    135     DataTypeMax
    136 };
    137 
    138 typedef struct {
    139     DataTypeCategory category;
    140     const char * rs_type;
    141     const char * rs_short_type;
    142     uint32_t size_in_bits;
    143     const char * c_name;
    144     const char * java_name;
    145     const char * rs_c_vector_prefix;
    146     const char * rs_java_vector_prefix;
    147     bool java_promotion;
    148 } RSReflectionType;
    149 
    150 
    151 typedef struct RSReflectionTypeData_rec {
    152     const RSReflectionType *type;
    153     uint32_t vecSize;
    154     bool isPointer;
    155     uint32_t arraySize;
    156 
    157     // Subelements
    158     //std::vector<const struct RSReflectionTypeData_rec *> fields;
    159     //std::vector< std::string > fieldNames;
    160     //std::vector< uint32_t> fieldOffsetBytes;
    161 } RSReflectionTypeData;
    162 
    163 // Make a name for types that are too complicated to create the real names.
    164 std::string CreateDummyName(const char *type, const std::string &name);
    165 
    166 inline bool IsDummyName(const llvm::StringRef &Name) {
    167   return Name.startswith("<");
    168 }
    169 
    170 class RSExportType : public RSExportable {
    171   friend class RSExportElement;
    172  public:
    173   typedef enum {
    174     ExportClassPrimitive,
    175     ExportClassPointer,
    176     ExportClassVector,
    177     ExportClassMatrix,
    178     ExportClassConstantArray,
    179     ExportClassRecord
    180   } ExportClass;
    181 
    182   void convertToRTD(RSReflectionTypeData *rtd) const;
    183 
    184  private:
    185   ExportClass mClass;
    186   std::string mName;
    187 
    188   // Cache the result after calling convertToLLVMType() at the first time
    189   mutable llvm::Type *mLLVMType;
    190 
    191  protected:
    192   RSExportType(RSContext *Context,
    193                ExportClass Class,
    194                const llvm::StringRef &Name);
    195 
    196   // Let's make it private since there're some prerequisites to call this
    197   // function.
    198   //
    199   // @T was normalized by calling RSExportType::NormalizeType().
    200   // @TypeName was retrieve from RSExportType::GetTypeName() before calling
    201   //           this.
    202   //
    203   static RSExportType *Create(RSContext *Context,
    204                               const clang::Type *T,
    205                               const llvm::StringRef &TypeName);
    206 
    207   static llvm::StringRef GetTypeName(const clang::Type *T);
    208 
    209   // This function convert the RSExportType to LLVM type. Actually, it should be
    210   // "convert Clang type to LLVM type." However, clang doesn't make this API
    211   // (lib/CodeGen/CodeGenTypes.h) public, we need to do by ourselves.
    212   //
    213   // Once we can get LLVM type, we can use LLVM to get alignment information,
    214   // allocation size of a given type and structure layout that LLVM used
    215   // (all of these information are target dependent) without dealing with these
    216   // by ourselves.
    217   virtual llvm::Type *convertToLLVMType() const = 0;
    218   // Record type may recursively reference its type definition. We need a
    219   // temporary type setup before the type construction gets done.
    220   inline void setAbstractLLVMType(llvm::Type *LLVMType) const {
    221     mLLVMType = LLVMType;
    222   }
    223 
    224   virtual ~RSExportType();
    225 
    226  public:
    227   // This function additionally verifies that the Type T is exportable.
    228   // If it is not, this function returns false. Otherwise it returns true.
    229   static bool NormalizeType(const clang::Type *&T,
    230                             llvm::StringRef &TypeName,
    231                             RSContext *Context,
    232                             const clang::VarDecl *VD);
    233 
    234   // This function checks whether the specified type can be handled by RS/FS.
    235   // If it cannot, this function returns false. Otherwise it returns true.
    236   // Filterscript has additional restrictions on supported types.
    237   static bool ValidateType(slang::RSContext *Context, clang::ASTContext &C,
    238                            clang::QualType QT, clang::NamedDecl *ND,
    239                            clang::SourceLocation Loc, unsigned int TargetAPI,
    240                            bool IsFilterscript);
    241 
    242   // This function ensures that the VarDecl can be properly handled by RS.
    243   // If it cannot, this function returns false. Otherwise it returns true.
    244   // Filterscript has additional restrictions on supported types.
    245   static bool ValidateVarDecl(slang::RSContext *Context, clang::VarDecl *VD,
    246                               unsigned int TargetAPI, bool IsFilterscript);
    247 
    248   // @T may not be normalized
    249   static RSExportType *Create(RSContext *Context, const clang::Type *T);
    250   static RSExportType *CreateFromDecl(RSContext *Context,
    251                                       const clang::VarDecl *VD);
    252 
    253   static const clang::Type *GetTypeOfDecl(const clang::DeclaratorDecl *DD);
    254 
    255   inline ExportClass getClass() const { return mClass; }
    256 
    257   virtual unsigned getSize() const { return 1; }
    258 
    259   inline llvm::Type *getLLVMType() const {
    260     if (mLLVMType == NULL)
    261       mLLVMType = convertToLLVMType();
    262     return mLLVMType;
    263   }
    264 
    265   // Return the maximum number of bytes that may be written when this type is stored.
    266   virtual size_t getStoreSize() const;
    267 
    268   // Return the distance in bytes between successive elements of this type; it includes padding.
    269   virtual size_t getAllocSize() const;
    270 
    271   inline const std::string &getName() const { return mName; }
    272 
    273   virtual std::string getElementName() const {
    274     // Base case is actually an invalid C/Java identifier.
    275     return "@@INVALID@@";
    276   }
    277 
    278   virtual bool keep();
    279   virtual bool equals(const RSExportable *E) const;
    280 };  // RSExportType
    281 
    282 // Primitive types
    283 class RSExportPrimitiveType : public RSExportType {
    284   friend class RSExportType;
    285   friend class RSExportElement;
    286  private:
    287   DataType mType;
    288   bool mNormalized;
    289 
    290   typedef llvm::StringMap<DataType> RSSpecificTypeMapTy;
    291   static llvm::ManagedStatic<RSSpecificTypeMapTy> RSSpecificTypeMap;
    292 
    293   static const size_t SizeOfDataTypeInBits[];
    294   // @T was normalized by calling RSExportType::NormalizeType() before calling
    295   // this.
    296   // @TypeName was retrieved from RSExportType::GetTypeName() before calling
    297   // this
    298   static RSExportPrimitiveType *Create(RSContext *Context,
    299                                        const clang::Type *T,
    300                                        const llvm::StringRef &TypeName,
    301                                        bool Normalized = false);
    302 
    303  protected:
    304   RSExportPrimitiveType(RSContext *Context,
    305                         // for derived class to set their type class
    306                         ExportClass Class,
    307                         const llvm::StringRef &Name,
    308                         DataType DT,
    309                         bool Normalized)
    310       : RSExportType(Context, Class, Name),
    311         mType(DT),
    312         mNormalized(Normalized) {
    313   }
    314 
    315   virtual llvm::Type *convertToLLVMType() const;
    316 
    317   static DataType GetDataType(RSContext *Context, const clang::Type *T);
    318 
    319  public:
    320   // T is normalized by calling RSExportType::NormalizeType() before
    321   // calling this
    322   static bool IsPrimitiveType(const clang::Type *T);
    323 
    324   // @T may not be normalized
    325   static RSExportPrimitiveType *Create(RSContext *Context,
    326                                        const clang::Type *T);
    327 
    328   static DataType GetRSSpecificType(const llvm::StringRef &TypeName);
    329   static DataType GetRSSpecificType(const clang::Type *T);
    330 
    331   static bool IsRSMatrixType(DataType DT);
    332   static bool IsRSObjectType(DataType DT);
    333   static bool IsRSObjectType(const clang::Type *T) {
    334     return IsRSObjectType(GetRSSpecificType(T));
    335   }
    336 
    337   // Determines whether T is [an array of] struct that contains at least one
    338   // RS object type within it.
    339   static bool IsStructureTypeWithRSObject(const clang::Type *T);
    340 
    341   static size_t GetSizeInBits(const RSExportPrimitiveType *EPT);
    342 
    343   inline DataType getType() const { return mType; }
    344   inline bool isRSObjectType() const {
    345       return IsRSObjectType(mType);
    346   }
    347 
    348   virtual bool equals(const RSExportable *E) const;
    349 
    350   static RSReflectionType *getRSReflectionType(DataType DT);
    351   static RSReflectionType *getRSReflectionType(
    352       const RSExportPrimitiveType *EPT) {
    353     return getRSReflectionType(EPT->getType());
    354   }
    355 
    356   virtual unsigned getSize() const { return (GetSizeInBits(this) >> 3); }
    357 
    358   std::string getElementName() const {
    359     return getRSReflectionType(this)->rs_short_type;
    360   }
    361 };  // RSExportPrimitiveType
    362 
    363 
    364 class RSExportPointerType : public RSExportType {
    365   friend class RSExportType;
    366   friend class RSExportFunc;
    367  private:
    368   const RSExportType *mPointeeType;
    369 
    370   RSExportPointerType(RSContext *Context,
    371                       const llvm::StringRef &Name,
    372                       const RSExportType *PointeeType)
    373       : RSExportType(Context, ExportClassPointer, Name),
    374         mPointeeType(PointeeType) {
    375   }
    376 
    377   // @PT was normalized by calling RSExportType::NormalizeType() before calling
    378   // this.
    379   static RSExportPointerType *Create(RSContext *Context,
    380                                      const clang::PointerType *PT,
    381                                      const llvm::StringRef &TypeName);
    382 
    383   virtual llvm::Type *convertToLLVMType() const;
    384 
    385  public:
    386   virtual bool keep();
    387 
    388   inline const RSExportType *getPointeeType() const { return mPointeeType; }
    389 
    390   virtual bool equals(const RSExportable *E) const;
    391 };  // RSExportPointerType
    392 
    393 
    394 class RSExportVectorType : public RSExportPrimitiveType {
    395   friend class RSExportType;
    396   friend class RSExportElement;
    397  private:
    398   unsigned mNumElement;   // number of element
    399 
    400   RSExportVectorType(RSContext *Context,
    401                      const llvm::StringRef &Name,
    402                      DataType DT,
    403                      bool Normalized,
    404                      unsigned NumElement)
    405       : RSExportPrimitiveType(Context, ExportClassVector, Name,
    406                               DT, Normalized),
    407         mNumElement(NumElement) {
    408   }
    409 
    410   // @EVT was normalized by calling RSExportType::NormalizeType() before
    411   // calling this.
    412   static RSExportVectorType *Create(RSContext *Context,
    413                                     const clang::ExtVectorType *EVT,
    414                                     const llvm::StringRef &TypeName,
    415                                     bool Normalized = false);
    416 
    417   virtual llvm::Type *convertToLLVMType() const;
    418 
    419  public:
    420   static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT);
    421 
    422   inline unsigned getNumElement() const { return mNumElement; }
    423 
    424   std::string getElementName() const {
    425     std::stringstream Name;
    426     Name << RSExportPrimitiveType::getRSReflectionType(this)->rs_short_type
    427          << "_" << getNumElement();
    428     return Name.str();
    429   }
    430 
    431   virtual bool equals(const RSExportable *E) const;
    432 };
    433 
    434 // Only *square* *float* matrix is supported by now.
    435 //
    436 // struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following
    437 // form *exactly*:
    438 //  typedef struct {
    439 //    float m[{NxN}];
    440 //  } rs_matrixNxN;
    441 //
    442 //  where mDim will be N.
    443 class RSExportMatrixType : public RSExportType {
    444   friend class RSExportType;
    445  private:
    446   unsigned mDim;  // dimension
    447 
    448   RSExportMatrixType(RSContext *Context,
    449                      const llvm::StringRef &Name,
    450                      unsigned Dim)
    451     : RSExportType(Context, ExportClassMatrix, Name),
    452       mDim(Dim) {
    453   }
    454 
    455   virtual llvm::Type *convertToLLVMType() const;
    456 
    457  public:
    458   // @RT was normalized by calling RSExportType::NormalizeType() before
    459   // calling this.
    460   static RSExportMatrixType *Create(RSContext *Context,
    461                                     const clang::RecordType *RT,
    462                                     const llvm::StringRef &TypeName,
    463                                     unsigned Dim);
    464 
    465   inline unsigned getDim() const { return mDim; }
    466 
    467   virtual bool equals(const RSExportable *E) const;
    468 };
    469 
    470 class RSExportConstantArrayType : public RSExportType {
    471   friend class RSExportType;
    472  private:
    473   const RSExportType *mElementType;  // Array element type
    474   unsigned mSize;  // Array size
    475 
    476   RSExportConstantArrayType(RSContext *Context,
    477                             const RSExportType *ElementType,
    478                             unsigned Size)
    479     : RSExportType(Context, ExportClassConstantArray, "<ConstantArray>"),
    480       mElementType(ElementType),
    481       mSize(Size) {
    482   }
    483 
    484   // @CAT was normalized by calling RSExportType::NormalizeType() before
    485   // calling this.
    486   static RSExportConstantArrayType *Create(RSContext *Context,
    487                                            const clang::ConstantArrayType *CAT);
    488 
    489   virtual llvm::Type *convertToLLVMType() const;
    490 
    491  public:
    492   virtual unsigned getSize() const { return mSize; }
    493   inline const RSExportType *getElementType() const { return mElementType; }
    494 
    495   std::string getElementName() const {
    496     return mElementType->getElementName();
    497   }
    498 
    499   virtual bool keep();
    500   virtual bool equals(const RSExportable *E) const;
    501 };
    502 
    503 class RSExportRecordType : public RSExportType {
    504   friend class RSExportType;
    505  public:
    506   class Field {
    507    private:
    508     const RSExportType *mType;
    509     // Field name
    510     std::string mName;
    511     // Link to the struct that contain this field
    512     const RSExportRecordType *mParent;
    513     // Offset in the container
    514     size_t mOffset;
    515 
    516    public:
    517     Field(const RSExportType *T,
    518           const llvm::StringRef &Name,
    519           const RSExportRecordType *Parent,
    520           size_t Offset)
    521         : mType(T),
    522           mName(Name.data(), Name.size()),
    523           mParent(Parent),
    524           mOffset(Offset) {
    525     }
    526 
    527     inline const RSExportRecordType *getParent() const { return mParent; }
    528     inline const RSExportType *getType() const { return mType; }
    529     inline const std::string &getName() const { return mName; }
    530     inline size_t getOffsetInParent() const { return mOffset; }
    531   };
    532 
    533   typedef std::list<const Field*>::const_iterator const_field_iterator;
    534 
    535   inline const_field_iterator fields_begin() const {
    536     return this->mFields.begin();
    537   }
    538   inline const_field_iterator fields_end() const {
    539     return this->mFields.end();
    540   }
    541 
    542  private:
    543   std::list<const Field*> mFields;
    544   bool mIsPacked;
    545   // Artificial export struct type is not exported by user (and thus it won't
    546   // get reflected)
    547   bool mIsArtificial;
    548   size_t mStoreSize;
    549   size_t mAllocSize;
    550 
    551   RSExportRecordType(RSContext *Context,
    552                      const llvm::StringRef &Name,
    553                      bool IsPacked,
    554                      bool IsArtificial,
    555                      size_t StoreSize,
    556                      size_t AllocSize)
    557       : RSExportType(Context, ExportClassRecord, Name),
    558         mIsPacked(IsPacked),
    559         mIsArtificial(IsArtificial),
    560         mStoreSize(StoreSize),
    561         mAllocSize(AllocSize) {
    562   }
    563 
    564   // @RT was normalized by calling RSExportType::NormalizeType() before calling
    565   // this.
    566   // @TypeName was retrieved from RSExportType::GetTypeName() before calling
    567   // this.
    568   static RSExportRecordType *Create(RSContext *Context,
    569                                     const clang::RecordType *RT,
    570                                     const llvm::StringRef &TypeName,
    571                                     bool mIsArtificial = false);
    572 
    573   virtual llvm::Type *convertToLLVMType() const;
    574 
    575  public:
    576   inline const std::list<const Field*>& getFields() const { return mFields; }
    577   inline bool isPacked() const { return mIsPacked; }
    578   inline bool isArtificial() const { return mIsArtificial; }
    579   virtual size_t getStoreSize() const { return mStoreSize; }
    580   virtual size_t getAllocSize() const { return mAllocSize; }
    581 
    582   virtual std::string getElementName() const {
    583     return "ScriptField_" + getName();
    584   }
    585 
    586   virtual bool keep();
    587   virtual bool equals(const RSExportable *E) const;
    588 
    589   ~RSExportRecordType() {
    590     for (std::list<const Field*>::iterator I = mFields.begin(),
    591              E = mFields.end();
    592          I != E;
    593          I++)
    594       if (*I != NULL)
    595         delete *I;
    596   }
    597 };  // RSExportRecordType
    598 
    599 }   // namespace slang
    600 
    601 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_  NOLINT
    602