slang_rs_export_type.h revision 6b6320ad5faee29e0f75fe937e40156746ef9e80
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  ExportClass mClass;
56  std::string mName;
57
58  // Cache the result after calling convertToLLVMType() at the first time
59  mutable const llvm::Type *mLLVMType;
60
61 protected:
62  RSExportType(RSContext *Context,
63               ExportClass Class,
64               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  inline ExportClass getClass() const { return mClass; }
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                        // for derived class to set their type class
215                        ExportClass Class,
216                        const llvm::StringRef &Name,
217                        DataType DT,
218                        DataKind DK,
219                        bool Normalized)
220      : RSExportType(Context, Class, Name),
221        mType(DT),
222        mKind(DK),
223        mNormalized(Normalized) {
224    return;
225  }
226
227  virtual const llvm::Type *convertToLLVMType() const;
228 public:
229  // @T may not be normalized
230  static RSExportPrimitiveType *Create(RSContext *Context,
231                                       const clang::Type *T,
232                                       DataKind DK = DataKindUser);
233
234  static DataType GetRSObjectType(const llvm::StringRef &TypeName);
235  static DataType GetRSObjectType(const clang::Type *T);
236
237  static size_t GetSizeInBits(const RSExportPrimitiveType *EPT);
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, ExportClassPointer, 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  inline const RSExportType *getPointeeType() const { return mPointeeType; }
272};  // RSExportPointerType
273
274
275class RSExportVectorType : public RSExportPrimitiveType {
276  friend class RSExportType;
277  friend class RSExportElement;
278 private:
279  unsigned mNumElement;   // number of element
280
281  RSExportVectorType(RSContext *Context,
282                     const llvm::StringRef &Name,
283                     DataType DT,
284                     DataKind DK,
285                     bool Normalized,
286                     unsigned NumElement)
287      : RSExportPrimitiveType(Context, ExportClassVector, Name,
288                              DT, DK, Normalized),
289        mNumElement(NumElement) {
290    return;
291  }
292
293  // @EVT was normalized by calling RSExportType::TypeExportable() before
294  // calling this.
295  static RSExportVectorType *Create(RSContext *Context,
296                                    const clang::ExtVectorType *EVT,
297                                    const llvm::StringRef &TypeName,
298                                    DataKind DK = DataKindUser,
299                                    bool Normalized = false);
300
301  static const char *VectorTypeNameStore[][3];
302
303  virtual const llvm::Type *convertToLLVMType() const;
304 public:
305  static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT);
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, ExportClassMatrix, Name),
328      mDim(Dim) {
329    return;
330  }
331
332  virtual const llvm::Type *convertToLLVMType() const;
333 public:
334  // @RT was normalized by calling RSExportType::TypeExportable() before
335  // calling this.
336  static RSExportMatrixType *Create(RSContext *Context,
337                                    const clang::RecordType *RT,
338                                    const llvm::StringRef &TypeName,
339                                    unsigned Dim);
340
341  inline unsigned getDim() const { return mDim; }
342};
343
344class RSExportConstantArrayType : public RSExportType {
345  friend class RSExportType;
346 private:
347  const RSExportType *mElementType;  // Array element type
348  unsigned mSize;  // Array size
349
350  RSExportConstantArrayType(RSContext *Context,
351                            const RSExportType *ElementType,
352                            unsigned Size)
353    : RSExportType(Context,
354                   ExportClassConstantArray,
355                   DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE),
356      mElementType(ElementType),
357      mSize(Size) {
358    return;
359  }
360
361  // @CAT was normalized by calling RSExportType::TypeExportable() before
362  // calling this.
363  static RSExportConstantArrayType *Create(RSContext *Context,
364                                           const clang::ConstantArrayType *CAT);
365
366  virtual const llvm::Type *convertToLLVMType() const;
367 public:
368  inline unsigned getSize() const { return mSize; }
369  inline const RSExportType *getElementType() const { return mElementType; }
370};
371
372class RSExportRecordType : public RSExportType {
373  friend class RSExportType;
374 public:
375  class Field {
376   private:
377    const RSExportType *mType;
378    // Field name
379    std::string mName;
380    // Link to the struct that contain this field
381    const RSExportRecordType *mParent;
382    // Offset in the container
383    size_t mOffset;
384
385   public:
386    Field(const RSExportType *T,
387          const llvm::StringRef &Name,
388          const RSExportRecordType *Parent,
389          size_t Offset)
390        : mType(T),
391          mName(Name.data(), Name.size()),
392          mParent(Parent),
393          mOffset(Offset) {
394      return;
395    }
396
397    inline const RSExportRecordType *getParent() const { return mParent; }
398    inline const RSExportType *getType() const { return mType; }
399    inline const std::string &getName() const { return mName; }
400    inline size_t getOffsetInParent() const { return mOffset; }
401  };
402
403  typedef std::list<const Field*>::const_iterator const_field_iterator;
404
405  inline const_field_iterator fields_begin() const {
406    return this->mFields.begin();
407  }
408  inline const_field_iterator fields_end() const {
409    return this->mFields.end();
410  }
411
412 private:
413  std::list<const Field*> mFields;
414  bool mIsPacked;
415  // Artificial export struct type is not exported by user (and thus it won't
416  // get reflected)
417  bool mIsArtificial;
418  size_t mAllocSize;
419
420  RSExportRecordType(RSContext *Context,
421                     const llvm::StringRef &Name,
422                     bool IsPacked,
423                     bool IsArtificial,
424                     size_t AllocSize)
425      : RSExportType(Context, ExportClassRecord, Name),
426        mIsPacked(IsPacked),
427        mIsArtificial(IsArtificial),
428        mAllocSize(AllocSize) {
429    return;
430  }
431
432  // @RT was normalized by calling RSExportType::TypeExportable() before calling
433  // this.
434  // @TypeName was retrieved from RSExportType::GetTypeName() before calling
435  // this.
436  static RSExportRecordType *Create(RSContext *Context,
437                                    const clang::RecordType *RT,
438                                    const llvm::StringRef &TypeName,
439                                    bool mIsArtificial = false);
440
441  virtual const llvm::Type *convertToLLVMType() const;
442 public:
443  inline const std::list<const Field*>& getFields() const { return mFields; }
444  inline bool isPacked() const { return mIsPacked; }
445  inline bool isArtificial() const { return mIsArtificial; }
446  inline size_t getAllocSize() const { return mAllocSize; }
447
448  ~RSExportRecordType() {
449    for (std::list<const Field*>::iterator I = mFields.begin(),
450             E = mFields.end();
451         I != E;
452         I++)
453      if (*I != NULL)
454        delete *I;
455    return;
456  }
457};  // RSExportRecordType
458
459}   // namespace slang
460
461#endif  // _SLANG_COMPILER_RS_EXPORT_TYPE_H
462