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