slang_rs_export_type.h revision d6f9fedf1b32c27c0bcaddd13d7b741ab5ad74b8
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 // Record type may recursively referece its type definition. We need a 114 // temporary type setup before the type construction gets done. 115 inline void setAbstractLLVMType(const llvm::Type *LLVMType) const { 116 mLLVMType = LLVMType; 117 } 118 119 virtual ~RSExportType() {} 120 public: 121 static bool NormalizeType(const clang::Type *&T, llvm::StringRef &TypeName); 122 // @T may not be normalized 123 static RSExportType *Create(RSContext *Context, const clang::Type *T); 124 static RSExportType *CreateFromDecl(RSContext *Context, 125 const clang::VarDecl *VD); 126 127 static const clang::Type *GetTypeOfDecl(const clang::DeclaratorDecl *DD); 128 129 inline ExportClass getClass() const { return mClass; } 130 131 inline const llvm::Type *getLLVMType() const { 132 if (mLLVMType == NULL) 133 mLLVMType = convertToLLVMType(); 134 return mLLVMType; 135 } 136 137 // Return the number of bits necessary to hold the specified RSExportType 138 static size_t GetTypeStoreSize(const RSExportType *ET); 139 140 // The size of allocation of specified RSExportType (alignment considered) 141 static size_t GetTypeAllocSize(const RSExportType *ET); 142 static unsigned char GetTypeAlignment(const RSExportType *ET); 143 144 inline const std::string &getName() const { return mName; } 145 146 virtual bool keep(); 147 virtual bool equals(const RSExportable *E) const; 148}; // RSExportType 149 150// Primitive types 151class RSExportPrimitiveType : public RSExportType { 152 friend class RSExportType; 153 friend class RSExportElement; 154 public: 155 // From graphics/java/android/renderscript/Element.java: Element.DataType 156 typedef enum { 157 DataTypeUnknown = -1, 158 159#define ENUM_RS_DATA_TYPE(type, cname, bits) \ 160 DataType ## type, 161#include "RSDataTypeEnums.inc" 162 163 DataTypeMax 164 } DataType; 165 166 // From graphics/java/android/renderscript/Element.java: Element.DataKind 167 typedef enum { 168 DataKindUnknown = -1 169#define ENUM_RS_DATA_KIND(kind) \ 170 , DataKind ## kind 171#include "RSDataKindEnums.inc" 172 } DataKind; 173 174 private: 175 // NOTE: There's no any instance of RSExportPrimitiveType which mType 176 // is of the value DataTypeRSMatrix*. DataTypeRSMatrix* enumeration here is 177 // only for RSExportPrimitiveType::GetRSObjectType to *recognize* the struct 178 // rs_matrix{2x2, 3x3, 4x4}. These matrix type are represented as 179 // RSExportMatrixType. 180 DataType mType; 181 DataKind mKind; 182 bool mNormalized; 183 184 typedef llvm::StringMap<DataType> RSObjectTypeMapTy; 185 static llvm::ManagedStatic<RSObjectTypeMapTy> RSObjectTypeMap; 186 187 static llvm::Type *RSObjectLLVMType; 188 189 static const size_t SizeOfDataTypeInBits[]; 190 // @T was normalized by calling RSExportType::TypeExportable() before calling 191 // this. 192 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 193 // this 194 static RSExportPrimitiveType *Create(RSContext *Context, 195 const clang::Type *T, 196 const llvm::StringRef &TypeName, 197 DataKind DK = DataKindUser, 198 bool Normalized = false); 199 200 protected: 201 // T is normalized by calling RSExportType::TypeExportable() before 202 // calling this 203 static bool IsPrimitiveType(const clang::Type *T); 204 205 static DataType GetDataType(const clang::Type *T); 206 207 RSExportPrimitiveType(RSContext *Context, 208 // for derived class to set their type class 209 ExportClass Class, 210 const llvm::StringRef &Name, 211 DataType DT, 212 DataKind DK, 213 bool Normalized) 214 : RSExportType(Context, Class, Name), 215 mType(DT), 216 mKind(DK), 217 mNormalized(Normalized) { 218 return; 219 } 220 221 virtual const llvm::Type *convertToLLVMType() const; 222 public: 223 // @T may not be normalized 224 static RSExportPrimitiveType *Create(RSContext *Context, 225 const clang::Type *T, 226 DataKind DK = DataKindUser); 227 228 static DataType GetRSObjectType(const llvm::StringRef &TypeName); 229 static DataType GetRSObjectType(const clang::Type *T); 230 231 static size_t GetSizeInBits(const RSExportPrimitiveType *EPT); 232 233 inline DataType getType() const { return mType; } 234 inline DataKind getKind() const { return mKind; } 235 inline bool isRSObjectType() const { 236 return ((mType >= DataTypeRSElement) && (mType < DataTypeMax)); 237 } 238 239 virtual bool equals(const RSExportable *E) const; 240}; // RSExportPrimitiveType 241 242 243class RSExportPointerType : public RSExportType { 244 friend class RSExportType; 245 friend class RSExportFunc; 246 private: 247 const RSExportType *mPointeeType; 248 249 RSExportPointerType(RSContext *Context, 250 const llvm::StringRef &Name, 251 const RSExportType *PointeeType) 252 : RSExportType(Context, ExportClassPointer, Name), 253 mPointeeType(PointeeType) { 254 return; 255 } 256 257 // @PT was normalized by calling RSExportType::TypeExportable() before calling 258 // this. 259 static RSExportPointerType *Create(RSContext *Context, 260 const clang::PointerType *PT, 261 const llvm::StringRef &TypeName); 262 263 virtual const llvm::Type *convertToLLVMType() const; 264 public: 265 static const clang::Type *IntegerType; 266 267 virtual bool keep(); 268 269 inline const RSExportType *getPointeeType() const { return mPointeeType; } 270 271 virtual bool equals(const RSExportable *E) const; 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 virtual const llvm::Type *convertToLLVMType() const; 302 public: 303 static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT); 304 305 inline unsigned getNumElement() const { return mNumElement; } 306 307 virtual bool equals(const RSExportable *E) const; 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 virtual bool equals(const RSExportable *E) const; 344}; 345 346class RSExportConstantArrayType : public RSExportType { 347 friend class RSExportType; 348 private: 349 const RSExportType *mElementType; // Array element type 350 unsigned mSize; // Array size 351 352 RSExportConstantArrayType(RSContext *Context, 353 const RSExportType *ElementType, 354 unsigned Size) 355 : RSExportType(Context, 356 ExportClassConstantArray, 357 DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE), 358 mElementType(ElementType), 359 mSize(Size) { 360 return; 361 } 362 363 // @CAT was normalized by calling RSExportType::TypeExportable() before 364 // calling this. 365 static RSExportConstantArrayType *Create(RSContext *Context, 366 const clang::ConstantArrayType *CAT); 367 368 virtual const llvm::Type *convertToLLVMType() const; 369 public: 370 inline unsigned getSize() const { return mSize; } 371 inline const RSExportType *getElementType() const { return mElementType; } 372 373 virtual bool keep(); 374 virtual bool equals(const RSExportable *E) const; 375}; 376 377class RSExportRecordType : public RSExportType { 378 friend class RSExportType; 379 public: 380 class Field { 381 private: 382 const RSExportType *mType; 383 // Field name 384 std::string mName; 385 // Link to the struct that contain this field 386 const RSExportRecordType *mParent; 387 // Offset in the container 388 size_t mOffset; 389 390 public: 391 Field(const RSExportType *T, 392 const llvm::StringRef &Name, 393 const RSExportRecordType *Parent, 394 size_t Offset) 395 : mType(T), 396 mName(Name.data(), Name.size()), 397 mParent(Parent), 398 mOffset(Offset) { 399 return; 400 } 401 402 inline const RSExportRecordType *getParent() const { return mParent; } 403 inline const RSExportType *getType() const { return mType; } 404 inline const std::string &getName() const { return mName; } 405 inline size_t getOffsetInParent() const { return mOffset; } 406 }; 407 408 typedef std::list<const Field*>::const_iterator const_field_iterator; 409 410 inline const_field_iterator fields_begin() const { 411 return this->mFields.begin(); 412 } 413 inline const_field_iterator fields_end() const { 414 return this->mFields.end(); 415 } 416 417 private: 418 std::list<const Field*> mFields; 419 bool mIsPacked; 420 // Artificial export struct type is not exported by user (and thus it won't 421 // get reflected) 422 bool mIsArtificial; 423 size_t mAllocSize; 424 425 RSExportRecordType(RSContext *Context, 426 const llvm::StringRef &Name, 427 bool IsPacked, 428 bool IsArtificial, 429 size_t AllocSize) 430 : RSExportType(Context, ExportClassRecord, Name), 431 mIsPacked(IsPacked), 432 mIsArtificial(IsArtificial), 433 mAllocSize(AllocSize) { 434 return; 435 } 436 437 // @RT was normalized by calling RSExportType::TypeExportable() before calling 438 // this. 439 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 440 // this. 441 static RSExportRecordType *Create(RSContext *Context, 442 const clang::RecordType *RT, 443 const llvm::StringRef &TypeName, 444 bool mIsArtificial = false); 445 446 virtual const llvm::Type *convertToLLVMType() const; 447 public: 448 inline const std::list<const Field*>& getFields() const { return mFields; } 449 inline bool isPacked() const { return mIsPacked; } 450 inline bool isArtificial() const { return mIsArtificial; } 451 inline size_t getAllocSize() const { return mAllocSize; } 452 453 virtual bool keep(); 454 virtual bool equals(const RSExportable *E) const; 455 456 ~RSExportRecordType() { 457 for (std::list<const Field*>::iterator I = mFields.begin(), 458 E = mFields.end(); 459 I != E; 460 I++) 461 if (*I != NULL) 462 delete *I; 463 return; 464 } 465}; // RSExportRecordType 466 467} // namespace slang 468 469#endif // _SLANG_COMPILER_RS_EXPORT_TYPE_H 470