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