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