slang_rs_export_type.h revision a5d2c232d56b04292cb51c8fb343aef990f7970f
1#ifndef _SLANG_COMPILER_RS_EXPORT_TYPE_H
2#define _SLANG_COMPILER_RS_EXPORT_TYPE_H
3
4#include <set>
5#include <list>
6#include <string>
7
8#include "llvm/Support/ManagedStatic.h"
9
10#include "llvm/ADT/StringRef.h"
11#include "llvm/ADT/StringMap.h"
12#include "llvm/ADT/SmallPtrSet.h"
13
14#include "clang/AST/Type.h"
15#include "clang/AST/Decl.h"
16
17#include "slang_rs_exportable.h"
18
19#define GET_CANONICAL_TYPE(T) \
20    (((T) == NULL) ? NULL : (T)->getCanonicalTypeInternal().getTypePtr())
21#define UNSAFE_CAST_TYPE(TT, T) \
22    static_cast<TT*>(T->getCanonicalTypeInternal().getTypePtr())
23#define GET_EXT_VECTOR_ELEMENT_TYPE(T) \
24    (((T) == NULL) ? NULL : \
25                     GET_CANONICAL_TYPE((T)->getElementType().getTypePtr()))
26#define GET_POINTEE_TYPE(T) \
27    (((T) == NULL) ? NULL : \
28                     GET_CANONICAL_TYPE((T)->getPointeeType().getTypePtr()))
29#define GET_CONSTANT_ARRAY_ELEMENT_TYPE(T)  \
30    (((T) == NULL) ? NULL : \
31                     GET_CANONICAL_TYPE((T)->getElementType().getTypePtr()))
32#define DUMMY_RS_TYPE_NAME_PREFIX   "<"
33#define DUMMY_RS_TYPE_NAME_POSTFIX  ">"
34#define DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE  \
35    DUMMY_RS_TYPE_NAME_PREFIX"ConstantArray"DUMMY_RS_TYPE_NAME_POSTFIX
36
37namespace llvm {
38  class Type;
39}   // namespace llvm
40
41namespace slang {
42
43  class RSContext;
44
45class RSExportType : public RSExportable {
46  friend class RSExportElement;
47 public:
48  typedef enum {
49    ExportClassPrimitive,
50    ExportClassPointer,
51    ExportClassVector,
52    ExportClassMatrix,
53    ExportClassConstantArray,
54    ExportClassRecord
55  } ExportClass;
56
57 private:
58  RSContext *mContext;
59  ExportClass mClass;
60  std::string mName;
61
62  // Cache the result after calling convertToLLVMType() at the first time
63  mutable const llvm::Type *mLLVMType;
64
65 protected:
66  RSExportType(RSContext *Context,
67               ExportClass Class,
68               const llvm::StringRef &Name);
69
70  // Let's make it private since there're some prerequisites to call this
71  // function.
72  //
73  // @T was normalized by calling RSExportType::TypeExportable().
74  // @TypeName was retrieve from RSExportType::GetTypeName() before calling
75  //           this.
76  //
77  static RSExportType *Create(RSContext *Context,
78                              const clang::Type *T,
79                              const llvm::StringRef &TypeName);
80
81  static llvm::StringRef GetTypeName(const clang::Type *T);
82  // Return the type that can be used to create RSExportType, will always return
83  // the canonical type
84  static const clang::Type
85  *TypeExportable(const clang::Type *T,
86                  // Contain the checked type for recursion
87                  llvm::SmallPtrSet<const clang::Type*, 8> &SPS);
88
89  // This function convert the RSExportType to LLVM type. Actually, it should be
90  // "convert Clang type to LLVM type." However, clang doesn't make this API
91  // (lib/CodeGen/CodeGenTypes.h) public, we need to do by ourselves.
92  //
93  // Once we can get LLVM type, we can use LLVM to get alignment information,
94  // allocation size of a given type and structure layout that LLVM used
95  // (all of these information are target dependent) without dealing with these
96  // by ourselves.
97  virtual const llvm::Type *convertToLLVMType() const = 0;
98
99  virtual ~RSExportType() {}
100 public:
101  static bool NormalizeType(const clang::Type *&T, llvm::StringRef &TypeName);
102  // @T may not be normalized
103  static RSExportType *Create(RSContext *Context, const clang::Type *T);
104  static RSExportType *CreateFromDecl(RSContext *Context,
105                                      const clang::VarDecl *VD);
106
107  static const clang::Type *GetTypeOfDecl(const clang::DeclaratorDecl *DD);
108
109  inline ExportClass getClass() const { return mClass; }
110
111  inline const llvm::Type *getLLVMType() const {
112    if (mLLVMType == NULL)
113      mLLVMType = convertToLLVMType();
114    return mLLVMType;
115  }
116
117  // Return the number of bits necessary to hold the specified RSExportType
118  static size_t GetTypeStoreSize(const RSExportType *ET);
119
120  // The size of allocation of specified RSExportType (alignment considered)
121  static size_t GetTypeAllocSize(const RSExportType *ET);
122  static unsigned char GetTypeAlignment(const RSExportType *ET);
123
124  const std::string &getName() const { return mName; }
125  inline RSContext *getRSContext() const { return mContext; }
126};  // RSExportType
127
128// Primitive types
129class RSExportPrimitiveType : public RSExportType {
130  friend class RSExportType;
131  friend class RSExportElement;
132 public:
133  // From graphics/java/android/renderscript/Element.java: Element.DataType
134  typedef enum {
135    DataTypeUnknown = -1,
136
137    DataTypeFloat16 = 0,
138    DataTypeFloat32,
139    DataTypeFloat64,
140    DataTypeSigned8,
141    DataTypeSigned16,
142    DataTypeSigned32,
143    DataTypeSigned64,
144    DataTypeUnsigned8,
145    DataTypeUnsigned16,
146    DataTypeUnsigned32,
147    DataTypeUnsigned64,
148
149    DataTypeBoolean,
150
151    DataTypeUnsigned565,
152    DataTypeUnsigned5551,
153    DataTypeUnsigned4444,
154
155    // Actually, there's no any instance of RSExportPrimitiveType which mType
156    // is of the value DataTypeRSMatrix*. DataTypeRSMatrix* enumeration here is
157    // only for RSExportPrimitiveType::GetRSObjectType to *recognize* the struct
158    // rs_matrix{2x2, 3x3, 4x4}. These matrix type are represented as
159    // RSExportMatrixType.
160    DataTypeRSMatrix2x2,
161    DataTypeRSMatrix3x3,
162    DataTypeRSMatrix4x4,
163
164    DataTypeRSElement,
165    DataTypeRSType,
166    DataTypeRSAllocation,
167    DataTypeRSSampler,
168    DataTypeRSScript,
169    DataTypeRSMesh,
170    DataTypeRSProgramFragment,
171    DataTypeRSProgramVertex,
172    DataTypeRSProgramRaster,
173    DataTypeRSProgramStore,
174    DataTypeRSFont,
175
176    DataTypeMax
177  } DataType;
178
179  // From graphics/java/android/renderscript/Element.java: Element.DataKind
180  typedef enum {
181    DataKindUser,
182    DataKindPixelL,
183    DataKindPixelA,
184    DataKindPixelLA,
185    DataKindPixelRGB,
186    DataKindPixelRGBA
187  } DataKind;
188
189 private:
190  DataType mType;
191  DataKind mKind;
192  bool mNormalized;
193
194  typedef llvm::StringMap<DataType> RSObjectTypeMapTy;
195  static llvm::ManagedStatic<RSObjectTypeMapTy> RSObjectTypeMap;
196
197  static llvm::Type *RSObjectLLVMType;
198
199  static const size_t SizeOfDataTypeInBits[];
200  // @T was normalized by calling RSExportType::TypeExportable() before calling
201  // this.
202  // @TypeName was retrieved from RSExportType::GetTypeName() before calling
203  // this
204  static RSExportPrimitiveType *Create(RSContext *Context,
205                                       const clang::Type *T,
206                                       const llvm::StringRef &TypeName,
207                                       DataKind DK = DataKindUser,
208                                       bool Normalized = false);
209
210 protected:
211  // T is normalized by calling RSExportType::TypeExportable() before
212  // calling this
213  static bool IsPrimitiveType(const clang::Type *T);
214
215  static DataType GetDataType(const clang::Type *T);
216
217  RSExportPrimitiveType(RSContext *Context,
218                        // for derived class to set their type class
219                        ExportClass Class,
220                        const llvm::StringRef &Name,
221                        DataType DT,
222                        DataKind DK,
223                        bool Normalized)
224      : RSExportType(Context, Class, Name),
225        mType(DT),
226        mKind(DK),
227        mNormalized(Normalized) {
228    return;
229  }
230
231  virtual const llvm::Type *convertToLLVMType() const;
232 public:
233  // @T may not be normalized
234  static RSExportPrimitiveType *Create(RSContext *Context,
235                                       const clang::Type *T,
236                                       DataKind DK = DataKindUser);
237
238  static DataType GetRSObjectType(const llvm::StringRef &TypeName);
239  static DataType GetRSObjectType(const clang::Type *T);
240
241  static size_t GetSizeInBits(const RSExportPrimitiveType *EPT);
242
243  inline DataType getType() const { return mType; }
244  inline DataKind getKind() const { return mKind; }
245  inline bool isRSObjectType() const {
246    return ((mType >= DataTypeRSElement) && (mType < DataTypeMax));
247  }
248};  // RSExportPrimitiveType
249
250
251class RSExportPointerType : public RSExportType {
252  friend class RSExportType;
253  friend class RSExportFunc;
254 private:
255  const RSExportType *mPointeeType;
256
257  RSExportPointerType(RSContext *Context,
258                      const llvm::StringRef &Name,
259                      const RSExportType *PointeeType)
260      : RSExportType(Context, ExportClassPointer, Name),
261        mPointeeType(PointeeType) {
262    return;
263  }
264
265  // @PT was normalized by calling RSExportType::TypeExportable() before calling
266  // this.
267  static RSExportPointerType *Create(RSContext *Context,
268                                     const clang::PointerType *PT,
269                                     const llvm::StringRef &TypeName);
270
271  virtual const llvm::Type *convertToLLVMType() const;
272 public:
273  static const clang::Type *IntegerType;
274
275  inline const RSExportType *getPointeeType() const { return mPointeeType; }
276};  // RSExportPointerType
277
278
279class RSExportVectorType : public RSExportPrimitiveType {
280  friend class RSExportType;
281  friend class RSExportElement;
282 private:
283  unsigned mNumElement;   // number of element
284
285  RSExportVectorType(RSContext *Context,
286                     const llvm::StringRef &Name,
287                     DataType DT,
288                     DataKind DK,
289                     bool Normalized,
290                     unsigned NumElement)
291      : RSExportPrimitiveType(Context, ExportClassVector, Name,
292                              DT, DK, Normalized),
293        mNumElement(NumElement) {
294    return;
295  }
296
297  // @EVT was normalized by calling RSExportType::TypeExportable() before
298  // calling this.
299  static RSExportVectorType *Create(RSContext *Context,
300                                    const clang::ExtVectorType *EVT,
301                                    const llvm::StringRef &TypeName,
302                                    DataKind DK = DataKindUser,
303                                    bool Normalized = false);
304
305  static const char *VectorTypeNameStore[][3];
306
307  virtual const llvm::Type *convertToLLVMType() const;
308 public:
309  static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT);
310
311  inline unsigned getNumElement() const { return mNumElement; }
312};
313
314// Only *square* *float* matrix is supported by now.
315//
316// struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following
317// form *exactly*:
318//  typedef struct {
319//    float m[{NxN}];
320//  } rs_matrixNxN;
321//
322//  where mDim will be N.
323class RSExportMatrixType : public RSExportType {
324  friend class RSExportType;
325 private:
326  unsigned mDim;  // dimension
327
328  RSExportMatrixType(RSContext *Context,
329                     const llvm::StringRef &Name,
330                     unsigned Dim)
331    : RSExportType(Context, ExportClassMatrix, Name),
332      mDim(Dim) {
333    return;
334  }
335
336  virtual const llvm::Type *convertToLLVMType() const;
337 public:
338  // @RT was normalized by calling RSExportType::TypeExportable() before
339  // calling this.
340  static RSExportMatrixType *Create(RSContext *Context,
341                                    const clang::RecordType *RT,
342                                    const llvm::StringRef &TypeName,
343                                    unsigned Dim);
344
345  inline unsigned getDim() const { return mDim; }
346};
347
348class RSExportConstantArrayType : public RSExportType {
349  friend class RSExportType;
350 private:
351  const RSExportType *mElementType;  // Array element type
352  unsigned mSize;  // Array size
353
354  RSExportConstantArrayType(RSContext *Context,
355                            const RSExportType *ElementType,
356                            unsigned Size)
357    : RSExportType(Context,
358                   ExportClassConstantArray,
359                   DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE),
360      mElementType(ElementType),
361      mSize(Size) {
362    return;
363  }
364
365  // @CAT was normalized by calling RSExportType::TypeExportable() before
366  // calling this.
367  static RSExportConstantArrayType *Create(RSContext *Context,
368                                           const clang::ConstantArrayType *CAT);
369
370  virtual const llvm::Type *convertToLLVMType() const;
371 public:
372  inline unsigned getSize() const { return mSize; }
373  inline const RSExportType *getElementType() const { return mElementType; }
374};
375
376class RSExportRecordType : public RSExportType {
377  friend class RSExportType;
378 public:
379  class Field {
380   private:
381    const RSExportType *mType;
382    // Field name
383    std::string mName;
384    // Link to the struct that contain this field
385    const RSExportRecordType *mParent;
386    // Offset in the container
387    size_t mOffset;
388
389   public:
390    Field(const RSExportType *T,
391          const llvm::StringRef &Name,
392          const RSExportRecordType *Parent,
393          size_t Offset)
394        : mType(T),
395          mName(Name.data(), Name.size()),
396          mParent(Parent),
397          mOffset(Offset) {
398      return;
399    }
400
401    inline const RSExportRecordType *getParent() const { return mParent; }
402    inline const RSExportType *getType() const { return mType; }
403    inline const std::string &getName() const { return mName; }
404    inline size_t getOffsetInParent() const { return mOffset; }
405  };
406
407  typedef std::list<const Field*>::const_iterator const_field_iterator;
408
409  inline const_field_iterator fields_begin() const {
410    return this->mFields.begin();
411  }
412  inline const_field_iterator fields_end() const {
413    return this->mFields.end();
414  }
415
416 private:
417  std::list<const Field*> mFields;
418  bool mIsPacked;
419  // Artificial export struct type is not exported by user (and thus it won't
420  // get reflected)
421  bool mIsArtificial;
422  size_t mAllocSize;
423
424  RSExportRecordType(RSContext *Context,
425                     const llvm::StringRef &Name,
426                     bool IsPacked,
427                     bool IsArtificial,
428                     size_t AllocSize)
429      : RSExportType(Context, ExportClassRecord, Name),
430        mIsPacked(IsPacked),
431        mIsArtificial(IsArtificial),
432        mAllocSize(AllocSize) {
433    return;
434  }
435
436  // @RT was normalized by calling RSExportType::TypeExportable() before calling
437  // this.
438  // @TypeName was retrieved from RSExportType::GetTypeName() before calling
439  // this.
440  static RSExportRecordType *Create(RSContext *Context,
441                                    const clang::RecordType *RT,
442                                    const llvm::StringRef &TypeName,
443                                    bool mIsArtificial = false);
444
445  virtual const llvm::Type *convertToLLVMType() const;
446 public:
447  inline const std::list<const Field*>& getFields() const { return mFields; }
448  inline bool isPacked() const { return mIsPacked; }
449  inline bool isArtificial() const { return mIsArtificial; }
450  inline size_t getAllocSize() const { return mAllocSize; }
451
452  ~RSExportRecordType() {
453    for (std::list<const Field*>::iterator I = mFields.begin(),
454             E = mFields.end();
455         I != E;
456         I++)
457      if (*I != NULL)
458        delete *I;
459    return;
460  }
461};  // RSExportRecordType
462
463}   // namespace slang
464
465#endif  // _SLANG_COMPILER_RS_EXPORT_TYPE_H
466