slang_rs_export_type.h revision a65ec168e41e3ee9c6e8ac04cde694bbbfc2590a
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#define ENUM_RS_DATA_TYPE(type, cname, bits) \ 155 DataType ## type, 156#include "RSDataTypeEnums.inc" 157#undef ENUM_RS_DATA_TYPE 158 159 DataTypeMax 160 } DataType; 161 162 // From graphics/java/android/renderscript/Element.java: Element.DataKind 163 typedef enum { 164 DataKindUnknown = -1 165#define ENUM_RS_DATA_KIND(kind) \ 166 , DataKind ## kind 167#include "RSDataKindEnums.inc" 168#undef ENUM_RS_DATA_KIND 169 } DataKind; 170 171 private: 172 // NOTE: 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 DataType mType; 178 DataKind mKind; 179 bool mNormalized; 180 181 typedef llvm::StringMap<DataType> RSObjectTypeMapTy; 182 static llvm::ManagedStatic<RSObjectTypeMapTy> RSObjectTypeMap; 183 184 static llvm::Type *RSObjectLLVMType; 185 186 static const size_t SizeOfDataTypeInBits[]; 187 // @T was normalized by calling RSExportType::TypeExportable() before calling 188 // this. 189 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 190 // this 191 static RSExportPrimitiveType *Create(RSContext *Context, 192 const clang::Type *T, 193 const llvm::StringRef &TypeName, 194 DataKind DK = DataKindUser, 195 bool Normalized = false); 196 197 protected: 198 // T is normalized by calling RSExportType::TypeExportable() before 199 // calling this 200 static bool IsPrimitiveType(const clang::Type *T); 201 202 static DataType GetDataType(const clang::Type *T); 203 204 RSExportPrimitiveType(RSContext *Context, 205 // for derived class to set their type class 206 ExportClass Class, 207 const llvm::StringRef &Name, 208 DataType DT, 209 DataKind DK, 210 bool Normalized) 211 : RSExportType(Context, Class, Name), 212 mType(DT), 213 mKind(DK), 214 mNormalized(Normalized) { 215 return; 216 } 217 218 virtual const llvm::Type *convertToLLVMType() const; 219 public: 220 // @T may not be normalized 221 static RSExportPrimitiveType *Create(RSContext *Context, 222 const clang::Type *T, 223 DataKind DK = DataKindUser); 224 225 static DataType GetRSObjectType(const llvm::StringRef &TypeName); 226 static DataType GetRSObjectType(const clang::Type *T); 227 228 static size_t GetSizeInBits(const RSExportPrimitiveType *EPT); 229 230 inline DataType getType() const { return mType; } 231 inline DataKind getKind() const { return mKind; } 232 inline bool isRSObjectType() const { 233 return ((mType >= DataTypeRSElement) && (mType < DataTypeMax)); 234 } 235 236 virtual bool equals(const RSExportable *E) const; 237}; // RSExportPrimitiveType 238 239 240class RSExportPointerType : public RSExportType { 241 friend class RSExportType; 242 friend class RSExportFunc; 243 private: 244 const RSExportType *mPointeeType; 245 246 RSExportPointerType(RSContext *Context, 247 const llvm::StringRef &Name, 248 const RSExportType *PointeeType) 249 : RSExportType(Context, ExportClassPointer, Name), 250 mPointeeType(PointeeType) { 251 return; 252 } 253 254 // @PT was normalized by calling RSExportType::TypeExportable() before calling 255 // this. 256 static RSExportPointerType *Create(RSContext *Context, 257 const clang::PointerType *PT, 258 const llvm::StringRef &TypeName); 259 260 virtual const llvm::Type *convertToLLVMType() const; 261 public: 262 static const clang::Type *IntegerType; 263 264 virtual void keep(); 265 266 inline const RSExportType *getPointeeType() const { return mPointeeType; } 267 268 virtual bool equals(const RSExportable *E) const; 269}; // RSExportPointerType 270 271 272class RSExportVectorType : public RSExportPrimitiveType { 273 friend class RSExportType; 274 friend class RSExportElement; 275 private: 276 unsigned mNumElement; // number of element 277 278 RSExportVectorType(RSContext *Context, 279 const llvm::StringRef &Name, 280 DataType DT, 281 DataKind DK, 282 bool Normalized, 283 unsigned NumElement) 284 : RSExportPrimitiveType(Context, ExportClassVector, Name, 285 DT, DK, Normalized), 286 mNumElement(NumElement) { 287 return; 288 } 289 290 // @EVT was normalized by calling RSExportType::TypeExportable() before 291 // calling this. 292 static RSExportVectorType *Create(RSContext *Context, 293 const clang::ExtVectorType *EVT, 294 const llvm::StringRef &TypeName, 295 DataKind DK = DataKindUser, 296 bool Normalized = false); 297 298 virtual const llvm::Type *convertToLLVMType() const; 299 public: 300 static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT); 301 302 inline unsigned getNumElement() const { return mNumElement; } 303 304 virtual bool equals(const RSExportable *E) const; 305}; 306 307// Only *square* *float* matrix is supported by now. 308// 309// struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following 310// form *exactly*: 311// typedef struct { 312// float m[{NxN}]; 313// } rs_matrixNxN; 314// 315// where mDim will be N. 316class RSExportMatrixType : public RSExportType { 317 friend class RSExportType; 318 private: 319 unsigned mDim; // dimension 320 321 RSExportMatrixType(RSContext *Context, 322 const llvm::StringRef &Name, 323 unsigned Dim) 324 : RSExportType(Context, ExportClassMatrix, Name), 325 mDim(Dim) { 326 return; 327 } 328 329 virtual const llvm::Type *convertToLLVMType() const; 330 public: 331 // @RT was normalized by calling RSExportType::TypeExportable() before 332 // calling this. 333 static RSExportMatrixType *Create(RSContext *Context, 334 const clang::RecordType *RT, 335 const llvm::StringRef &TypeName, 336 unsigned Dim); 337 338 inline unsigned getDim() const { return mDim; } 339 340 virtual bool equals(const RSExportable *E) const; 341}; 342 343class RSExportConstantArrayType : public RSExportType { 344 friend class RSExportType; 345 private: 346 const RSExportType *mElementType; // Array element type 347 unsigned mSize; // Array size 348 349 RSExportConstantArrayType(RSContext *Context, 350 const RSExportType *ElementType, 351 unsigned Size) 352 : RSExportType(Context, 353 ExportClassConstantArray, 354 DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE), 355 mElementType(ElementType), 356 mSize(Size) { 357 return; 358 } 359 360 // @CAT was normalized by calling RSExportType::TypeExportable() before 361 // calling this. 362 static RSExportConstantArrayType *Create(RSContext *Context, 363 const clang::ConstantArrayType *CAT); 364 365 virtual const llvm::Type *convertToLLVMType() const; 366 public: 367 inline unsigned getSize() const { return mSize; } 368 inline const RSExportType *getElementType() const { return mElementType; } 369 370 virtual void keep(); 371 virtual bool equals(const RSExportable *E) const; 372}; 373 374class RSExportRecordType : public RSExportType { 375 friend class RSExportType; 376 public: 377 class Field { 378 private: 379 const RSExportType *mType; 380 // Field name 381 std::string mName; 382 // Link to the struct that contain this field 383 const RSExportRecordType *mParent; 384 // Offset in the container 385 size_t mOffset; 386 387 public: 388 Field(const RSExportType *T, 389 const llvm::StringRef &Name, 390 const RSExportRecordType *Parent, 391 size_t Offset) 392 : mType(T), 393 mName(Name.data(), Name.size()), 394 mParent(Parent), 395 mOffset(Offset) { 396 return; 397 } 398 399 inline const RSExportRecordType *getParent() const { return mParent; } 400 inline const RSExportType *getType() const { return mType; } 401 inline const std::string &getName() const { return mName; } 402 inline size_t getOffsetInParent() const { return mOffset; } 403 }; 404 405 typedef std::list<const Field*>::const_iterator const_field_iterator; 406 407 inline const_field_iterator fields_begin() const { 408 return this->mFields.begin(); 409 } 410 inline const_field_iterator fields_end() const { 411 return this->mFields.end(); 412 } 413 414 private: 415 std::list<const Field*> mFields; 416 bool mIsPacked; 417 // Artificial export struct type is not exported by user (and thus it won't 418 // get reflected) 419 bool mIsArtificial; 420 size_t mAllocSize; 421 422 RSExportRecordType(RSContext *Context, 423 const llvm::StringRef &Name, 424 bool IsPacked, 425 bool IsArtificial, 426 size_t AllocSize) 427 : RSExportType(Context, ExportClassRecord, Name), 428 mIsPacked(IsPacked), 429 mIsArtificial(IsArtificial), 430 mAllocSize(AllocSize) { 431 return; 432 } 433 434 // @RT was normalized by calling RSExportType::TypeExportable() before calling 435 // this. 436 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 437 // this. 438 static RSExportRecordType *Create(RSContext *Context, 439 const clang::RecordType *RT, 440 const llvm::StringRef &TypeName, 441 bool mIsArtificial = false); 442 443 virtual const llvm::Type *convertToLLVMType() const; 444 public: 445 inline const std::list<const Field*>& getFields() const { return mFields; } 446 inline bool isPacked() const { return mIsPacked; } 447 inline bool isArtificial() const { return mIsArtificial; } 448 inline size_t getAllocSize() const { return mAllocSize; } 449 450 virtual void keep(); 451 virtual bool equals(const RSExportable *E) const; 452 453 ~RSExportRecordType() { 454 for (std::list<const Field*>::iterator I = mFields.begin(), 455 E = mFields.end(); 456 I != E; 457 I++) 458 if (*I != NULL) 459 delete *I; 460 return; 461 } 462}; // RSExportRecordType 463 464} // namespace slang 465 466#endif // _SLANG_COMPILER_RS_EXPORT_TYPE_H 467