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