slang_rs_export_type.h revision 6b6320ad5faee29e0f75fe937e40156746ef9e80
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 ExportClass mClass; 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, 63 ExportClass Class, 64 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 inline ExportClass getClass() const { return mClass; } 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 // for derived class to set their type class 215 ExportClass Class, 216 const llvm::StringRef &Name, 217 DataType DT, 218 DataKind DK, 219 bool Normalized) 220 : RSExportType(Context, Class, Name), 221 mType(DT), 222 mKind(DK), 223 mNormalized(Normalized) { 224 return; 225 } 226 227 virtual const llvm::Type *convertToLLVMType() const; 228 public: 229 // @T may not be normalized 230 static RSExportPrimitiveType *Create(RSContext *Context, 231 const clang::Type *T, 232 DataKind DK = DataKindUser); 233 234 static DataType GetRSObjectType(const llvm::StringRef &TypeName); 235 static DataType GetRSObjectType(const clang::Type *T); 236 237 static size_t GetSizeInBits(const RSExportPrimitiveType *EPT); 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, ExportClassPointer, 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 inline const RSExportType *getPointeeType() const { return mPointeeType; } 272}; // RSExportPointerType 273 274 275class RSExportVectorType : public RSExportPrimitiveType { 276 friend class RSExportType; 277 friend class RSExportElement; 278 private: 279 unsigned mNumElement; // number of element 280 281 RSExportVectorType(RSContext *Context, 282 const llvm::StringRef &Name, 283 DataType DT, 284 DataKind DK, 285 bool Normalized, 286 unsigned NumElement) 287 : RSExportPrimitiveType(Context, ExportClassVector, Name, 288 DT, DK, Normalized), 289 mNumElement(NumElement) { 290 return; 291 } 292 293 // @EVT was normalized by calling RSExportType::TypeExportable() before 294 // calling this. 295 static RSExportVectorType *Create(RSContext *Context, 296 const clang::ExtVectorType *EVT, 297 const llvm::StringRef &TypeName, 298 DataKind DK = DataKindUser, 299 bool Normalized = false); 300 301 static const char *VectorTypeNameStore[][3]; 302 303 virtual const llvm::Type *convertToLLVMType() const; 304 public: 305 static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT); 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, ExportClassMatrix, Name), 328 mDim(Dim) { 329 return; 330 } 331 332 virtual const llvm::Type *convertToLLVMType() const; 333 public: 334 // @RT was normalized by calling RSExportType::TypeExportable() before 335 // calling this. 336 static RSExportMatrixType *Create(RSContext *Context, 337 const clang::RecordType *RT, 338 const llvm::StringRef &TypeName, 339 unsigned Dim); 340 341 inline unsigned getDim() const { return mDim; } 342}; 343 344class RSExportConstantArrayType : public RSExportType { 345 friend class RSExportType; 346 private: 347 const RSExportType *mElementType; // Array element type 348 unsigned mSize; // Array size 349 350 RSExportConstantArrayType(RSContext *Context, 351 const RSExportType *ElementType, 352 unsigned Size) 353 : RSExportType(Context, 354 ExportClassConstantArray, 355 DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE), 356 mElementType(ElementType), 357 mSize(Size) { 358 return; 359 } 360 361 // @CAT was normalized by calling RSExportType::TypeExportable() before 362 // calling this. 363 static RSExportConstantArrayType *Create(RSContext *Context, 364 const clang::ConstantArrayType *CAT); 365 366 virtual const llvm::Type *convertToLLVMType() const; 367 public: 368 inline unsigned getSize() const { return mSize; } 369 inline const RSExportType *getElementType() const { return mElementType; } 370}; 371 372class RSExportRecordType : public RSExportType { 373 friend class RSExportType; 374 public: 375 class Field { 376 private: 377 const RSExportType *mType; 378 // Field name 379 std::string mName; 380 // Link to the struct that contain this field 381 const RSExportRecordType *mParent; 382 // Offset in the container 383 size_t mOffset; 384 385 public: 386 Field(const RSExportType *T, 387 const llvm::StringRef &Name, 388 const RSExportRecordType *Parent, 389 size_t Offset) 390 : mType(T), 391 mName(Name.data(), Name.size()), 392 mParent(Parent), 393 mOffset(Offset) { 394 return; 395 } 396 397 inline const RSExportRecordType *getParent() const { return mParent; } 398 inline const RSExportType *getType() const { return mType; } 399 inline const std::string &getName() const { return mName; } 400 inline size_t getOffsetInParent() const { return mOffset; } 401 }; 402 403 typedef std::list<const Field*>::const_iterator const_field_iterator; 404 405 inline const_field_iterator fields_begin() const { 406 return this->mFields.begin(); 407 } 408 inline const_field_iterator fields_end() const { 409 return this->mFields.end(); 410 } 411 412 private: 413 std::list<const Field*> mFields; 414 bool mIsPacked; 415 // Artificial export struct type is not exported by user (and thus it won't 416 // get reflected) 417 bool mIsArtificial; 418 size_t mAllocSize; 419 420 RSExportRecordType(RSContext *Context, 421 const llvm::StringRef &Name, 422 bool IsPacked, 423 bool IsArtificial, 424 size_t AllocSize) 425 : RSExportType(Context, ExportClassRecord, Name), 426 mIsPacked(IsPacked), 427 mIsArtificial(IsArtificial), 428 mAllocSize(AllocSize) { 429 return; 430 } 431 432 // @RT was normalized by calling RSExportType::TypeExportable() before calling 433 // this. 434 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 435 // this. 436 static RSExportRecordType *Create(RSContext *Context, 437 const clang::RecordType *RT, 438 const llvm::StringRef &TypeName, 439 bool mIsArtificial = false); 440 441 virtual const llvm::Type *convertToLLVMType() const; 442 public: 443 inline const std::list<const Field*>& getFields() const { return mFields; } 444 inline bool isPacked() const { return mIsPacked; } 445 inline bool isArtificial() const { return mIsArtificial; } 446 inline size_t getAllocSize() const { return mAllocSize; } 447 448 ~RSExportRecordType() { 449 for (std::list<const Field*>::iterator I = mFields.begin(), 450 E = mFields.end(); 451 I != E; 452 I++) 453 if (*I != NULL) 454 delete *I; 455 return; 456 } 457}; // RSExportRecordType 458 459} // namespace slang 460 461#endif // _SLANG_COMPILER_RS_EXPORT_TYPE_H 462