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