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