• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_  // NOLINT
18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_
19 
20 #include <list>
21 #include <set>
22 #include <string>
23 
24 #include "clang/AST/Decl.h"
25 #include "clang/AST/Type.h"
26 
27 #include "llvm/ADT/SmallPtrSet.h"
28 #include "llvm/ADT/StringMap.h"
29 #include "llvm/ADT/StringRef.h"
30 
31 #include "llvm/Support/ManagedStatic.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 
53 union RSType;
54 
55 namespace llvm {
56   class Type;
57 }   // namespace llvm
58 
59 namespace slang {
60 
61   class RSContext;
62 
63 class RSExportType : public RSExportable {
64   friend class RSExportElement;
65  public:
66   typedef enum {
67     ExportClassPrimitive,
68     ExportClassPointer,
69     ExportClassVector,
70     ExportClassMatrix,
71     ExportClassConstantArray,
72     ExportClassRecord
73   } ExportClass;
74 
75  private:
76   ExportClass mClass;
77   std::string mName;
78 
79   // Cache the result after calling convertToLLVMType() at the first time
80   mutable llvm::Type *mLLVMType;
81   // Cache the result after calling convertToSpecType() at the first time
82   mutable union RSType *mSpecType;
83 
84  protected:
85   RSExportType(RSContext *Context,
86                ExportClass Class,
87                const llvm::StringRef &Name);
88 
89   // Let's make it private since there're some prerequisites to call this
90   // function.
91   //
92   // @T was normalized by calling RSExportType::NormalizeType().
93   // @TypeName was retrieve from RSExportType::GetTypeName() before calling
94   //           this.
95   //
96   static RSExportType *Create(RSContext *Context,
97                               const clang::Type *T,
98                               const llvm::StringRef &TypeName);
99 
100   static llvm::StringRef GetTypeName(const clang::Type *T);
101 
102   // This function convert the RSExportType to LLVM type. Actually, it should be
103   // "convert Clang type to LLVM type." However, clang doesn't make this API
104   // (lib/CodeGen/CodeGenTypes.h) public, we need to do by ourselves.
105   //
106   // Once we can get LLVM type, we can use LLVM to get alignment information,
107   // allocation size of a given type and structure layout that LLVM used
108   // (all of these information are target dependent) without dealing with these
109   // by ourselves.
110   virtual llvm::Type *convertToLLVMType() const = 0;
111   // Record type may recursively reference its type definition. We need a
112   // temporary type setup before the type construction gets done.
setAbstractLLVMType(llvm::Type * LLVMType)113   inline void setAbstractLLVMType(llvm::Type *LLVMType) const {
114     mLLVMType = LLVMType;
115   }
116 
117   virtual union RSType *convertToSpecType() const = 0;
setSpecTypeTemporarily(union RSType * SpecType)118   inline void setSpecTypeTemporarily(union RSType *SpecType) const {
119     mSpecType = SpecType;
120   }
121 
122   virtual ~RSExportType();
123 
124  public:
125   // This function additionally verifies that the Type T is exportable.
126   // If it is not, this function returns false. Otherwise it returns true.
127   static bool NormalizeType(const clang::Type *&T,
128                             llvm::StringRef &TypeName,
129                             clang::Diagnostic *Diags,
130                             const clang::VarDecl *VD);
131 
132   // This function ensures that the VarDecl can be properly handled by RS.
133   // If it cannot, this function returns false. Otherwise it returns true.
134   static bool ValidateVarDecl(clang::VarDecl *VD);
135 
136   // @T may not be normalized
137   static RSExportType *Create(RSContext *Context, const clang::Type *T);
138   static RSExportType *CreateFromDecl(RSContext *Context,
139                                       const clang::VarDecl *VD);
140 
141   static const clang::Type *GetTypeOfDecl(const clang::DeclaratorDecl *DD);
142 
getClass()143   inline ExportClass getClass() const { return mClass; }
144 
getLLVMType()145   inline llvm::Type *getLLVMType() const {
146     if (mLLVMType == NULL)
147       mLLVMType = convertToLLVMType();
148     return mLLVMType;
149   }
150 
getSpecType()151   inline const union RSType *getSpecType() const {
152     if (mSpecType == NULL)
153       mSpecType = convertToSpecType();
154     return mSpecType;
155   }
156 
157   // Return the number of bits necessary to hold the specified RSExportType
158   static size_t GetTypeStoreSize(const RSExportType *ET);
159 
160   // The size of allocation of specified RSExportType (alignment considered)
161   static size_t GetTypeAllocSize(const RSExportType *ET);
162 
getName()163   inline const std::string &getName() const { return mName; }
164 
165   virtual bool keep();
166   virtual bool equals(const RSExportable *E) const;
167 };  // RSExportType
168 
169 // Primitive types
170 class RSExportPrimitiveType : public RSExportType {
171   friend class RSExportType;
172   friend class RSExportElement;
173  public:
174   // From graphics/java/android/renderscript/Element.java: Element.DataType
175   typedef enum {
176     DataTypeIsStruct = -2,
177     DataTypeUnknown = -1,
178 
179 #define ENUM_PRIMITIVE_DATA_TYPE_RANGE(begin_type, end_type)  \
180     FirstPrimitiveType = DataType ## begin_type,  \
181     LastPrimitiveType = DataType ## end_type,
182 
183 #define ENUM_RS_MATRIX_DATA_TYPE_RANGE(begin_type, end_type)  \
184     FirstRSMatrixType = DataType ## begin_type,  \
185     LastRSMatrixType = DataType ## end_type,
186 
187 #define ENUM_RS_OBJECT_DATA_TYPE_RANGE(begin_type, end_type)  \
188     FirstRSObjectType = DataType ## begin_type,  \
189     LastRSObjectType = DataType ## end_type,
190 
191 #define ENUM_RS_DATA_TYPE(type, cname, bits)  \
192     DataType ## type,
193 
194 #include "RSDataTypeEnums.inc"
195 
196     DataTypeMax
197   } DataType;
198 
199   // From graphics/java/android/renderscript/Element.java: Element.DataKind
200   typedef enum {
201     DataKindUnknown = -1
202 #define ENUM_RS_DATA_KIND(kind) \
203     , DataKind ## kind
204 #include "RSDataKindEnums.inc"
205   } DataKind;
206 
207  private:
208   // NOTE: There's no any instance of RSExportPrimitiveType which mType
209   // is of the value DataTypeRSMatrix*. DataTypeRSMatrix* enumeration here is
210   // only for RSExportPrimitiveType::GetRSObjectType to *recognize* the struct
211   // rs_matrix{2x2, 3x3, 4x4}. These matrix type are represented as
212   // RSExportMatrixType.
213   DataType mType;
214   DataKind mKind;
215   bool mNormalized;
216 
217   typedef llvm::StringMap<DataType> RSSpecificTypeMapTy;
218   static llvm::ManagedStatic<RSSpecificTypeMapTy> RSSpecificTypeMap;
219 
220   static llvm::Type *RSObjectLLVMType;
221 
222   static const size_t SizeOfDataTypeInBits[];
223   // @T was normalized by calling RSExportType::NormalizeType() before calling
224   // this.
225   // @TypeName was retrieved from RSExportType::GetTypeName() before calling
226   // this
227   static RSExportPrimitiveType *Create(RSContext *Context,
228                                        const clang::Type *T,
229                                        const llvm::StringRef &TypeName,
230                                        DataKind DK = DataKindUser,
231                                        bool Normalized = false);
232 
233  protected:
RSExportPrimitiveType(RSContext * Context,ExportClass Class,const llvm::StringRef & Name,DataType DT,DataKind DK,bool Normalized)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 llvm::Type *convertToLLVMType() const;
249   virtual union RSType *convertToSpecType() const;
250 
251   static DataType GetDataType(RSContext *Context, const clang::Type *T);
252 
253  public:
254   // T is normalized by calling RSExportType::NormalizeType() before
255   // calling this
256   static bool IsPrimitiveType(const clang::Type *T);
257 
258   // @T may not be normalized
259   static RSExportPrimitiveType *Create(RSContext *Context,
260                                        const clang::Type *T,
261                                        DataKind DK = DataKindUser);
262 
263   static DataType GetRSSpecificType(const llvm::StringRef &TypeName);
264   static DataType GetRSSpecificType(const clang::Type *T);
265 
266   static bool IsRSMatrixType(DataType DT);
267   static bool IsRSObjectType(DataType DT);
IsRSObjectType(const clang::Type * T)268   static bool IsRSObjectType(const clang::Type *T) {
269     return IsRSObjectType(GetRSSpecificType(T));
270   }
271 
272   // Determines whether T is [an array of] struct that contains at least one
273   // RS object type within it.
274   static bool IsStructureTypeWithRSObject(const clang::Type *T);
275 
276   static size_t GetSizeInBits(const RSExportPrimitiveType *EPT);
277 
getType()278   inline DataType getType() const { return mType; }
getKind()279   inline DataKind getKind() const { return mKind; }
isRSObjectType()280   inline bool isRSObjectType() const {
281     return ((mType >= FirstRSObjectType) && (mType <= LastRSObjectType));
282   }
283 
284   virtual bool equals(const RSExportable *E) const;
285 };  // RSExportPrimitiveType
286 
287 
288 class RSExportPointerType : public RSExportType {
289   friend class RSExportType;
290   friend class RSExportFunc;
291  private:
292   const RSExportType *mPointeeType;
293 
RSExportPointerType(RSContext * Context,const llvm::StringRef & Name,const RSExportType * PointeeType)294   RSExportPointerType(RSContext *Context,
295                       const llvm::StringRef &Name,
296                       const RSExportType *PointeeType)
297       : RSExportType(Context, ExportClassPointer, Name),
298         mPointeeType(PointeeType) {
299     return;
300   }
301 
302   // @PT was normalized by calling RSExportType::NormalizeType() before calling
303   // this.
304   static RSExportPointerType *Create(RSContext *Context,
305                                      const clang::PointerType *PT,
306                                      const llvm::StringRef &TypeName);
307 
308   virtual llvm::Type *convertToLLVMType() const;
309   virtual union RSType *convertToSpecType() const;
310 
311  public:
312   virtual bool keep();
313 
getPointeeType()314   inline const RSExportType *getPointeeType() const { return mPointeeType; }
315 
316   virtual bool equals(const RSExportable *E) const;
317 };  // RSExportPointerType
318 
319 
320 class RSExportVectorType : public RSExportPrimitiveType {
321   friend class RSExportType;
322   friend class RSExportElement;
323  private:
324   unsigned mNumElement;   // number of element
325 
RSExportVectorType(RSContext * Context,const llvm::StringRef & Name,DataType DT,DataKind DK,bool Normalized,unsigned NumElement)326   RSExportVectorType(RSContext *Context,
327                      const llvm::StringRef &Name,
328                      DataType DT,
329                      DataKind DK,
330                      bool Normalized,
331                      unsigned NumElement)
332       : RSExportPrimitiveType(Context, ExportClassVector, Name,
333                               DT, DK, Normalized),
334         mNumElement(NumElement) {
335     return;
336   }
337 
338   // @EVT was normalized by calling RSExportType::NormalizeType() before
339   // calling this.
340   static RSExportVectorType *Create(RSContext *Context,
341                                     const clang::ExtVectorType *EVT,
342                                     const llvm::StringRef &TypeName,
343                                     DataKind DK = DataKindUser,
344                                     bool Normalized = false);
345 
346   virtual llvm::Type *convertToLLVMType() const;
347   virtual union RSType *convertToSpecType() const;
348 
349  public:
350   static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT);
351 
getNumElement()352   inline unsigned getNumElement() const { return mNumElement; }
353 
354   virtual bool equals(const RSExportable *E) const;
355 };
356 
357 // Only *square* *float* matrix is supported by now.
358 //
359 // struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following
360 // form *exactly*:
361 //  typedef struct {
362 //    float m[{NxN}];
363 //  } rs_matrixNxN;
364 //
365 //  where mDim will be N.
366 class RSExportMatrixType : public RSExportType {
367   friend class RSExportType;
368  private:
369   unsigned mDim;  // dimension
370 
RSExportMatrixType(RSContext * Context,const llvm::StringRef & Name,unsigned Dim)371   RSExportMatrixType(RSContext *Context,
372                      const llvm::StringRef &Name,
373                      unsigned Dim)
374     : RSExportType(Context, ExportClassMatrix, Name),
375       mDim(Dim) {
376     return;
377   }
378 
379   virtual llvm::Type *convertToLLVMType() const;
380   virtual union RSType *convertToSpecType() const;
381 
382  public:
383   // @RT was normalized by calling RSExportType::NormalizeType() before
384   // calling this.
385   static RSExportMatrixType *Create(RSContext *Context,
386                                     const clang::RecordType *RT,
387                                     const llvm::StringRef &TypeName,
388                                     unsigned Dim);
389 
getDim()390   inline unsigned getDim() const { return mDim; }
391 
392   virtual bool equals(const RSExportable *E) const;
393 };
394 
395 class RSExportConstantArrayType : public RSExportType {
396   friend class RSExportType;
397  private:
398   const RSExportType *mElementType;  // Array element type
399   unsigned mSize;  // Array size
400 
RSExportConstantArrayType(RSContext * Context,const RSExportType * ElementType,unsigned Size)401   RSExportConstantArrayType(RSContext *Context,
402                             const RSExportType *ElementType,
403                             unsigned Size)
404     : RSExportType(Context,
405                    ExportClassConstantArray,
406                    DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE),
407       mElementType(ElementType),
408       mSize(Size) {
409     return;
410   }
411 
412   // @CAT was normalized by calling RSExportType::NormalizeType() before
413   // calling this.
414   static RSExportConstantArrayType *Create(RSContext *Context,
415                                            const clang::ConstantArrayType *CAT);
416 
417   virtual llvm::Type *convertToLLVMType() const;
418   virtual union RSType *convertToSpecType() const;
419 
420  public:
getSize()421   inline unsigned getSize() const { return mSize; }
getElementType()422   inline const RSExportType *getElementType() const { return mElementType; }
423 
424   virtual bool keep();
425   virtual bool equals(const RSExportable *E) const;
426 };
427 
428 class RSExportRecordType : public RSExportType {
429   friend class RSExportType;
430  public:
431   class Field {
432    private:
433     const RSExportType *mType;
434     // Field name
435     std::string mName;
436     // Link to the struct that contain this field
437     const RSExportRecordType *mParent;
438     // Offset in the container
439     size_t mOffset;
440 
441    public:
Field(const RSExportType * T,const llvm::StringRef & Name,const RSExportRecordType * Parent,size_t Offset)442     Field(const RSExportType *T,
443           const llvm::StringRef &Name,
444           const RSExportRecordType *Parent,
445           size_t Offset)
446         : mType(T),
447           mName(Name.data(), Name.size()),
448           mParent(Parent),
449           mOffset(Offset) {
450       return;
451     }
452 
getParent()453     inline const RSExportRecordType *getParent() const { return mParent; }
getType()454     inline const RSExportType *getType() const { return mType; }
getName()455     inline const std::string &getName() const { return mName; }
getOffsetInParent()456     inline size_t getOffsetInParent() const { return mOffset; }
457   };
458 
459   typedef std::list<const Field*>::const_iterator const_field_iterator;
460 
fields_begin()461   inline const_field_iterator fields_begin() const {
462     return this->mFields.begin();
463   }
fields_end()464   inline const_field_iterator fields_end() const {
465     return this->mFields.end();
466   }
467 
468  private:
469   std::list<const Field*> mFields;
470   bool mIsPacked;
471   // Artificial export struct type is not exported by user (and thus it won't
472   // get reflected)
473   bool mIsArtificial;
474   size_t mAllocSize;
475 
RSExportRecordType(RSContext * Context,const llvm::StringRef & Name,bool IsPacked,bool IsArtificial,size_t AllocSize)476   RSExportRecordType(RSContext *Context,
477                      const llvm::StringRef &Name,
478                      bool IsPacked,
479                      bool IsArtificial,
480                      size_t AllocSize)
481       : RSExportType(Context, ExportClassRecord, Name),
482         mIsPacked(IsPacked),
483         mIsArtificial(IsArtificial),
484         mAllocSize(AllocSize) {
485     return;
486   }
487 
488   // @RT was normalized by calling RSExportType::NormalizeType() before calling
489   // this.
490   // @TypeName was retrieved from RSExportType::GetTypeName() before calling
491   // this.
492   static RSExportRecordType *Create(RSContext *Context,
493                                     const clang::RecordType *RT,
494                                     const llvm::StringRef &TypeName,
495                                     bool mIsArtificial = false);
496 
497   virtual llvm::Type *convertToLLVMType() const;
498   virtual union RSType *convertToSpecType() const;
499 
500  public:
getFields()501   inline const std::list<const Field*>& getFields() const { return mFields; }
isPacked()502   inline bool isPacked() const { return mIsPacked; }
isArtificial()503   inline bool isArtificial() const { return mIsArtificial; }
getAllocSize()504   inline size_t getAllocSize() const { return mAllocSize; }
505 
506   virtual bool keep();
507   virtual bool equals(const RSExportable *E) const;
508 
~RSExportRecordType()509   ~RSExportRecordType() {
510     for (std::list<const Field*>::iterator I = mFields.begin(),
511              E = mFields.end();
512          I != E;
513          I++)
514       if (*I != NULL)
515         delete *I;
516     return;
517   }
518 };  // RSExportRecordType
519 
520 }   // namespace slang
521 
522 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_  NOLINT
523