slang_rs_export_type.h revision 6315f76e3cc6ff2d012d1183a0b030d4ff0dc808
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
29namespace llvm {
30  class Type;
31}   // namespace llvm
32
33namespace slang {
34
35  class RSContext;
36  class RSExportPrimitiveType;
37  class RSExportConstantArrayType;
38  class RSExportVectorType;
39  class RSExportRecordType;
40  class RSExportFunction;
41
42class RSExportType {
43  friend class RSExportElement;
44 public:
45  typedef enum {
46    ExportClassPrimitive,
47    ExportClassPointer,
48    ExportClassConstantArray,
49    ExportClassVector,
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    DataTypeRSMatrix2x2,
149    DataTypeRSMatrix3x3,
150    DataTypeRSMatrix4x4,
151
152    DataTypeRSElement,
153    DataTypeRSType,
154    DataTypeRSAllocation,
155    DataTypeRSSampler,
156    DataTypeRSScript,
157    DataTypeRSMesh,
158    DataTypeRSProgramFragment,
159    DataTypeRSProgramVertex,
160    DataTypeRSProgramRaster,
161    DataTypeRSProgramStore,
162    DataTypeRSFont,
163
164    DataTypeMax
165  } DataType;
166
167  // From graphics/java/android/renderscript/Element.java: Element.DataKind
168  typedef enum {
169    DataKindUser,
170    DataKindPixelL,
171    DataKindPixelA,
172    DataKindPixelLA,
173    DataKindPixelRGB,
174    DataKindPixelRGBA
175  } DataKind;
176
177 private:
178  DataType mType;
179  DataKind mKind;
180  bool mNormalized;
181
182  typedef llvm::StringMap<DataType> RSObjectTypeMapTy;
183  static RSObjectTypeMapTy *RSObjectTypeMap;
184
185  static llvm::Type *RSObjectLLVMType;
186
187  static const size_t SizeOfDataTypeInBits[];
188  // @T was normalized by calling RSExportType::TypeExportable() before calling
189  // this.
190  // @TypeName was retrieved from RSExportType::GetTypeName() before calling
191  // this
192  static RSExportPrimitiveType *Create(RSContext *Context,
193                                       const clang::Type *T,
194                                       const llvm::StringRef &TypeName,
195                                       DataKind DK = DataKindUser,
196                                       bool Normalized = false);
197
198 protected:
199  // T is normalized by calling RSExportType::TypeExportable() before
200  // calling this
201  static bool IsPrimitiveType(const clang::Type *T);
202
203  static DataType GetDataType(const clang::Type *T);
204
205  RSExportPrimitiveType(RSContext *Context,
206                        const llvm::StringRef &Name,
207                        DataType DT,
208                        DataKind DK,
209                        bool Normalized)
210      : RSExportType(Context, Name),
211        mType(DT),
212        mKind(DK),
213        mNormalized(Normalized) {
214    return;
215  }
216
217  virtual const llvm::Type *convertToLLVMType() const;
218 public:
219  // @T may not be normalized
220  static RSExportPrimitiveType *Create(RSContext *Context,
221                                       const clang::Type *T,
222                                       DataKind DK = DataKindUser);
223
224  static DataType GetRSObjectType(const llvm::StringRef &TypeName);
225  static DataType GetRSObjectType(const clang::Type *T);
226
227  static size_t GetSizeInBits(const RSExportPrimitiveType *EPT);
228
229  virtual ExportClass getClass() const;
230
231  inline DataType getType() const { return mType; }
232  inline DataKind getKind() const { return mKind; }
233  inline bool isRSObjectType() const {
234    return ((mType >= DataTypeRSElement) && (mType < DataTypeMax));
235  }
236};  // RSExportPrimitiveType
237
238
239class RSExportPointerType : public RSExportType {
240  friend class RSExportType;
241  friend class RSExportElement;
242  friend class RSExportFunc;
243
244 private:
245  const RSExportType *mPointeeType;
246
247  RSExportPointerType(RSContext *Context,
248                      const llvm::StringRef &Name,
249                      const RSExportType *PointeeType)
250      : RSExportType(Context, Name),
251        mPointeeType(PointeeType) {
252    return;
253  }
254
255  // @PT was normalized by calling RSExportType::TypeExportable() before calling
256  // this.
257  static RSExportPointerType *Create(RSContext *Context,
258                                     const clang::PointerType *PT,
259                                     const llvm::StringRef &TypeName);
260
261  virtual const llvm::Type *convertToLLVMType() const;
262 public:
263  static const clang::Type *IntegerType;
264
265  virtual ExportClass getClass() const;
266
267  inline const RSExportType *getPointeeType() const { return mPointeeType; }
268};  // RSExportPointerType
269
270
271class RSExportConstantArrayType : public RSExportPrimitiveType {
272  friend class RSExportType;
273  friend class RSExportElement;
274  friend class RSExportFunc;
275
276 private:
277  int mNumElement;   // number of element
278
279  RSExportConstantArrayType(RSContext *Context,
280                            const llvm::StringRef &Name,
281                            DataType DT,
282                            DataKind DK,
283                            bool Normalized,
284                            int NumElement)
285      : RSExportPrimitiveType(Context, Name, DT, DK, Normalized),
286        mNumElement(NumElement) {
287    return;
288  }
289
290  static RSExportConstantArrayType *Create(RSContext *Context,
291                                           const clang::ConstantArrayType *ECT,
292                                           const llvm::StringRef &TypeName,
293                                           DataKind DK = DataKindUser,
294                                           bool Normalized = false);
295  virtual const llvm::Type *convertToLLVMType() const;
296 public:
297  static llvm::StringRef GetTypeName(const clang::ConstantArrayType *ECT);
298
299  virtual ExportClass getClass() const;
300
301  inline int getNumElement() const { return mNumElement; }
302};
303
304
305class RSExportVectorType : public RSExportPrimitiveType {
306  friend class RSExportType;
307  friend class RSExportElement;
308
309 private:
310  int mNumElement;   // number of element
311
312  RSExportVectorType(RSContext *Context,
313                     const llvm::StringRef &Name,
314                     DataType DT,
315                     DataKind DK,
316                     bool Normalized,
317                     int NumElement)
318      : RSExportPrimitiveType(Context, Name, DT, DK, Normalized),
319        mNumElement(NumElement) {
320    return;
321  }
322
323  // @EVT was normalized by calling RSExportType::TypeExportable() before
324  // calling this.
325  static RSExportVectorType *Create(RSContext *Context,
326                                    const clang::ExtVectorType *EVT,
327                                    const llvm::StringRef &TypeName,
328                                    DataKind DK = DataKindUser,
329                                    bool Normalized = false);
330
331  static const char *VectorTypeNameStore[][3];
332
333  virtual const llvm::Type *convertToLLVMType() const;
334 public:
335  static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT);
336
337  virtual ExportClass getClass() const;
338
339  inline int getNumElement() const { return mNumElement; }
340};
341
342class RSExportRecordType : public RSExportType {
343  friend class RSExportType;
344  friend class RSExportElement;
345  friend class RSExportFunc;
346 public:
347  class Field {
348   private:
349    const RSExportType *mType;
350    // Field name
351    std::string mName;
352    // Link to the struct that contain this field
353    const RSExportRecordType *mParent;
354    // Index in the container
355    unsigned int mIndex;
356
357   public:
358    Field(const RSExportType *T,
359          const llvm::StringRef &Name,
360          const RSExportRecordType *Parent,
361          unsigned int Index)
362        : mType(T),
363          mName(Name.data(), Name.size()),
364          mParent(Parent),
365          mIndex(Index) {
366      return;
367    }
368
369    inline const RSExportRecordType *getParent() const { return mParent; }
370    inline unsigned int getIndex() const { return mIndex; }
371    inline const RSExportType *getType() const { return mType; }
372    inline const std::string &getName() const { return mName; }
373    size_t getOffsetInParent() const;
374  };
375
376  typedef std::list<const Field*>::const_iterator const_field_iterator;
377
378  inline const_field_iterator fields_begin() const {
379    return this->mFields.begin();
380  }
381  inline const_field_iterator fields_end() const {
382    return this->mFields.end();
383  }
384
385 private:
386  std::list<const Field*> mFields;
387  bool mIsPacked;
388  // Artificial export struct type is not exported by user (and thus it won't
389  // get reflected)
390  bool mIsArtificial;
391  size_t AllocSize;
392
393  RSExportRecordType(RSContext *Context,
394                     const llvm::StringRef &Name,
395                     bool IsPacked,
396                     bool IsArtificial = false)
397      : RSExportType(Context, Name),
398        mIsPacked(IsPacked),
399        mIsArtificial(IsArtificial) {
400    return;
401  }
402
403  // @RT was normalized by calling RSExportType::TypeExportable() before calling
404  // this.
405  // @TypeName was retrieved from RSExportType::GetTypeName() before calling
406  // this.
407  static RSExportRecordType *Create(RSContext *Context,
408                                    const clang::RecordType *RT,
409                                    const llvm::StringRef &TypeName,
410                                    bool mIsArtificial = false);
411
412  virtual const llvm::Type *convertToLLVMType() const;
413 public:
414  virtual ExportClass getClass() const;
415
416  inline bool isPacked() const { return mIsPacked; }
417  inline bool isArtificial() const { return mIsArtificial; }
418  inline size_t getAllocSize() const { return AllocSize; }
419
420  ~RSExportRecordType() {
421    for (std::list<const Field*>::iterator I = mFields.begin(),
422             E = mFields.end();
423         I != E;
424         I++)
425      if (*I != NULL)
426        delete *I;
427    return;
428  }
429};  // RSExportRecordType
430
431}   // namespace slang
432
433#endif  // _SLANG_COMPILER_RS_EXPORT_TYPE_H
434