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