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