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