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