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