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